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

Alternatives to http-proxy #1687

Open
paulrutter opened this issue Nov 8, 2024 · 3 comments
Open

Alternatives to http-proxy #1687

paulrutter opened this issue Nov 8, 2024 · 3 comments

Comments

@paulrutter
Copy link

paulrutter commented Nov 8, 2024

I've been using this module for a long time for http proxying, but since it's no longer maintained i was looking into alternatives.
For what it's worth, sharing my findings here.

Using node basic modules

My usecase: i have a expressjs app for which i want to proxy all requests to a Node process running on the same machine, on a different port. This code snippet shows how to proxy request/response including error handling.

const stream = require('stream');
const util = require('util');
const pipeline = util.promisify(stream.pipeline);

// proxyPort, req and res are passed here
// proxyPort: 5000
// req: incoming expressjs request
// res: incoming expressjs response

// custom agent if needed
const proxyAgent = new http.Agent({
  keepAlive: global.PROXY_CONFIG.useKeepAlive,
  maxSockets: global.PROXY_CONFIG.maxSockets
});

// copy over url, method and headers here
const requestOptions = {
  hostname: "localhost",
  port: proxyPort,
  path: req.url,
  method: req.method,
  agent: proxyAgent ,
  headers: req.headers
};

// create the proxy request 
const proxyReq = http.request(requestOptions, async (proxyRes) => {
  // Proxy response headers
  for (const headerName of Object.keys(proxyRes.headers)) {
    res.setHeader(headerName, proxyRes.headers[headerName]);
  }

  // Proxy response status code and message
  res.statusCode = proxyRes.statusCode;
  res.statusMessage = proxyRes.statusMessage;

  // send the response body of the proxied response to the origin response 
  try {
    await pipeline(proxyRes, res);
  } catch (err) {
    // add error handling here or log it at least
   res.send(500).end();
  } finally {
    // proxy is done here, log it?
  }
});

// Proxy the request body
try {
  await pipeline(req, proxyReq);
} catch (error) {
  // add error handling here or log it at least
  res.send(500).end();
} finally {
    // The request body is fully proxied here, if you want to do anything with this information
}

This snippet doesn't offer everything this module offers, but it's easily extendable to add features like adding/removing headers from the request or response. It's all plain node code, no additional module involved.

Other proxy modules or ways to do it

I hope this is helpful to others moving away from http-proxy.

@med8bra
Copy link

med8bra commented Nov 8, 2024

Thanks @paulrutter for this snippet, I was looking into migrating some old code too, and I came up with this using fetch API

async function handler(req: Request): Promise<Response> {
  const parsedUrl = new URL(req.url);
  // transform request
  parsedUrl.host = API_HOST;

  // add forwarded headers
  req.headers.append("x-forwarded-for", req.headers.get("host") ?? DEFAULT_HOST);

  // fetch should handle pipeing ReadStream/WriteStream
  return fetch(new Request(parsedUrl, req));
}

It's pretty simple, but I believe its extendable too to add extra pre/post processing if needed. Currently I'm using this only for dev.

@paulrutter
Copy link
Author

paulrutter commented Nov 8, 2024

@med8bra thanks, that seems pretty easy as well. It doesn't pipe the proxied response (headers, statusCode, body) though, but that could be added probably.

@paulrutter
Copy link
Author

Another thing to handle in my code snippet would be request timeout and set-cookie headers, which would need to be rewritten (if cookies are relevant to the proxy). Http-proxy does both as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants