Http-proxy-middleware: Unable to access session inside onProxyReqWs

Created on 3 Oct 2019  路  7Comments  路  Source: chimurai/http-proxy-middleware

Hello, I have issue: I want to use onProxyReqWs for authentication. I need to take my session data and send it to websocket server as a header. But my connect middlewares are not getting called before proxy in case of websocket connection. Here is example:

app.use((req, res, next) => {
  req.test = 123
})

app.use(proxy({
  changeOrigin: true,
   ws: true,
   target: 'http://localhost:7045',
    onProxyReq(proxyReq, req, res) {
        // Everything is correct, req.test are set here
        console.log('onProxyReq triggered: ', req.test)
        proxyReq.setHeader('x-secret', req.test);
    },
    onProxyReqWs(proxyReq, req, sock, options, head) {
        // Whoops, req.test are undefined!
        console.log('onProxyReqWs triggered: ', req.test)
    }
))

I don't understand why and most importantly, HOW it bypasses middleware chain, since proxy is a middleware itself. Can you please explain this magic and advice me how to get session data from previous middlewares?

The problem is that I use it inside nuxt, which only supports low-level middlewares (e.g. only use()), so I cannot attach anything to connect app.

Most helpful comment

I have met the same problem. It seems if proxy for websocket, the HPM will overwrite previous express handler. let's look at the code below:

const WsProxy = HPM(...);
DiskManager.use('/socket', function(req, res, next){
    console.log("entering first handler")
    next();
});
DiskManager.use('/socket', WsProxy);

If incoming request is websocket request, the "entering first handler" will not appear.

So weird!!! How can we solve this problem?

All 7 comments

I have met the same problem. It seems if proxy for websocket, the HPM will overwrite previous express handler. let's look at the code below:

const WsProxy = HPM(...);
DiskManager.use('/socket', function(req, res, next){
    console.log("entering first handler")
    next();
});
DiskManager.use('/socket', WsProxy);

If incoming request is websocket request, the "entering first handler" will not appear.

So weird!!! How can we solve this problem?

@CrazyPandar yes, that's very disappointing since I wanted to use it for graphql with subscriptions. Graphql via http works, but subscription doesn't. Spent some time and loose some hair while debugging. Still looking for solution tho. I will let yuou know if I will find something.

Any suggestions or workarounds for this one?

Edit : Had to use

server.on('upgrade', function (req, socket, head)

@rohitcelestial Were you able to get this working? I'm running into this same issue, and would appreciate any insight you could share.

const wsProxy = require('http-proxy').createProxyServer();
const server = app.listen(port, host)
  server.on('upgrade', function (req, socket, head) {
    sessionMiddleware(req, {}, function () {
     // access req.session data here
      wsProxy.ws(req, socket, head, {
        target: `ws://${wsHost}`,
         headers: {
             // headers
        }, 
        changeOrigin: true,
         ws: true
      });
    })
  });

  wsProxy.on('error', function (err, req, res) {
    console.log(err);
    res.end();
  });

Straight code, Hope this helps. I am sure similar can be achieved with http-proxy-middleware
Thanks.

anyone here got it working with http-proxy-middleware ?

@MatthiasGrandl

My solution:

// configure express app however you like, then:
const server = app.listen(port)

const graphqlProxy = createProxyMiddleware({
  target: GRAPHQL_URI,
  changeOrigin: true,
  ws: true,
})

// Re-enable sessions on websockets. Middlewares are not passed to our websocket server and therefore our required `req.session` on the request is not available.
server.on("upgrade", (req, socket, head) => {
  // return a promise to make sure the session is added to the request
  // before anything else will be called.
  return new Promise((resolve) => {
    session(req, {} as any, () => {
      // req.session is now available and will be passed alongside the request
      graphqlProxy.upgrade?.(req, socket, head)
      resolve()
    })
  })
})

Hope this helps!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

udayms picture udayms  路  8Comments

DylanPiercey picture DylanPiercey  路  6Comments

joshiste picture joshiste  路  4Comments

ghostd picture ghostd  路  7Comments

villesau picture villesau  路  8Comments