6

I'm using the http-proxy-middleware (https://github.com/chimurai/http-proxy-middleware#http-proxy-events) to implement a simple proxy (call it my-proxy/) to another REST API (call it /rest-api) that requires the user to pass an auth token in the HTTP header auth-token. The token can be fetched from an endpoint POST /rest-api/auth with the credentials in the body.

I want my proxy to take incoming requests and check if auth-token is set in the the request header, and if not perform a POST /rest-api/auth to retrieve the token and set auth-token in the header before passing the request to rest-api/.

In the proxy config I specify

onProxyReq: function (proxyReq, req, res) {
        if (!req.header("auth-token")) {
            const authRequest = request({
                    url: 'rest-api/auth',
                    method: 'POST',
                    json: {"username": "user", "password": "pass"}
                },
                function (error, resp, body) {
                    proxyReq.setHeader("auth-token", body.token)
                }
            );
        }
    }

I can see the body.token return the right token. However the setHeader call fails with Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client.

I think this means the request I modify has already been sent to rest-api/ before waiting for the callback, but I don't know how this is best solved in my scenario.

Any help?

1 Answer 1

6

I met this same issue today. I workaround this by using a separate middleware (before http proxy).

pseudo code

// fix token stuff here in a separate middleware
app.use('/api', async (req, res, next) => {

    if (!req.session.token) {
       const resToken = await axios.post(token_url, data, options)
       req.session.token = resToken.data
    }
    next()
}

// proxy middleware options
const proxyOptions = {
  target: config.gateway.url, // target host
  changeOrigin: true,
  pathRewrite: function(path, req) {
    return path.replace('/api', '')
  },
  onProxyReq: function onProxyReq(proxyReq, req, res) {
    // add custom header to request
    let token = req.session.token
    if (token) {
      proxyReq.setHeader('Authorization', `bearer ${token.access_token}`)
    }
  },
  logLevel: 'debug',
}

app.use(proxy('/api', proxyOptions))

Hope this helps!

Sign up to request clarification or add additional context in comments.

2 Comments

Forgot to post my solution, but I ended up doing the same, except that I call the proxy inside the middleware, so I only register that middleware, which I believe is better encapsulation.
yeah i wish the onProxyReq function could accept an async function so that we could await a request before sending the proxy request, but this answer works well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.