控制器负责处理传入的请求和向客户端返回响应。为了创建控制器,我们必须使用
装饰器
。装饰器将类与所需的元数据关联,并使Nest
能够创建路由映射(将请求绑定到相应的控制器)
路由
创建控制器的方法是 nest g co 控制器名
cats.controller.ts
import { Controller, Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}
@Controller('cats') 装饰器用于定义控制器,cats为路径前缀,用于路由分组,以区分不同控制器下的路由处理程序。
@Get() 表明这时一个路由处理程序,用GET方法请求,里面可以带参数,例如, @Get('profile')
会为请求生成路由映射 GET /cats/profile
。路由处理程序有两种方式产生响应,一种是标准模式,也是推荐做法,当返回是js对象或数组时Nest会自动将其序列化为Json返回,如果是基本类型,如number、string、boolean,则Nest原样返回,第二种是通过 @Res() 注入方式(后面会详细说),。注意,一个路由处理程序只能用其中一种
Request
要获得客户端请求细节,可以用 @Req() 将请求对象注入到处理程序
cats.controller.ts
import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';
@Controller('cats')
export class CatsController {
@Get()
findAll(@Req() request: Request): string {
return 'This action returns all cats';
}
}
Request 表示HTTP请求,包括查询字符串、参数、HTTP 标头和正文属性。大多数情况下,不用手动获取它们,可以使用特定装饰器来获取,如 @Body() 。某些情况下,使用 @Req() 注入还是很有用的,如身份认证时的 req.user ,详细参考 https://docs.nestjs.com/techniques/authentication。注意,如果使用了 @Res,则必须用
res.json(…)
或res.send(…)
发出响应,否则得不到任何响应
方法
Nest 有 @Get() 、@Put() 、@Delete()、@Patch()、@Options()、@Head()、@All()等装饰器标志不同HTTP请求的处理程序
路由通配符
路由支持模式匹配,*表示通配符,匹配任何字符,?、+、()都是特殊字符,但 - 和 .不作为特殊字符
@Get('ab*cd')
findAll() {
return 'This route uses a wildcard';
}
状态码
默认情况下,响应的状态码总是200,POST请求响应码是201。可以用@HttpCode()返回不同响应码
@Post()
@HttpCode(204)
create() {
return 'This action adds a new cat';
}
注意,即使内部某个环节发生错误,没有获得预期结果,只要没有抛出异常,状态码也会是 @HttpCode() 中指定的,这通常不是我们想要的,解决方案一种方式是抛出异常,另一种是通过 @Res 注入
Headers
设置响应头有两种方式,一种是 @Header() 装饰器,另一种是 @Req 装饰器,并通过 req.header()设置
@Post()
@Header('Cache-Control', 'none')
create() {
return 'This action adds a new cat';
}
重定向
@Redirect() 用于路由重定向,第一个参数时重定向url,第二个参数可以省略,默认是302
@Get()
@Redirect('https://nestjs.com', 301)
如果希望动态决定HTTP响应码或重定向URL,可以返回下列形式的对象
{
"url": string,
"statusCode": number
}
这个对象会覆盖所有传递给 @Redirect() 装饰器的参数,如
@Get('docs')
@Redirect('https://docs.nestjs.com', 302)
getDocs(@Query('version') version) {
if (version && version === '5') {
return { url: 'https://docs.nestjs.com/v5/' };
}
}
// 如果version为5,重定向到https://docs.nestjs.com/v5/,否则重定向到https://docs.nestjs.com
路由参数
在路由中添加路由参数标记可以获得URL中的动态值,通过 @Param() 装饰器访问以这种方式声明的路由参数
@Get(':id')
findOne(@Param() params): string {
console.log(params.id);
return `This action returns a #${params.id} cat`;
}
请求 GET /cats/1 时,params.id为1,还可以向装饰器传入值,获得指定路由参数
@Get(':id')
findOne(@Param('id') id): string {
return `This action returns a #${id} cat`;
}
子域路由
如果只用NestJS做后台开发,可以不考虑这个问题。https://docs.nestjs.com/controllers#sub-domain-routing
Async/Await
数据读取大部分是异步的,这些异步函数必须返回Promise
@Get()
async findAll(): Promise {
return [];
}
POST参数
@Body() 获得 post 发送的数据
create-cat.dto.ts
export class CreateCatDto {
readonly name: string;
readonly age: number;
readonly breed: string;
}
cats.controller.ts
@Post()
async create(@Body() createCatDto: CreateCatDto) {
return 'This action adds a new cat';
}
最后一步
Nest并不知道控制器的存在,必须在module中声明controllers数组,这个数组可以在每个模块保留一个,然后在app.module.ts的@modules()中把这个模块import进来
app.module.tsJS
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
@Module({
controllers: [CatsController],
})
export class AppModule {}
@Res() 注入
import { Controller, Get, Post, Res, HttpStatus } from '@nestjs/common';
import { Response } from 'express';
@Controller('cats')
export class CatsController {
@Post()
create(@Res() res: Response) {
res.status(HttpStatus.CREATED).send();
}
@Get()
findAll(@Res() res: Response) {
res.status(HttpStatus.OK).json([]);
}
}
这种响应方式提供响应对象的完全控制(标准操作,库特定的功能等)在某些方面允许更多的灵活性,但同时会使拦截器和
@HttpCode()
装饰器失效