diff --git a/src/utils/proxy.ts b/src/utils/proxy.ts index 75287cf8019..8a2a166aab6 100644 --- a/src/utils/proxy.ts +++ b/src/utils/proxy.ts @@ -794,6 +794,10 @@ const onRequest = async ( headers.append(req.rawHeaders[index], req.rawHeaders[index + 1]) } + // The server handler gets a `Request` with no socket, so it reads the + // client's address from this header to set `context.ip`. + headers.set('x-forwarded-for', req.socket.remoteAddress ?? '') + const response = await serverMatch.handle( new Request(requestURL, { body: req.originalBody, diff --git a/tests/integration/commands/dev/netlify-server.test.ts b/tests/integration/commands/dev/netlify-server.test.ts index 99d5f7d376a..8e466b9f5ac 100644 --- a/tests/integration/commands/dev/netlify-server.test.ts +++ b/tests/integration/commands/dev/netlify-server.test.ts @@ -40,6 +40,7 @@ const withServerEntry = (builder: SiteBuilder): SiteBuilder => url: req.url, body, siteID: req.headers['x-nf-site-id'] ?? null, + clientIP: req.headers['x-nf-client-connection-ip'] ?? null, }), ) }) @@ -113,6 +114,7 @@ describe.concurrent('command/dev Netlify Server', () => { t.expect(result.source).toBe('server') t.expect(result.url).toBe('/some/deep/path?value=1') t.expect(result.siteID).toBe('unlinked') + t.expect(result.clientIP).toMatch(/^(::ffff:)?127\.0\.0\.1$|^::1$/) }) }) })