18 lines
1.1 KiB
TypeScript
18 lines
1.1 KiB
TypeScript
import { Injectable, NestMiddleware } from '@nestjs/common';
|
|
import { requestContext } from './request-context';
|
|
|
|
type RequestLike = { headers: Record<string, string | string[] | undefined>; socket?: { remoteAddress?: string } };
|
|
|
|
@Injectable()
|
|
export class RequestContextMiddleware implements NestMiddleware {
|
|
use(request: RequestLike, _response: unknown, next: () => void) {
|
|
const forwarded = request.headers['x-forwarded-for'];
|
|
const firstForwarded = Array.isArray(forwarded) ? forwarded[0] : forwarded?.split(',')[0];
|
|
const remoteAddress = request.socket?.remoteAddress?.trim().replace(/^::ffff:/, '');
|
|
const trustedProxies = new Set((process.env.TRUSTED_PROXY_IPS ?? '127.0.0.1,::1').split(',').map((item) => item.trim()).filter(Boolean));
|
|
// 仅可信反向代理可以声明客户端地址,防止攻击者伪造 X-Forwarded-For 绕过保护名单或嫁祸他人。
|
|
const ipAddress = (remoteAddress && trustedProxies.has(remoteAddress) ? firstForwarded : remoteAddress)?.trim().replace(/^::ffff:/, '');
|
|
requestContext.run({ ipAddress }, next);
|
|
}
|
|
}
|