Sathish
Sathish

Reputation: 346

"ERR_HTTP_HEADERS_SENT:Cannot set headers after they are sent to the client" while http-proxy-middleware combined with https-proxy-agent

The Node (Express JS) middle-ware uses http-proxy-middleware to proxy requests and responses between client (probably Chrome browser) and jira server. It also uses https-proxy-agent to add proxy agent as the host server requires proxy to access Jira APIs.

The request headers have been updated using onProxyReq. It completely works fine in localhost as it doesn't require proxy agent but it throws an error "ERR_HTTP_HEADERS_SENT:Cannot set headers after they are sent to the client" in server.

The code implementation is below

var express = require("express");
var proxy = require("http-proxy-middleware");
var HttpsProxyAgent = require("https-proxy-agent");

var router = express.Router();
// proxy to connect open network
var proxyServer = "http://myproxy.url:8080";

router.use(
  "/jira",
  proxy({
    target: "https://myJira.url",
    agent: new HttpsProxyAgent(proxyServer),
    secure: false,
    changeOrigin: true,
    onProxyReq: function(proxyReq, req, res) {
      proxyReq.setHeader("user-agent", "XXX");
      proxyReq.setHeader("X-Atlassian-Token", "nocheck");
      console.log(
        "Printing Req HEADERS: " + JSON.stringify(proxyReq.getHeaders())
      );
    },
    onProxyRes: function(proxyRes, req, res) {
      proxyRes.headers["Access-Control-Allow-Origin"] = "*";
    },
    pathRewrite: {
      "^/api/jira/": "/" 
    }
  })
);

module.exports = router;

Appreciate any help to resolve it.

Upvotes: 4

Views: 4102

Answers (1)

pomeh
pomeh

Reputation: 4902

http-proxy-middleware use internally http-proxy module.

In http-proxy module, there is an open issue about using proxyReq (or onProxyReq for http-proxy-middleware) when behing a corporate proxy : https://github.com/http-party/node-http-proxy/issues/1287

The workaround found by b44x is to use proxy.web low-level method from http-proxy module.

I encountered the same problem, and I solved it this way:

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


// define an agent to proxy request to corporate proxy
const proxyAgent = require('proxy-agent');
// get values from environnement variables and avoid hard-coded values
const corporateProxyUrl = process.env.https_proxy || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.HTTP_PROXY || '';
const agent = corporateProxyUrl ? new proxyAgent(corporateProxyUrl) : false;


const myLocalProxy = httpProxy.createProxyServer({});

const myServer = http.createServer(function(req, res) {

  // change request before it's being sent to target
  delete req.headers.origin;

  myLocalProxy.web(req, res, {
    // instruct 'http-proxy' to forward this request to 'target'
    // using 'agent' to pass through corporate proxy
    target: 'https://www.example.com',
    changeOrigin: true,
    agent: agent,
    toProxy: true,
  });

});

myServer.listen(8003);
console.log('[DEMO] Server: listening on port 8003');

Upvotes: 3

Related Questions