HTTP 请求参数类型
前端发起 HTTP 请求时,参数有以下几种常见的传递方式:
1. Query 参数(URL 查询字符串)
// 前端 axios 示例
axios.get('/api/users', {
params: { id: 123, name: 'test' }
});
// 实际请求:GET /api/users?id=123&name=test
typescript
2. Body 参数(请求体)
axios.post('/api/users', {
id: 123,
name: 'test',
password: '123456'
});
// 数据放在请求体(Request Body)中,通常为 JSON 格式
typescript
3. 路径参数(URL Path)
axios.delete('/api/users/1001');
// 路径中的 1001 就是路径参数
typescript
4. Header 参数(请求头)
axios.get('/api/users', {
headers: {
'Authorization': 'Bearer token...',
'x-tenant-id': 'mysql1',
}
});
// 请求头中可以携带认证信息、自定义字段等
typescript
NestJS 参数解析装饰器
NestJS 提供了一套优雅的装饰器来解析上述各类参数,无需手动处理 req.query、req.body 等:
+-------------------+------------------+----------------------------------+
| 参数类型 | 装饰器 | Express 等价写法 |
+-------------------+------------------+----------------------------------+
| Query 参数 | @Query() | req.query |
| Body 参数 | @Body() | req.body |
| 路径参数 | @Param() | req.params |
| Header 参数 | @Headers() | req.headers |
| 完整请求对象 | @Req() | req |
| IP 地址 | @Ip() | req.ip |
| 主机名 | @HostParam() | req.hostname |
+-------------------+------------------+----------------------------------+
text
实战示例
综合使用多种装饰器
import {
Controller,
Get,
Post,
Body,
Query,
Param,
Headers,
} from '@nestjs/common';
@Controller('api/v1')
export class AppController {
@Post('hello/:id')
postHello(
@Query('page') page: string,
@Param('id') id: string,
@Body() body: any,
@Headers('x-tenant-id') tenantId: string,
) {
return {
page: Number(page), // Query 参数
id: parseInt(id, 10), // 路径参数(默认为 string)
body, // Body 参数
tenantId, // Header 参数
};
}
}
typescript
请求示例与响应
请求配置:
POST /api/v1/hello/1000?page=1
Headers:
x-tenant-id: 100001
Body (JSON):
{
"username": "tom",
"password": "123456"
}
text
响应:
{
"page": 1,
"id": 1000,
"body": {
"username": "tom",
"password": "123456"
},
"tenantId": "100001"
}
json
各装饰器详解
@Query() - 查询参数
// 获取单个参数
@Get('users')
findUsers(@Query('page') page: string) {
return `Page: ${page}`;
}
// 获取所有 Query 参数
@Get('users')
findUsers(@Query() query: { page: string; limit: string }) {
return `Page: ${query.page}, Limit: ${query.limit}`;
}
typescript
@Param() - 路径参数
// 路由中需要定义参数占位符 :id
@Get('users/:id')
findOne(@Param('id') id: string) {
return `User ID: ${id}`; // 注意:路径参数默认为 string 类型
}
// 获取所有路径参数
@Get('users/:userId/posts/:postId')
findPost(@Param() params: { userId: string; postId: string }) {
return `User: ${params.userId}, Post: ${params.postId}`;
}
typescript
路径参数始终是 string 类型,需要手动转换为数字:
@Get('users/:id')
findOne(@Param('id') id: string) {
const numericId = parseInt(id, 10);
// 或使用 DTO + class-transformer 自动转换
}
typescript
@Body() - 请求体
// 使用 DTO 定义请求体结构
class CreateUserDto {
username: string;
password: string;
email: string;
}
@Post('users')
create(@Body() createUserDto: CreateUserDto) {
return { message: 'User created', data: createUserDto };
}
// 获取 Body 中的单个字段
@Post('users')
create(@Body('username') username: string) {
return `Creating user: ${username}`;
}
typescript
@Headers() - 请求头
// 获取单个 Header
@Get('profile')
getProfile(@Headers('authorization') auth: string) {
return `Auth token: ${auth}`;
}
// 获取所有 Headers
@Get('info')
getInfo(@Headers() headers: Record<string, string>) {
return { userAgent: headers['user-agent'] };
}
typescript
@Req() 的使用场景
@Req() 提供完整的 Express Request 对象,但一般不推荐在业务逻辑中使用,因为它绕过了 NestJS 的封装层,使代码与底层框架(Express/Fastify)耦合。
仅在以下场景使用:
- 需要读取特殊 Header(如
x-forwarded-for) - 需要 Cookie 操作
- 调试和开发阶段
import { Request } from 'express';
@Get('debug')
debug(@Req() req: Request) {
return {
ip: req.ip,
cookies: req.cookies,
headers: req.headers,
};
}
typescript
使用 DTO 进行类型校验
结合 class-validator 和 class-transformer,可以在参数层面实现自动校验:
import { IsString, IsNumber, IsEmail, MinLength } from 'class-validator';
import { Type } from 'class-transformer';
export class CreateUserDto {
@IsString()
username: string;
@IsString()
@MinLength(6)
password: string;
@IsEmail()
email: string;
}
export class PaginationDto {
@Type(() => Number)
@IsNumber()
page: number = 1;
@Type(() => Number)
@IsNumber()
limit: number = 10;
}
typescript
小结
- NestJS 通过装饰器优雅地解析 HTTP 请求参数,替代手动操作
req对象 - 四种常用装饰器:
@Query()、@Param()、@Body()、@Headers() - 路径参数默认为
string类型,需要手动转换 - 优先使用具体装饰器而非
@Req(),保持代码与框架解耦 - 配合 DTO +
class-validator实现参数类型校验
↑