请求处理
请求处理
控制器负责处理传入的请求和向客户端返回响应。

控制器的目的是接收应用的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器有多个路由,不同的路由可以执行不同的操作。为了创建一个基本的控制器,我们必须使用装饰器。装饰器将类与所需的元数据关联,并使
路由
得益于
import { Controller, Get } from "@nestjs/common";
@Controller("cats")
export class CatsController {
@Get()
findAll(): string {
return "This action returns all cats";
}
}
我们可以用 $ nest g controller cats
来自动生成上面的代码。
-
标准模式(建议的
) :使用内置方法时,如果返回一个JavaScript 对象或者数据,将自动序列化成JSON ,如果是字符串将默认不会序列化,响应的返回状态码 默认 总是200 ,除非是POST 请求会默认设置成201 。可以使用@HttpCode() 装饰器来改变它 -
指定框架:也可以使用指定框架的请求处理方法,比如
Express 的响应对象。可以使用@Res() 装饰器来装饰响应对象使用,这样以来你就可以使用类Express API 的方式处理响应了:response.status(200).send()
路由的注册顺序与控制器类中的方法顺序相关,如果你先装饰了一个
路由通配符
*
)表示匹配任意的字母组合。
@Get('ab*cd')
'ab*cd'
abcd
ab_cd
abecd
?
+
*
()
通配符 | 说明 | 示例 | 匹配 | 不匹配 |
---|---|---|---|---|
* |
匹配任意数量的任意字符 | Law* |
Law , Laws , or Lawyer |
GrokLaw , La , or aw |
*Law* |
Law , GrokLaw , or Lawyer . |
La , or aw |
||
? |
匹配任意单个字符 | ?at |
Cat , cat , Bat or bat |
at |
[abc] |
匹配方括号中的任意一个字符 | [CB]at |
Cat or Bat |
cat or bat |
[a-z] |
匹配字母、数字区间 | Letter[0-9] |
Letter0 , Letter1 , Letter2 up to Letter9 |
Letters , Letter or Letter10 |
路由参数
通常我们需要设置一些动态的路由来接收一些客户端的查询参数,通过指定路由参数可以很方便的捕获到
@Get(':id')
findOne(@Param() params): string {
console.log(params.id);
return `This action returns a #${params.id} cat`;
}
通过使用@Get()
中的的参数字典,
当然,就像前面学到的参数装饰器也可以指定到具体的某个参数值:
@Get(':id')
findOne(@Param('id') id): string {
return `This action returns a #${id} cat`;
}
请求对象
处理器一般需要访问到请求对象。一般配合
装饰器 | 参数值 |
---|---|
@Request() |
req |
@Response() |
res |
@Next() |
next |
@Session() |
req.session |
@Param(key?: string) |
req.params / req.params[key] |
@Body(key?: string) |
req.body / req.body[key] |
@Query(key?: string) |
req.query / req.query[key] |
@Headers(name?: string) |
req.headers / req.headers[name] |
譬如,我们只需要处理请求的查询字符串(query string
@Get()
getHello(@Query() q: String): string {
console.log(q)
return this.appService.getHello();
}
// http://localhost:3000/?test=a
除了使用
请求体
现在我们习惯以
import { IsInt, IsString } from "class-validator";
export class CreateCatDto {
@IsString()
readonly name: string;
@IsInt()
readonly age: number;
@IsString()
readonly breed: string;
}
然后在请求函数中我们可以直接获取该对象:
@Post()
@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
响应对象
状态码
响应的默认状态码是
@Post()
@HttpCode(204)
create() {
return 'This action adds a new cat';
}
如果想动态指定状态码,就要使用
响应头
同样的我们可以使用
@Post()
@Header('Cache-Control', 'none')
create() {
return 'This action adds a new cat';
}
返回文件流
在
// This is my controller
async getFile(@Param('bucketname') bucketName: string, @Param('filename') fileName: string, @Res() response) {
return (await this.appService.getFile(bucketName, fileName)).pipe(response);
}
这里以常见的打印
// Controller
import { Post, Body, Res } from '@nestjs/common';
import { Response } from 'express';
@Post('pdf')
async print(
@Body(new JoiValidationPipe(printSchema)) body: PrintDto,
@Res() res: Response,
) {
const buffer = await this.printService.printPdf(body);
const stream = this.printService.getReadableStream(buffer);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': buffer.length,
});
stream.pipe(res);
}
// PrintService
import { Readable } from 'stream';
// import PrintDto
async printPdf(body: PrintDto): Promise<Buffer> {
// ...
return buffer;
}
getReadableStream(buffer: Buffer): Readable {
const stream = new Readable();
stream.push(buffer);
stream.push(null);
return stream;
}