Läsa requestkontext med param-dekoratorer
Skapa anpassade @CurrentUser- och @ClientIp-param-dekoratorer med createParamDecorator och ExecutionContext.
Läsa requestkontext med param-dekoratorer är en gratis lektion i NestJS: backend-API:er för företag på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för NestJS: backend-API:er för företag, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i NestJS: backend-API:er för företag innehåller totalt 4 lektioner.
Varför param-dekoratorer?
I NestJS-controllers behöver Ni ofta hämta samma information från begäran om och om igen: den autentiserade användaren, klientens IP-adress eller ett tenant-id från en header. Att göra detta med @Req() och leta i request.user i varje handler är repetitivt och läcker ramverksdetaljer in i Er affärslogik.
Anpassade param-dekoratorer låter Er kapsla in denna extraktion en gång och återanvända den överallt:
@CurrentUser()i stället förreq.user@ClientIp()i stället för att tolkax-forwarded-for
Resultatet blir renare, mer testbar och mer deklarativ controller-kod.
Det repetitiva sättet
Här är det Ni vanligtvis börjar med: att hämta hela request-objektet och manuellt leta i det. Det fungerar, men varje handler upprepar samma rader, och controllern känner nu till request.user, vilket är en implementeringsdetalj i Er auth guard.
Lägg märke till hur den faktiska routelogiken döljs under teknisk infrastrukturkod. Det är precis detta som en param-dekorator tar bort.
import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';
@Controller('profile')
export class ProfileController {
@Get()
getProfile(@Req() request: Request) {
const user = (request as any).user;
return { id: user.id, email: user.email };
}
}createParamDecorator
NestJS tillhandahåller fabriken createParamDecorator från @nestjs/common. Ni skickar in en funktion som tar emot två argument och returnerar det värde Ni vill injicera i handler-parametern.
- data — det valfria argument som skickas när dekoratorn används, till exempel
@CurrentUser('email'). - ctx: ExecutionContext — en omslutning kring den aktuella requestkontexten, oberoende av transport (HTTP, RPC, WebSocket).
Det returnerade värdet blir parameterns värde när handlern anropas.
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const Example = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
// return any value -> it gets injected into the param
return 'hello';
},
);Hämta HTTP-requesten
I HTTP-appar konverterar Ni den generiska ExecutionContext till ett HTTP-specifikt argumentshost-objekt och läser requesten från det:
ctx.switchToHttp()returnerar enHttpArgumentsHost..getRequest()hämtar den underliggande requesten (Express eller Fastify).
Att använda switchToHttp() gör det tydligt vilket transportprotokoll dekoratorn riktar sig mot. Samma kontext kan även växlas till RPC eller WS för andra protokoll.
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { Request } from 'express';
export const RawRequest = createParamDecorator(
(data: unknown, ctx: ExecutionContext): Request => {
return ctx.switchToHttp().getRequest<Request>();
},
);Bygga @CurrentUser
Anta att en auth guard (till exempel en JWT-strategi) redan har kopplat den autentiserade användaren till request.user. Dekoratorn @CurrentUser() returnerar den helt enkelt.
Detta är det etablerade mönstret i företagsapplikationer med NestJS: guard ansvarar för autentisering, och dekoratorn ger smidig åtkomst till resultatet utan att exponera request-objektet.
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export interface AuthUser {
id: string;
email: string;
roles: string[];
}
export const CurrentUser = createParamDecorator(
(data: unknown, ctx: ExecutionContext): AuthUser => {
const request = ctx.switchToHttp().getRequest();
return request.user;
},
);Använda argumentet data
Den första parametern, data, är det som anroparen skickar inom dekoratorns parenteser. Ni kan använda den för att returnera en enskild egenskap i stället för hela objektet:
@CurrentUser()returnerar hela användaren.@CurrentUser('email')returnerar endast e-postadressen.
Typbestäm data-argumentet som keyof AuthUser så att anroparen får autokomplettering och säkerhet vid kompilering för egenskapsnamnet.
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { AuthUser } from './auth-user.interface';
export const CurrentUser = createParamDecorator(
(data: keyof AuthUser | undefined, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const user: AuthUser = request.user;
return data ? user?.[data] : user;
},
);Använda @CurrentUser i en controller
Nu blir controllern lättläst. Guard garanterar att användaren finns, och dekoratorn injicerar exakt det varje handler behöver. Ingen @Req() och inget manuellt letande efter egenskaper.
Det är denna åtskillnad som gör handlern enkel att enhetstesta: Ni anropar bara metoden med ett vanligt användarobjekt.
import { Controller, Get, UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from './jwt-auth.guard';
import { CurrentUser } from './current-user.decorator';
import { AuthUser } from './auth-user.interface';
@UseGuards(JwtAuthGuard)
@Controller('me')
export class MeController {
@Get()
getMe(@CurrentUser() user: AuthUser) {
return user;
}
@Get('email')
getEmail(@CurrentUser('email') email: string) {
return { email };
}
}Bygga @ClientIp
Bakom en lastbalanserare eller reverse proxy finns klientens riktiga IP-adress inte i request.ip, utan som det första värdet i headern x-forwarded-for. En @ClientIp()-dekorator centraliserar denna logik så att varje handler läser rätt adress.
Viktigt: lita endast på x-forwarded-for när Ni faktiskt kör bakom en betrodd proxy, och aktivera Express-inställningen trust proxy. Annars kan klienter förfalska headern.
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { Request } from 'express';
export const ClientIp = createParamDecorator(
(data: unknown, ctx: ExecutionContext): string => {
const request = ctx.switchToHttp().getRequest<Request>();
const forwarded = request.headers['x-forwarded-for'];
if (typeof forwarded === 'string' && forwarded.length > 0) {
return forwarded.split(',')[0].trim();
}
return request.ip ?? '';
},
);Ren extraktionslogik går att testa
Det värdefulla i en param-dekorator är dess rena extraktionslogik. Ni kan flytta den till en vanlig funktion, enhetstesta den med en simulerad request och anropa den från dekoratorn. Här är IP-tolkningslogiken som ett fristående, körbart program.
Detta visar regeln för att välja den första vidarebefordrade adressen och reservbeteendet — Ni behöver varken NestJS eller en server för att verifiera det.
function extractClientIp(headers: Record<string, string>, fallbackIp: string): string {
const forwarded = headers['x-forwarded-for'];
if (typeof forwarded === 'string' && forwarded.length > 0) {
return forwarded.split(',')[0].trim();
}
return fallbackIp;
}
console.log(extractClientIp({ 'x-forwarded-for': '203.0.113.7, 70.41.3.18' }, '10.0.0.1'));
console.log(extractClientIp({}, '10.0.0.1'));
console.log(extractClientIp({ 'x-forwarded-for': '198.51.100.5' }, '10.0.0.1'));Kombinera dekoratorer i en handler
Param-dekoratorer kan kombineras fritt. En enda handler kan blanda inbyggda dekoratorer (@Body, @Param) med Era anpassade dekoratorer. NestJS löser varje parameter separat utifrån dekoratorns metadata.
Här registrerar en gransknings-endpoint vem som gjorde vad och varifrån, genom att deklarativt läsa användare och IP-adress.
import { Controller, Post, Body, UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from './jwt-auth.guard';
import { CurrentUser } from './current-user.decorator';
import { ClientIp } from './client-ip.decorator';
import { AuthUser } from './auth-user.interface';
@UseGuards(JwtAuthGuard)
@Controller('audit')
export class AuditController {
@Post('action')
record(
@CurrentUser('id') userId: string,
@ClientIp() ip: string,
@Body() body: { action: string },
) {
return { userId, ip, action: body.action, at: new Date().toISOString() };
}
}Validering och pipes gäller fortfarande
En anpassad param-dekorator returnerar ett obehandlat värde, så Ni kan fortfarande koppla pipes till den precis som till inbyggda dekoratorer. Skicka med en pipe som ett extra argument när Ni använder dekoratorn.
@CurrentUser('id', ParseUUIDPipe)validerar att det extraherade id:t är ett UUID.- Pipes körs efter att dekoratorfabriken har returnerat sitt värde.
På så sätt kan Ni hålla extraktion och validering tydligt åtskilda och samtidigt dra nytta av NestJS pipe-pipeline.
import { Controller, Get, ParseUUIDPipe } from '@nestjs/common';
import { CurrentUser } from './current-user.decorator';
@Controller('orders')
export class OrdersController {
@Get('mine')
myOrders(@CurrentUser('id', ParseUUIDPipe) userId: string) {
return { userId };
}
}Snabb kontroll
Testa Er förståelse av hur en anpassad param-dekorator läser requesten.
Sammanfattning
Ni har lärt Er att läsa requestkontext deklarativt med anpassade param-dekoratorer:
- createParamDecorator((data, ctx) => ...) bygger en återanvändbar dekorator; det returnerade värdet injiceras i handler-parametern.
- ctx.switchToHttp().getRequest() hämtar HTTP-requesten på ett sätt som tydligt anger transportprotokollet.
- @CurrentUser() kapslar in
request.user(som fylls i av Er auth guard) och kan returnera en enskild egenskap viadata-argumentet, typbestämt somkeyof AuthUser. - @ClientIp() centraliserar tolkningen av
x-forwarded-for, med en reservlösning som använderrequest.ip— lita endast på headern bakom en verklig proxy. - Håll extraktionslogiken ren så att den blir enkel att enhetstesta, och kom ihåg att Ni fortfarande kan kedja pipes som
ParseUUIDPipetill Era anpassade dekoratorer.
Lär dig TypeScript med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 20
- Lektioner
- 76
Vanliga frågor
Är lektionen ”Läsa requestkontext med param-dekoratorer” gratis?
Ja – hela texten till ”Läsa requestkontext med param-dekoratorer” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i NestJS: backend-API:er för företag, kan Ni uppgradera till CoddyKit PRO. Kursen i NestJS: backend-API:er för företag innehåller totalt 4 lektioner.
Vad lär jag mig i ”Läsa requestkontext med param-dekoratorer”?
Skapa anpassade @CurrentUser- och @ClientIp-param-dekoratorer med createParamDecorator och ExecutionContext. Ni övar på NestJS: backend-API:er för företag med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig NestJS: backend-API:er för företag?
Du behöver inga förkunskaper. Utbildningen i NestJS: backend-API:er för företag på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Läsa requestkontext med param-dekoratorer”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här NestJS: backend-API:er för företag-lektionen?
Ja. Varje NestJS: backend-API:er för företag-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Läsa requestkontext med param-dekoratorer
- Bifoga metadata med SetMetadata och Reflector
- Kombinera dekoratorer med applyDecorators
- Dekoratorer på klassnivå för tvärgående konfiguration