From 7b0a65e2002b8d09fd2fee0873b5fb8384fdf08b Mon Sep 17 00:00:00 2001 From: John Hunter Date: Wed, 29 May 2024 15:22:59 +0100 Subject: [PATCH] fix(proxy): rewrite the origin header to match the target for ws proxy (#16558) Co-authored-by: John Hunter --- docs/config/server-options.md | 2 +- .../vite/src/node/server/middlewares/proxy.ts | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/config/server-options.md b/docs/config/server-options.md index 8008562de02509..dbeec4428120f5 100644 --- a/docs/config/server-options.md +++ b/docs/config/server-options.md @@ -90,7 +90,7 @@ Configure custom proxy rules for the dev server. Expects an object of `{ key: op Note that if you are using non-relative [`base`](/config/shared-options.md#base), you must prefix each key with that `base`. -Extends [`http-proxy`](https://github.com/http-party/node-http-proxy#options). Additional options are [here](https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/proxy.ts#L13). +Extends [`http-proxy`](https://github.com/http-party/node-http-proxy#options). Additional options are [here](https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/proxy.ts#L13). Note that [unlike http-proxy](https://github.com/http-party/node-http-proxy/issues/1669), the `changeOrigin` option will change both host and origin headers to match the target. In some cases, you might also want to configure the underlying dev server (e.g. to add custom middlewares to the internal [connect](https://github.com/senchalabs/connect) app). In order to do that, you need to write your own [plugin](/guide/using-plugins.html) and use [configureServer](/guide/api-plugin.html#configureserver) function. diff --git a/packages/vite/src/node/server/middlewares/proxy.ts b/packages/vite/src/node/server/middlewares/proxy.ts index 2b80f2801d2f71..4ceb4d8d435426 100644 --- a/packages/vite/src/node/server/middlewares/proxy.ts +++ b/packages/vite/src/node/server/middlewares/proxy.ts @@ -29,6 +29,29 @@ export interface ProxyOptions extends HttpProxy.ServerOptions { ) => void | null | undefined | false | string } +const setOriginHeader = ( + proxyReq: http.ClientRequest, + options: HttpProxy.ServerOptions, +) => { + // Browsers may send Origin headers even with same-origin + // requests. It is common for WebSocket servers to check the Origin + // header, so if changeOrigin is true we change the Origin to match + // the target URL. + // https://github.com/http-party/node-http-proxy/issues/1669 + if (options.changeOrigin) { + const { target } = options + + if (proxyReq.getHeader('origin') && target) { + const changedOrigin = + typeof target === 'object' + ? `${target.protocol}//${target.host}` + : target + + proxyReq.setHeader('origin', changedOrigin) + } + } +} + export function proxyMiddleware( httpServer: HttpServer | null, options: NonNullable, @@ -89,7 +112,13 @@ export function proxyMiddleware( } }) + proxy.on('proxyReq', (proxyReq, req, res, options) => { + setOriginHeader(proxyReq, options) + }) + proxy.on('proxyReqWs', (proxyReq, req, socket, options, head) => { + setOriginHeader(proxyReq, options) + socket.on('error', (err) => { config.logger.error( `${colors.red(`ws proxy socket error:`)}\n${err.stack}`,