From 5d600414009572e826766a710fa6a405f33209b9 Mon Sep 17 00:00:00 2001 From: John Hunter Date: Mon, 29 Apr 2024 18:03:58 +0100 Subject: [PATCH 1/4] Rewrite the origin header to match the target for ws proxy --- packages/vite/src/node/server/middlewares/proxy.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/vite/src/node/server/middlewares/proxy.ts b/packages/vite/src/node/server/middlewares/proxy.ts index 2b80f2801d2f71..0eed02518adb6f 100644 --- a/packages/vite/src/node/server/middlewares/proxy.ts +++ b/packages/vite/src/node/server/middlewares/proxy.ts @@ -90,6 +90,19 @@ export function proxyMiddleware( }) proxy.on('proxyReqWs', (proxyReq, req, socket, options, head) => { + // Browsers may send Origin headers even with same-origin + // requests. It is common for WebSocket servers to check the Origin + // header, so we have to change the Origin to match + // the target URL. + if (proxyReq.getHeader('origin') && options.target) { + const target = + typeof options.target === 'object' + ? `${options.target.protocol}//${options.target.host}` + : options.target + + proxyReq.setHeader('origin', target) + } + socket.on('error', (err) => { config.logger.error( `${colors.red(`ws proxy socket error:`)}\n${err.stack}`, From d14bbb7630114e31ad28793fdd5400ce7391a6b0 Mon Sep 17 00:00:00 2001 From: John Hunter Date: Tue, 30 Apr 2024 13:50:45 +0100 Subject: [PATCH 2/4] Update the docs to clarify the changeOrigin option This is misleadingly named in http-proxy --- docs/config/server-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config/server-options.md b/docs/config/server-options.md index 8008562de02509..abc6efef89ed51 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 the `changeOrigin` option changes host header to match the target URL, the origin header is always changed 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. From b9ebeeaf77d55130783f503df3795b676657cb85 Mon Sep 17 00:00:00 2001 From: John Hunter Date: Tue, 14 May 2024 18:13:02 +0100 Subject: [PATCH 3/4] Rewrite Origin header if changeOrigin is true Rewrites the header for both ws and http requests --- .../vite/src/node/server/middlewares/proxy.ts | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/packages/vite/src/node/server/middlewares/proxy.ts b/packages/vite/src/node/server/middlewares/proxy.ts index 0eed02518adb6f..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,19 +112,12 @@ export function proxyMiddleware( } }) + proxy.on('proxyReq', (proxyReq, req, res, options) => { + setOriginHeader(proxyReq, options) + }) + proxy.on('proxyReqWs', (proxyReq, req, socket, options, head) => { - // Browsers may send Origin headers even with same-origin - // requests. It is common for WebSocket servers to check the Origin - // header, so we have to change the Origin to match - // the target URL. - if (proxyReq.getHeader('origin') && options.target) { - const target = - typeof options.target === 'object' - ? `${options.target.protocol}//${options.target.host}` - : options.target - - proxyReq.setHeader('origin', target) - } + setOriginHeader(proxyReq, options) socket.on('error', (err) => { config.logger.error( From 8019aeac46df96f0d194fd356eb66caee9243160 Mon Sep 17 00:00:00 2001 From: John Hunter Date: Wed, 15 May 2024 09:41:56 +0100 Subject: [PATCH 4/4] Update docs to reflect change --- docs/config/server-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config/server-options.md b/docs/config/server-options.md index abc6efef89ed51..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). Note that the `changeOrigin` option changes host header to match the target URL, the origin header is always changed to match the target. +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.