14

I need to solve CORS on a third party service, so I want to build a proxy to add the header "Access-Control-Allow-Origin: *".

Why is this code is not adding the header?

httpProxy = require('http-proxy');

var URL = 'https://third_party_server...';

httpProxy.createServer({ secure: false, target: URL }, function (req, res, proxy) {

  res.oldWriteHead = res.writeHead;
  res.writeHead = function(statusCode, headers) {
    /* add logic to change headers here */

    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');

    res.oldWriteHead(statusCode, headers);
  }

  proxy.proxyRequest(req, res, { secure: false, target: URL });

}).listen(8000);
Joe Beuckman
  • 2,264
  • 2
  • 24
  • 63

3 Answers3

18

You have the proxyRes event available.

So something like that should work:

proxy.on('proxyRes', function(proxyRes, req, res) {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
});

Full working example (well, when I say full I do not mean this is a secure-failsafe-real proxy, but it does the job for your question):

var http = require('http'),
    httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});
var server = http.createServer(function(req, res) {
    proxy.web(req, res, {
        target: 'https://third_party_server...',
        secure: false,
        ws: false,
        prependPath: false,
        ignorePath: false,
    });
});
console.log("listening on port 8000")
server.listen(8000);

// Listen for the `error` event on `proxy`.
// as we will generate a big bunch of errors
proxy.on('error', function (err, req, res) {
  console.log(err)
  res.writeHead(500, {
    'Content-Type': 'text/plain'
  });
  res.end("Oops");
});

proxy.on('proxyRes', function(proxyRes, req, res) {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
});
regilero
  • 29,806
  • 6
  • 60
  • 99
  • So, you've to set the headers in `res` (you can either set in `proxyRes` event or `proxyReq` event). Not in `proxyRes` or `proxyReq` parameters on those events. – gihanchanuka Sep 17 '18 at 09:16
  • 1
    Note that this doesn't seem to work if the target has already set Access-Control-Allow-Origin, since your custom value will be overwritten when the proxy writes to `res`. – Michael Gummelt Feb 13 '20 at 18:56
  • It gives me the error "has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status." – Deepak Bandela Mar 23 '20 at 17:58
  • Well, this answer is from 2013, things may have changed a bit. But I think your main problem here is that you do not have a 200 Ok response to your OPTION http query `It does not have HTTP ok status` and that's another problem. – regilero Mar 25 '20 at 08:06
6

For those coming across this in the future, here's an updated answer. Combining Michael Gummelt's comment and Nicholas Mitrousis' answer, any headers set on res will be overridden if the response from upstream in proxyRes has the same header set. So to answer the original question:

proxy.on('proxyRes', function(proxyRes, req, res) {
 proxyRes.headers["access-control-allow-origin"] = "*";
 proxyRes.headers["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS";
}
elhil
  • 101
  • 1
  • 5
1

Even though this question is old, it's the first result from Google and the current answer isn't terribly informative.

The first point of note is that proxyRes does not have a setHeader() method. Additionally, if you try to override a proxyRes header with res.setHeader('Header-to-Override', 'new value'), it won't work (I assume due to headers being copied from proxyRes to res after this event is fired.

It appears we're not the only ones with this issue: https://github.com/http-party/node-http-proxy/issues/1401

Here's my solution for adding an additional cache-control header in my situation:

proxy.on('proxyRes', function(proxyRes, req, res) {
  if (proxyRes.headers['cache-control']) {
    proxyRes.headers['cache-control'] += ', proxy-revalidate'
  } else {
    proxyRes.headers['cache-control'] = 'proxy-revalidate'
  }
})