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:
parent
d6f03e405d
commit
fb5569583b
4 changed files with 53 additions and 3 deletions
5
.changeset/slimy-kids-peel.md
Normal file
5
.changeset/slimy-kids-peel.md
Normal 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()`
|
|
@ -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);
|
||||
|
|
20
packages/astro/src/core/routing/request.ts
Normal file
20
packages/astro/src/core/routing/request.ts
Normal 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'));
|
||||
}
|
19
packages/astro/test/units/routing/api-context.test.js
Normal file
19
packages/astro/test/units/routing/api-context.test.js
Normal 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');
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue