Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/config/server-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [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.
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 `rewriteWsOrigin` option will rewrite a WebScocket request Origin header to match the target. **Exercise caution as rewriting the Origin can leave the proxying open to [CSRF attacks](https://owasp.org/www-community/attacks/csrf).**

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.

Expand Down
23 changes: 14 additions & 9 deletions packages/vite/src/node/server/middlewares/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,27 @@ export interface ProxyOptions extends HttpProxy.ServerOptions {
) => void | null | undefined | false | string
}

const setOriginHeader = (
const rewriteOriginHeader = (
proxyReq: http.ClientRequest,
options: HttpProxy.ServerOptions,
config: ResolvedConfig,
) => {
// 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
// header, so if rewriteWsOrigin is true we change the Origin to match
// the target URL.
// https://github.com/http-party/node-http-proxy/issues/1669
if (options.changeOrigin) {
if (options.rewriteWsOrigin) {
const { target } = options

if (proxyReq.headersSent) {
config.logger.warn(
colors.yellow(
`Unable to rewrite Origin header as headers are already sent.`,
),
)
return
}

if (proxyReq.getHeader('origin') && target) {
const changedOrigin =
typeof target === 'object'
Expand Down Expand Up @@ -112,12 +121,8 @@ export function proxyMiddleware(
}
})

proxy.on('proxyReq', (proxyReq, req, res, options) => {
setOriginHeader(proxyReq, options)
})

proxy.on('proxyReqWs', (proxyReq, req, socket, options, head) => {
setOriginHeader(proxyReq, options)
rewriteOriginHeader(proxyReq, options, config)

socket.on('error', (err) => {
config.logger.error(
Expand Down
2 changes: 2 additions & 0 deletions packages/vite/src/types/http-proxy.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ export namespace HttpProxy {
localAddress?: string | undefined
/** Changes the origin of the host header to the target URL. */
changeOrigin?: boolean | undefined
/** Rewrites the Origin header of a WebSocket request to match the the target */
rewriteWsOrigin?: boolean | undefined
/** specify whether you want to keep letter case of response header key */
preserveHeaderKeyCase?: boolean | undefined
/** Basic authentication i.e. 'user:password' to compute an Authorization header. */
Expand Down