From e18039323de853ef3a5aba4ef76a70b41c582767 Mon Sep 17 00:00:00 2001 From: Jon Morrow Date: Fri, 26 Sep 2025 15:07:24 -0700 Subject: [PATCH] Use X-Forwarded-Port header when passing xForwardedHeaders option This change updates the logic for xForwardedHeaders=true so that hostname instead of host is set in X-Forwarded-Host so that the port is never included. Additionally, port is set in X-Forwarded-Port. Signed-off-by: Jon Morrow --- packages/fetch-proxy/README.md | 2 +- packages/fetch-proxy/src/lib/fetch-proxy.test.ts | 8 +++++--- packages/fetch-proxy/src/lib/fetch-proxy.ts | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/fetch-proxy/README.md b/packages/fetch-proxy/README.md index 001bbcb2ca8..c0e8ee403d5 100644 --- a/packages/fetch-proxy/README.md +++ b/packages/fetch-proxy/README.md @@ -10,7 +10,7 @@ In the context of servers, an HTTP proxy server is a server that forwards all re - Built on the standard [JavaScript Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) - Supports rewriting `Set-Cookie` headers received from target server -- Supports `X-Forwarded-Proto` and `X-Forwarded-Host` headers +- Supports `X-Forwarded-Proto`, `X-Forwarded-Host`, and `X-Forwarded-Port` headers - Supports custom `fetch` implementations ## Installation diff --git a/packages/fetch-proxy/src/lib/fetch-proxy.test.ts b/packages/fetch-proxy/src/lib/fetch-proxy.test.ts index 29edcfe79b8..27401dd7f6e 100644 --- a/packages/fetch-proxy/src/lib/fetch-proxy.test.ts +++ b/packages/fetch-proxy/src/lib/fetch-proxy.test.ts @@ -100,7 +100,7 @@ describe('fetch proxy', () => { } }) - it('does not append X-Forwarded-Proto and X-Forwarded-Host headers by default', async () => { + it('does not append X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-Port headers by default', async () => { let { request } = await testProxy( new Request('http://shopify.com:8080/search?q=remix'), 'https://remix.run:3000/dest', @@ -108,9 +108,10 @@ describe('fetch proxy', () => { assert.equal(request.headers.get('X-Forwarded-Proto'), null) assert.equal(request.headers.get('X-Forwarded-Host'), null) + assert.equal(request.headers.get('X-Forwarded-Port'), null) }) - it('appends X-Forwarded-Proto and X-Forwarded-Host headers when desired', async () => { + it('appends X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-Port headers when desired', async () => { let { request } = await testProxy( new Request('http://shopify.com:8080/search?q=remix'), 'https://remix.run:3000/dest', @@ -120,7 +121,8 @@ describe('fetch proxy', () => { ) assert.equal(request.headers.get('X-Forwarded-Proto'), 'http') - assert.equal(request.headers.get('X-Forwarded-Host'), 'shopify.com:8080') + assert.equal(request.headers.get('X-Forwarded-Host'), 'shopify.com') + assert.equal(request.headers.get('X-Forwarded-Port'), '8080') }) it('forwards additional request init options', async () => { diff --git a/packages/fetch-proxy/src/lib/fetch-proxy.ts b/packages/fetch-proxy/src/lib/fetch-proxy.ts index 11628145748..ca64a7ce3b2 100644 --- a/packages/fetch-proxy/src/lib/fetch-proxy.ts +++ b/packages/fetch-proxy/src/lib/fetch-proxy.ts @@ -60,7 +60,8 @@ export function createFetchProxy(target: string | URL, options?: FetchProxyOptio let proxyHeaders = new Headers(request.headers) if (xForwardedHeaders) { proxyHeaders.append('X-Forwarded-Proto', url.protocol.replace(/:$/, '')) - proxyHeaders.append('X-Forwarded-Host', url.host) + proxyHeaders.append('X-Forwarded-Host', url.hostname) + proxyHeaders.append('X-Forwarded-Port', url.port) } let proxyInit: RequestInit = {