0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-17 22:44:24 -05:00

fix(middleware): compute client address (#12222)

* fix(middleware): compute client address

* add unit test
This commit is contained in:
Emanuele Stoppa 2024-10-14 15:35:24 +01:00 committed by GitHub
parent d6f03e405d
commit fb5569583b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 53 additions and 3 deletions

View file

@ -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()`

View file

@ -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);

View file

@ -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'));
}

View file

@ -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');
});
});