diff options
-rw-r--r-- | .changeset/healthy-planets-dream.md | 7 | ||||
-rw-r--r-- | packages/astro/src/core/app/node.ts | 6 | ||||
-rw-r--r-- | packages/astro/test/client-address-node.test.js | 27 | ||||
-rw-r--r-- | packages/astro/test/fixtures/client-address-node/astro.config.mjs | 8 | ||||
-rw-r--r-- | packages/astro/test/fixtures/client-address-node/package.json | 9 | ||||
-rw-r--r-- | packages/astro/test/fixtures/client-address-node/src/pages/index.astro | 13 | ||||
-rw-r--r-- | packages/astro/test/test-utils.js | 8 | ||||
-rw-r--r-- | pnpm-lock.yaml | 9 |
8 files changed, 86 insertions, 1 deletions
diff --git a/.changeset/healthy-planets-dream.md b/.changeset/healthy-planets-dream.md new file mode 100644 index 000000000..52f42fc5e --- /dev/null +++ b/.changeset/healthy-planets-dream.md @@ -0,0 +1,7 @@ +--- +"astro": minor +--- + +Updates Astro's code for adapters to use the header `x-forwarded-for` to initialize the `clientAddress`. + +To take advantage of the new change, integration authors must upgrade the version of Astro in their adapter `peerDependencies` to `4.9.0`. diff --git a/packages/astro/src/core/app/node.ts b/packages/astro/src/core/app/node.ts index c28fa8754..537c7f5e7 100644 --- a/packages/astro/src/core/app/node.ts +++ b/packages/astro/src/core/app/node.ts @@ -81,7 +81,11 @@ export class NodeApp extends App { Object.assign(options, makeRequestBody(req)); } const request = new Request(url, options); - if (req.socket?.remoteAddress) { + + const clientIp = req.headers['x-forwarded-for']; + if (clientIp) { + Reflect.set(request, clientAddressSymbol, clientIp); + } else if (req.socket?.remoteAddress) { Reflect.set(request, clientAddressSymbol, req.socket.remoteAddress); } return request; diff --git a/packages/astro/test/client-address-node.test.js b/packages/astro/test/client-address-node.test.js new file mode 100644 index 000000000..8114ea42d --- /dev/null +++ b/packages/astro/test/client-address-node.test.js @@ -0,0 +1,27 @@ +import * as assert from 'node:assert/strict'; +import { describe, it } from 'node:test'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; +import { createRequestAndResponse } from './units/test-utils.js'; + +describe('NodeClientAddress', () => { + it('clientAddress is 1.1.1.1', async () => { + const fixture = await loadFixture({ + root: './fixtures/client-address-node/', + }); + await fixture.build(); + const handle = await fixture.loadNodeAdapterHandler(); + const { req, res, text } = createRequestAndResponse({ + method: 'GET', + url: '/', + headers: { + 'x-forwarded-for': '1.1.1.1', + }, + }); + handle(req, res); + const html = await text(); + const $ = cheerio.load(html); + assert.equal(res.statusCode, 200); + assert.equal($('#address').text(), '1.1.1.1'); + }); +}); diff --git a/packages/astro/test/fixtures/client-address-node/astro.config.mjs b/packages/astro/test/fixtures/client-address-node/astro.config.mjs new file mode 100644 index 000000000..ad9b3a3b1 --- /dev/null +++ b/packages/astro/test/fixtures/client-address-node/astro.config.mjs @@ -0,0 +1,8 @@ +import node from '@astrojs/node'; +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({ + output: 'server', + adapter: node({ mode: 'middleware' }), +}); diff --git a/packages/astro/test/fixtures/client-address-node/package.json b/packages/astro/test/fixtures/client-address-node/package.json new file mode 100644 index 000000000..4b1c6a5ee --- /dev/null +++ b/packages/astro/test/fixtures/client-address-node/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/client-address-node", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/node": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/client-address-node/src/pages/index.astro b/packages/astro/test/fixtures/client-address-node/src/pages/index.astro new file mode 100644 index 000000000..b720cfd34 --- /dev/null +++ b/packages/astro/test/fixtures/client-address-node/src/pages/index.astro @@ -0,0 +1,13 @@ +--- +export const prerender = false; +const address = Astro.clientAddress; +--- +<html> + <head> + <title>Astro.clientAddress</title> + </head> + <body> + <h1>Astro.clientAddress</h1> + <div id="address">{ address }</div> + </body> +</html> diff --git a/packages/astro/test/test-utils.js b/packages/astro/test/test-utils.js index bd7e1f903..65968a0bc 100644 --- a/packages/astro/test/test-utils.js +++ b/packages/astro/test/test-utils.js @@ -25,6 +25,8 @@ process.env.ASTRO_TELEMETRY_DISABLED = true; * @typedef {import('../src/core/app/index').App} App * @typedef {import('../src/cli/check/index').AstroChecker} AstroChecker * @typedef {import('../src/cli/check/index').CheckPayload} CheckPayload + * @typedef {import('http').IncomingMessage} NodeRequest + * @typedef {import('http').ServerResponse} NodeResponse * * * @typedef {Object} Fixture @@ -40,6 +42,7 @@ process.env.ASTRO_TELEMETRY_DISABLED = true; * @property {typeof preview} preview * @property {() => Promise<void>} clean * @property {() => Promise<App>} loadTestAdapterApp + * @property {() => Promise<(req: NodeRequest, res: NodeResponse) => void>} loadNodeAdapterHandler * @property {() => Promise<void>} onNextChange * @property {typeof check} check * @property {typeof sync} sync @@ -213,6 +216,11 @@ export async function loadFixture(inlineConfig) { }); } }, + loadNodeAdapterHandler: async () => { + const url = new URL(`./server/entry.mjs?id=${fixtureId}`, config.outDir); + const { handler } = await import(url); + return handler; + }, loadTestAdapterApp: async (streaming) => { const url = new URL(`./server/entry.mjs?id=${fixtureId}`, config.outDir); const { createApp, manifest } = await import(url); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cbc289056..829ec7013 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2381,6 +2381,15 @@ importers: specifier: workspace:* version: link:../../.. + packages/astro/test/fixtures/client-address-node: + dependencies: + '@astrojs/node': + specifier: workspace:* + version: link:../../../../integrations/node + astro: + specifier: workspace:* + version: link:../../.. + packages/astro/test/fixtures/code-component: dependencies: astro: |