Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a proxy server example for testing undici fetch. #3508

Open
sonamoman opened this issue Aug 26, 2024 · 2 comments
Open

Add a proxy server example for testing undici fetch. #3508

sonamoman opened this issue Aug 26, 2024 · 2 comments
Labels
Docs Changes related to the documentation good first issue Good for newcomers

Comments

@sonamoman
Copy link

sonamoman commented Aug 26, 2024

This would solve...

Hard to find an example of a proxy that works with undici fetch. Tried 3 different proxy servers in Node.js which all work with axios for example but not with undici fetch.
Would be very helpful to add a simple proxy server example written in Node.js to test undici fetch with.

The implementation should look like...

A small code block in the README.md like the following
Simple proxy in Node.js to test undici fetch with:

import * as http from 'http';
import { createProxy } from 'proxy';

const PORT = 8000;
const server = createProxy(http.createServer());

server.on('request', (req, res) => {
  console.log(`Incoming request to ${req.url}`);
});
server.listen(PORT, () => {
  console.log('Proxy server listening on port', PORT);
});

Additional context

I want to migrate from axios to fetch (Windows 11, Node.js version 20.17.0) but i've tried 3 different proxies which all work (passing through the proxy and getting a response) with axios (or postman) but none with undici (version 6.19.8) fetch. Request to proxy1.js and proxy2.js never resolves or rejects while request to proxy3.js bypasses proxy completely and gets a response.

Undici fetch test where proxy runs on http://127.0.0.1:8000 and http://127.0.0.1:4003/api/a1 is an endpoint in mockoon which returns a simple json response.

import { ProxyAgent, fetch } from "undici";

(async () => {
    try {
        const client = new ProxyAgent('http://127.0.0.1:8000');
        const response = await fetch("http://127.0.0.1:4003/api/a1", {
            dispatcher: client,
            method: "GET"
        });
        const data = await response.json();
        console.log('Response data:', data);
    } catch (e) {
        console.log(e);
    }
})();

proxy1.js

import http from "http";
import httpProxy from "http-proxy";
import url from "url";

const PORT = 8000;
const proxy = httpProxy.createProxyServer({});

const server = http.createServer((req, res) => {
  console.log(`Incoming request to ${req.url}`);

  const parsedUrl = url.parse(req.url, true);
  const target = `${parsedUrl.protocol}//${parsedUrl.host}`; 
  proxy.web(req, res, { target });
});

server.listen(PORT, () => {
  console.log('Proxy server listening on port', PORT);
});

proxy2.js

import http from "http";
import request from "request";

const PORT = 8000;

http.createServer(function (req, res) {
  console.log(`Incoming request to ${req.url}`);
  req.pipe(request(req.url)).pipe(res);
}).listen(PORT);

proxy3.js

import * as http from 'http';
import { createProxy } from 'proxy';

const PORT = 8000;
const server = createProxy(http.createServer());

server.on('request', (req, res) => {
  console.log(`Incoming request to ${req.url}`);
});
server.listen(PORT, () => {
  console.log('Proxy server listening on port', PORT);
});

Axios example which works with all 3 proxies:

import axios from "axios";

(async () => {
  try {
      const response = await axios.get('http://127.0.0.1:4003/api/a1', {
        proxy: {
          protocol: "http",
          host: '127.0.0.1',
          port: 8000,
        }
      });
      console.log('Response data:', response.data);
  } catch (e) {
    console.log(error);
  }
})();
@sonamoman sonamoman added the enhancement New feature or request label Aug 26, 2024
@metcoder95
Copy link
Member

This is an example of a server proxy with proxy

import * as http from 'node:http'
import { once } from 'node:events'
import { createProxy } from 'proxy'

import { ProxyAgent } from './index.js'

const proxyServer = createProxy(http.createServer())
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' })
  res.end('okay')
})

// proxyServer.on('request', (req, res) => {
//   console.log(`Incoming request to ${req.url}`)
// })

console.log('Listening...')
await once(proxyServer.listen(0), 'listening')
await once(server.listen(0), 'listening')

const { port: proxyPort } = proxyServer.address()
const { port } = server.address()

console.log(`Proxy listening on port ${proxyPort}`)
console.log(`Server listening on port ${port}`)
;(async () => {
  try {
    const agent = new ProxyAgent(`http://localhost:${proxyPort}`)
    const response = await fetch(`http://localhost:${port}`, {
      dispatcher: agent,
      method: 'GET'
    })
    const data = await response.text()
    console.log('Response data:', data)
  } catch (e) {
    console.log(e)
  }
})()

It is important to remark that undici does a tunneling to the proxy server using CONNECT.

Would you like to open a PR for sending a documentation update?

@metcoder95 metcoder95 added good first issue Good for newcomers Docs Changes related to the documentation and removed enhancement New feature or request labels Aug 28, 2024
@sonamoman
Copy link
Author

Sure, will open a PR real soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Docs Changes related to the documentation good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

5 participants
@metcoder95 @sonamoman and others