summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Emanuele Stoppa <my.burning@gmail.com> 2024-10-14 15:35:24 +0100
committerGravatar GitHub <noreply@github.com> 2024-10-14 15:35:24 +0100
commitfb5569583b11ef585cd0a79e97e7e9dc653f6afa (patch)
tree8e1f3d38af8b5eee99329efe5ed38728f09ac1e3
parentd6f03e405d142363083db5f42b836aacdad561b4 (diff)
downloadastro-fb5569583b11ef585cd0a79e97e7e9dc653f6afa.tar.gz
astro-fb5569583b11ef585cd0a79e97e7e9dc653f6afa.tar.zst
astro-fb5569583b11ef585cd0a79e97e7e9dc653f6afa.zip
fix(middleware): compute client address (#12222)
* fix(middleware): compute client address * add unit test
-rw-r--r--.changeset/slimy-kids-peel.md5
-rw-r--r--packages/astro/src/core/middleware/index.ts12
-rw-r--r--packages/astro/src/core/routing/request.ts20
-rw-r--r--packages/astro/test/units/routing/api-context.test.js19
4 files changed, 53 insertions, 3 deletions
diff --git a/.changeset/slimy-kids-peel.md b/.changeset/slimy-kids-peel.md
new file mode 100644
index 000000000..706d01d47
--- /dev/null
+++ b/.changeset/slimy-kids-peel.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixes an issue where the edge middleware couldn't correctly compute the client IP address when calling `ctx.clientAddress()`
diff --git a/packages/astro/src/core/middleware/index.ts b/packages/astro/src/core/middleware/index.ts
index 2ca802126..a684d23c0 100644
--- a/packages/astro/src/core/middleware/index.ts
+++ b/packages/astro/src/core/middleware/index.ts
@@ -8,6 +8,7 @@ import {
import { ASTRO_VERSION, clientAddressSymbol, clientLocalsSymbol } from '../constants.js';
import { AstroCookies } from '../cookies/index.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
+import { getClientIpAddress } from '../routing/request.js';
import { sequence } from './sequence.js';
function defineMiddleware(fn: MiddlewareHandler) {
@@ -50,6 +51,7 @@ function createContext({
let preferredLocale: string | undefined = undefined;
let preferredLocaleList: string[] | undefined = undefined;
let currentLocale: string | undefined = undefined;
+ let clientIpAddress: string | undefined;
const url = new URL(request.url);
const route = url.pathname;
@@ -85,10 +87,14 @@ function createContext({
},
url,
get clientAddress() {
- if (clientAddressSymbol in request) {
- return Reflect.get(request, clientAddressSymbol) as string;
+ if (clientIpAddress) {
+ return clientIpAddress;
}
- throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
+ clientIpAddress = getClientIpAddress(request);
+ if (!clientIpAddress) {
+ throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
+ }
+ return clientIpAddress;
},
get locals() {
let locals = Reflect.get(request, clientLocalsSymbol);
diff --git a/packages/astro/src/core/routing/request.ts b/packages/astro/src/core/routing/request.ts
new file mode 100644
index 000000000..f7e917a53
--- /dev/null
+++ b/packages/astro/src/core/routing/request.ts
@@ -0,0 +1,20 @@
+/**
+ * Utilities for extracting information from `Request`
+ */
+
+// Parses multiple header and returns first value if available.
+export function getFirstForwardedValue(multiValueHeader?: string | string[] | null) {
+ return multiValueHeader
+ ?.toString()
+ ?.split(',')
+ .map((e) => e.trim())?.[0];
+}
+
+/**
+ * Returns the first value associated to the `x-forwarded-for` header.
+ *
+ * @param {Request} request
+ */
+export function getClientIpAddress(request: Request): string | undefined {
+ return getFirstForwardedValue(request.headers.get('x-forwarded-for'));
+}
diff --git a/packages/astro/test/units/routing/api-context.test.js b/packages/astro/test/units/routing/api-context.test.js
new file mode 100644
index 000000000..1e955e50c
--- /dev/null
+++ b/packages/astro/test/units/routing/api-context.test.js
@@ -0,0 +1,19 @@
+import assert from 'node:assert/strict';
+import { describe, it } from 'node:test';
+import { createContext } from '../../../dist/core/middleware/index.js';
+
+describe('createAPIContext', () => {
+ it('should return the clientAddress', () => {
+ const request = new Request('http://example.com', {
+ headers: {
+ 'x-forwarded-for': '192.0.2.43, 172.16.58.3',
+ },
+ });
+
+ const context = createContext({
+ request,
+ });
+
+ assert.equal(context.clientAddress, '192.0.2.43');
+ });
+});