chimurai / http-proxy-middleware

:zap: The one-liner node.js http-proxy middleware for connect, express, next.js and more
MIT License
10.62k stars 825 forks source link

v3 Next.js API Route Websocket multiple requests #916

Open ldej opened 1 year ago

ldej commented 1 year ago

Checks

Describe the bug (be clear and concise)

I have used the recipe for next.js and API routes: https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/servers.md#nextjs

When I enable ws: true, it proxies my websocket request successfully. However, when I refresh the page, 2 websocket requests are made to the server, resulting in Invalid frame header errors. When I refresh the page again, 3 websocket requests are made, and so on.

I have the feeling that a new server.on('upgrade' events is registered whenever.

Step-by-step reproduction instructions

1. Use https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/servers.md#nextjs
2. Enable `ws: true`
3. Make a page which creates a websocket on `/api/something`
4. Refresh page multiple times
5. See the number of new websockets grow with each refresh

Expected behavior (be clear and concise)

I would expect that http-proxy-middleware would not create multiple websockets when I create 1 websocket.

How is http-proxy-middleware used in your project?

> $ yarn why http-proxy-middleware
yarn why v1.22.19
[1/4] Why do we have the module "http-proxy-middleware"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
[4/4] Calculating file sizes...
=> Found "http-proxy-middleware@3.0.0-beta.1"
info Has been hoisted to "http-proxy-middleware"
info This module exists because it's specified in "dependencies".
info Disk size without dependencies: "560KB"
info Disk size with unique dependencies: "2.82MB"
info Disk size with transitive dependencies: "4.16MB"
info Number of shared dependencies: 16
Done in 1.21s.

What http-proxy-middleware configuration are you using?

{
  target: `http://${process.env.BACKEND_HOST}`,
  changeOrigin: true,
  ws: true,
  pathRewrite: {
    '^/api/ws/': '/ws/',
  }
}

What OS/version and node/version are you seeing the problem?

System:
    OS: Linux 5.19 Ubuntu 22.04.2 LTS 22.04.2 LTS (Jammy Jellyfish)
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-1280P
    Memory: 42.95 GB / 62.52 GB
    Container: Yes
    Shell: 5.8.1 - /usr/bin/zsh
  Binaries:
    Node: 16.17.0 - ~/.nvm/versions/node/v16.17.0/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v16.17.0/bin/yarn
    npm: 8.15.0 - ~/.nvm/versions/node/v16.17.0/bin/npm

Additional context (optional)

For now, changing the handler to read from a global variable works:

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (!global.proxy) {
    global.proxy = proxyMiddleware
  }
  global.proxy(req, res, (result: unknown) => {
    if (result instanceof Error) {
      throw result
    }
  })
}

Any suggestions?

aaronmusknew commented 11 months ago

I have the same problem, Next.js does not behave well as a websocket proxy

anthonytranDev commented 8 months ago

Just so this thread doesn't self resolve. I have this same issue too

avarayr commented 7 months ago

@anthonytranDev this workaround might interest you, https://github.com/vercel/next.js/discussions/58698#discussioncomment-7655962