http-proxy-middleware icon indicating copy to clipboard operation
http-proxy-middleware copied to clipboard

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

Open cdisk opened this issue 5 years ago • 4 comments

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client.

I want to use both pathRewrite and followRedirects. I use the vue webpack config this funtions. But When I add followRedirects config attribute,the console show me this error.

Steps to reproduce

  1. create vue project.
  2. add vue.config.js
  3. add proxy config to vue.config.js file.
  4. add pathRewrite and followRedirects to proxy node.
  5. run command yarn serve to start project.
  6. use ajax call target url in browser.
  7. the yarn console display following errors and stop the project:

Here is my vue.config.js file:

    devServer: {
        proxy: {
            '/api': {
                target: 'http://127.0.0.1:8581/', // 反代目标地址
                changeOrigin: true,
                // autoRewrite: true,
                // xfwd: true,
                // prependPath: true,
                followRedirects: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }

Here is the error message displayed in the console:

_http_outgoing.js:485
    throw new ERR_HTTP_HEADERS_SENT('set');
    ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ClientRequest.setHeader (_http_outgoing.js:485:11)
    at RedirectableRequest.setHeader (/root/workspaces/sqwl/hzsc-pc/node_modules/http-proxy/node_modules/follow-redirects/index.js:118:24)
    at ProxyServer.onProxyReq (/root/workspaces/sqwl/hzsc-pc/node_modules/@vue/cli-service/lib/util/prepareProxy.js:97:20)
    at ProxyServer.emit (/root/workspaces/sqwl/hzsc-pc/node_modules/eventemitter3/index.js:184:35)
    at RedirectableRequest.<anonymous> (/root/workspaces/sqwl/hzsc-pc/node_modules/http-proxy/lib/http-proxy/passes/web-incoming.js:132:27)
    at RedirectableRequest.emit (events.js:223:5)
    at ClientRequest.eventHandlers.<computed> (/root/workspaces/sqwl/hzsc-pc/node_modules/http-proxy/node_modules/follow-redirects/index.js:17:24)
    at ClientRequest.emit (events.js:228:7)
    at tickOnSocket (_http_client.js:684:7)
    at onSocketNT (_http_client.js:723:5)
    at processTicksAndRejections (internal/process/task_queues.js:81:21) {
  code: 'ERR_HTTP_HEADERS_SENT'
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

please help me.

cdisk avatar Mar 09 '20 05:03 cdisk

any updates about this Issue ? :/

uranium93 avatar Aug 25 '20 09:08 uranium93

Not sure if it's relevant, but I also had this error in Angular application, while trying to proxy POST request via pathRewrite.

It appears that pathRewrite works fine for GET requests.

pathRewrite: () => '/mocks/get-heroes-response.mock.json'

Yes, it could also be a function, not an object.

But for POST and PUT bypass should be used instead.

bypass: (request) => {
    if (request.method === 'POST') {
        request.method = 'GET';
        return '/mocks/create-hero-response.mock.json';
    }
}

Using pathRewrite for POST and PUT also works, but with error you sent.

maks-humeniuk avatar Sep 21 '21 14:09 maks-humeniuk

After new research I figured out that bypass suffers from https://github.com/webpack/webpack-dev-server/issues/829.

Luckily, you could substitute it with pathRewrite like this.

// for non-GET requests
pathRewrite: (path, request) => {
    request.method === 'GET';
    return '/path/to/mock.json';
}

// for GET requests
pathRewrite: () => '/path/to/mock.json'

If you have multiple returns though, you should wrap request.method === 'GET'; with e.g. if (request.method === 'POST') {} to avoid infinite loop situations.

// for non-GET requests
pathRewrite: (path, request) => {
    if (request.method === 'POST') {
        request.method === 'GET';
        return '/path/to/post-mock.json';
    }
    if (request.method === 'PUT') {
        request.method === 'GET';
        return '/path/to/put-mock.json';
    }
}

Or, more elegant solution.

// for non-GET requests
pathRewrite: (path, request) => {
    const post = request.method === 'POST';
    const put = request.method === 'PUT';
    if (post || put) {
        request.method === 'GET';
    }
    if (post) {
        return '/path/to/post-mock.json';
    }
    if (put) {
        return '/path/to/put-mock.json';
    }
}

maks-humeniuk avatar Sep 22 '21 09:09 maks-humeniuk

Little update regarding this. we faced an issue with same error message using express with http-proxy-middleware and the issue was that in implementation next() was called twice, once in the middleware and the other one onError without return.

uranium93 avatar Nov 03 '21 21:11 uranium93