Node-http-proxy: How to solve the cors prolblem

Created on 29 Aug 2015  路  4Comments  路  Source: http-party/node-http-proxy

I want to request data from port 8080, It returns "XMLHttpRequest...Access-Control-Allow-Origin".
So I use node-http-proxy on port 8000 whick swithc to 8080, but I meet the same problem of cors on 8000.
This is my code, Looking forward to geting help from you, thanks~

var http = require('http'),
    httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});

proxy.on('proxyReq', function(proxyReq, req, res, options) {
    proxyReq.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");  
     proxyReq.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
     proxyReq.setHeader("X-Powered-By",' 3.2.1') ;
     proxyReq.setHeader("Content-Type", "application/json;charset=utf-8");  
});

var server = http.createServer(function(req, res) {
  proxy.web(req, res, { target: 'http://127.0.0.1:8080' });
});

console.log("listening on port 8000")
server.listen(8000);

Most helpful comment

For those who stumble upon this ticket, here's how I solved it:

const url = require('url');

// .. your proxyHttp conf

const allowedOrigins = ['www.mydomain.com', 'mydomain.com'];

proxyHttp.on('proxyRes', (proxyRes, req, res) => {
  let allowedOrigin = false;
  if (req.headers.origin) {
    const originHostName = url.parse(req.headers.origin).hostname;
    if (originHostName && allowedOrigins.some(o => o === originHostName)) {
      res.setHeader('access-control-allow-origin', req.headers.origin);
      res.setHeader('access-control-allow-credentials', 'true');
      allowedOrigin = true;
    }
  }

  if (req.headers['access-control-request-method']) {
    res.setHeader('access-control-allow-methods', req.headers['access-control-request-method']);
  }

  if (req.headers['access-control-request-headers']) {
    res.setHeader('access-control-allow-headers', req.headers['access-control-request-headers']);
  }

  if (allowedOrigin) {
    res.setHeader('access-control-max-age', 60 * 60 * 24 * 30);
    if (req.method === 'OPTIONS') {
      res.send(200);
      res.end();
    }
  }
});

All 4 comments

Having the same problem.

Having a proxy is necessary for the core of my application which proxies an external site. However certain resources (especially fonts) are always blocked by ACAO. I'm not sure how to compensate for this using node-http-proxy but I know it can be done.

For example using the proxy that ships with browser-sync, proxies external sites perfectly fine with no ACAO problems.

For those who stumble upon this ticket, here's how I solved it:

const url = require('url');

// .. your proxyHttp conf

const allowedOrigins = ['www.mydomain.com', 'mydomain.com'];

proxyHttp.on('proxyRes', (proxyRes, req, res) => {
  let allowedOrigin = false;
  if (req.headers.origin) {
    const originHostName = url.parse(req.headers.origin).hostname;
    if (originHostName && allowedOrigins.some(o => o === originHostName)) {
      res.setHeader('access-control-allow-origin', req.headers.origin);
      res.setHeader('access-control-allow-credentials', 'true');
      allowedOrigin = true;
    }
  }

  if (req.headers['access-control-request-method']) {
    res.setHeader('access-control-allow-methods', req.headers['access-control-request-method']);
  }

  if (req.headers['access-control-request-headers']) {
    res.setHeader('access-control-allow-headers', req.headers['access-control-request-headers']);
  }

  if (allowedOrigin) {
    res.setHeader('access-control-max-age', 60 * 60 * 24 * 30);
    if (req.method === 'OPTIONS') {
      res.send(200);
      res.end();
    }
  }
});

I was unable to do this in proxyHttp.on('proxyRes') as it gives me an error about Can't set headers after they are sent, but I solved it by putting the above code into a middleware layer instead.

One more thing: in modern versions of node res.send(200) needs to be res.statusCode = 200 or res.writeHead(200);.

This solution don't overwrite the original CORS headers sent by an api behind this proxy. (Because http-proxy will copy headers after this event).

You can remove CORS headers using this piece of code:

proxy.on('proxyRes', (proxyRes, req, res) => {
    proxyRes.headers = Object.keys(proxyRes.headers)
        .filter(h => (!h.toLowerCase().startsWith('access-control-') && !h.toLowerCase().startsWith('vary')))
        .reduce((all, h) => ({ ...all, [h]: proxyRes.headers[h] }), {});
});

On my side, I use the CORS middleware (https://www.npmjs.com/package/cors) to define my cors, you can use it like that (clean original headers if needed):

proxy.on('proxyRes', (proxyRes, req, res) => {
    cors(/* CORS OPTIONS */)(req, res, () => { });
});

I hope it will help 馃榾

Was this page helpful?
0 / 5 - 0 ratings

Related issues

robertjchristian picture robertjchristian  路  6Comments

damianchojna picture damianchojna  路  5Comments

karthikus picture karthikus  路  3Comments

martindale picture martindale  路  6Comments

jsmylnycky picture jsmylnycky  路  3Comments