Ever Tried Turning Your Express Server Into a Proxy Wizard?

Seamlessly Forwarding Requests with Express HTTP Proxy in Node.js

Ever Tried Turning Your Express Server Into a Proxy Wizard?

Let’s talk about something pretty common in the world of web development: building web applications where you might need to forward requests from your server to another server. Sounds fancy, right? Well, it’s not as complex as it sounds, thanks to our good friend, the proxy server. And, if you’re using Node.js with Express.js, setting up a proxy server is actually quite a breeze. So, here’s a laid-back guide on making this work using Express HTTP Proxy.

First things first, you need to get the express-http-proxy package. This package is super handy because it offers a simple way to proxy requests to another host and then return the response back to where it came from. Handy, right? You can install it using this nifty command in your terminal:

npm install express-http-proxy --save

Once the package is installed, it’s all about setting up your Express server to use the proxy middleware. Here’s a basic example to get you started:

const express = require('express');
const proxy = require('express-http-proxy');

const app = express();
const PORT = 3000;
const HOST = 'localhost';
const TARGET_HOST = 'http://example.com';

app.use('/proxy', proxy(TARGET_HOST));

app.listen(PORT, HOST, () => {
  console.log(`Server is running on http://${HOST}:${PORT}`);
});

With this setup, any request to http://localhost:3000/proxy is going to be forwarded to http://example.com. Pretty smooth, right?

Now, sometimes you might want to get a bit fancy with your proxy requests. Maybe you need to tweak the request method or add some custom headers. That’s where proxyReqOptDecorator comes in handy. This option lets you modify the proxy request options before they go out.

app.use('/proxy', proxy(TARGET_HOST, {
  proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
    proxyReqOpts.headers['Content-Type'] = 'text/html';
    proxyReqOpts.method = 'GET';
    return proxyReqOpts;
  }
}));

With this, you’re updating the Content-Type header and making sure the request method is set to GET for all proxy requests.

There’s another hiccup you might run into—handling multipart form data, like when you’re uploading files. Sadly, express-http-proxy doesn’t natively support multipart form data. If you need this feature, using http-proxy-middleware is a better call:

const { createProxyMiddleware } = require('http-proxy-middleware');

app.use('/proxy', createProxyMiddleware({
  target: TARGET_HOST,
  changeOrigin: true,
  pathRewrite: { '^/proxy': '' },
}));

This setup ensures that the multipart form data is properly forwarded to the target server.

Now, things can get a bit tricky with errors and timeouts. You don’t want your server hanging around forever waiting for a response. Setting a timeout is crucial:

app.use('/proxy', proxy(TARGET_HOST, {
  timeout: 10000 // 10 seconds
}));

And it’s always good to have a setup to catch and handle errors effectively:

app.use('/proxy', proxy(TARGET_HOST, {
  onProxyRes: function(proxyRes, req, res) {
    if (proxyRes.statusCode >= 400) {
      console.error(`Proxy error: ${proxyRes.statusCode}`);
    }
  },
  onProxyReqError: function(err, req, res) {
    console.error(`Proxy request error: ${err}`);
  },
  onError: function(err, req, res) {
    console.error(`Proxy error: ${err}`);
  },
}));

Sometimes, you might need to deal with HTTPS servers. No sweat. The express-http-proxy package can handle it if the target URL starts with https://, or you can set the https option to true:

app.use('/proxy', proxy('https://example.com', {
  https: true
}));

If you’re working with non-standard certificate chains or self-signed certificates, you can tweak the proxy request options with proxyReqOptDecorator:

app.use('/proxy', proxy('https://example.com', {
  proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
    proxyReqOpts.ca = [caCert, intermediaryCert];
    proxyReqOpts.rejectUnauthorized = false;
    return proxyReqOpts;
  }
}));

Let’s put everything together into a complete example. This Express server will proxy requests, handle errors, and customize requests:

const express = require('express');
const proxy = require('express-http-proxy');

const app = express();
const PORT = 3000;
const HOST = 'localhost';
const TARGET_HOST = 'http://example.com';

app.use('/proxy', proxy(TARGET_HOST, {
  proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
    proxyReqOpts.headers['Content-Type'] = 'text/html';
    return proxyReqOpts;
  },
  onProxyRes: function(proxyRes, req, res) {
    if (proxyRes.statusCode >= 400) {
      console.error(`Proxy error: ${proxyRes.statusCode}`);
    }
  },
  onProxyReqError: function(err, req, res) {
    console.error(`Proxy request error: ${err}`);
  },
  onError: function(err, req, res) {
    console.error(`Proxy error: ${err}`);
  },
  timeout: 10000 // 10 seconds
}));

app.listen(PORT, HOST, () => {
  console.log(`Server is running on http://${HOST}:${PORT}`);
});

So, there you have it—a smooth, clean way to forward requests using Express HTTP Proxy. Whether you’re just dealing with some simple GET requests or wrangling more complex multipart form data, with the right setup, tooling, and configurations, proxying requests becomes a walk in the park. It’s all about making life easier for the developer, and this way, you’ve got a reliable, efficient proxy solution at your fingertips.