控制器
控制器负责处理传入请求并向客户端返回响应。
控制器的作用是接收应用程序的特定请求。 路由机制控制哪个控制器接收哪些请求。 通常情况下,每个控制器都有不止一个路由,不同的路由可以指定不同的操作。
为了创建基本控制器,我们使用类和装饰器。 装饰器将类与所需的元数据关联起来,并使Nest能够创建路由映射(将请求绑定到相应的控制器)。
为了快速创建带有内置验证的CRUD控制器,
您可以使用CLI的CRUD生成器:nest g resource [name]
路由
在下面的示例中,我们将使用@Controller()
装饰器,这是定义基本控制器所必需的。
我们将指定一个可选的路径前缀:cats
。在@Controller()
装饰器中使用路径前缀
可以让我们轻松地将一组相关的路由分组,并最大限度地减少重复代码。
例如,我们可以选择将一组管理与猫实体交互的路由归类到路由/cats
下。
在这种情况下,我们可以再@Controller()
装饰器中指定路径前缀cats
,
这样就不必为文件中的每个路由重复写路径前缀的这一部分。
import { Controller, Get } from '@nestjs/commom';
@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}
要使用CLI创建控制器,只需执行nest g controller [name]
命令
findAll()
方法之前的@Get()
HTTP请求方法装饰器告诉Nest为HTTP请求的特定端点创建处理程序。
端点对应于HTTP请求方法(在本例中为GET)和路由路径。路由路径是什么?
处理程序的路由路径是通过连接为控制器声明的(可选)前缀和方法装饰器中指定的任何路径来确定的。
由于我们已经为每个路由(cats
)声明了一个前缀,并且没有在装饰器中添加任何路径信息,
因此Nest会将GET/cats
请求映射到此处理程序。
如前所述,路径包括可选的控制器路径前缀和请求方法装饰器中声明的任何路径字符串。
例如,cats
的路径前缀与装饰器@Get('breed')
结合将为GET /cats/breed
等请求生成路由映射。
在上面的示例中,当前此端点发出GET请求时,Nest将请求路由到我们用户定义的findAll()
方法。
请注意,我们在这里选择的方法名称是完全任意 的。显然,我们必须声明一个方法来绑定路由,
但Nest并不赋予所选方法名称任何意义。
此方法将返回200状态码和关联的响应,在本例中只是一个字符串。为什么会发生这种情况? 为了解释这一点,我们首先介绍Nest使用两种不同选项来操纵响应的概念:
-
标准(推荐)
使用此内置方法,当请求处理程序返回 JavaScript 对象或数组时,它将自动序列化为 JSON。然而,当它返回 JavaScript 基本类型(例如字符串、数字、布尔值)时,Nest 将仅发送该值,而不尝试对其进行序列化。 这使得响应处理变得简单:只需返回值,Nest 就会处理其余的事情。
此外,默认情况下,响应的状态码始终为200,但使用 201 的 POST 请求除外。 我们可以通过在处理程序级别添加
@HttpCode(...)
装饰器来轻松更改此行为(请参阅状态代码)。 -
特定库
我们可以使用特定于库的(例如 Express)响应对象,可以使用方法处理程序签名中的
@Res()
装饰器注入该对象(例如findAll(@Res() response)
)。 通过这种方法,您可以使用该对象公开的本机响应处理方法。例如,使用Express,您可以使用像response.status(200).send()
这样的代码构建响应。
Nest 检测处理程序何时使用@Res()
或@Next()
,表明您已选择特定库的选项。
如果同时使用两种方法,则该单一路线的标准方法将自动禁用,并且将不再按预期工作。
要同时使用这两种方法(例如,通过注入响应对象以仅设置 cookie/headers,但仍将其余部分留给框架),
您必须在@Res({ passthrough: true })
装饰器设置passthrough
为true
。
请求对象
处理程序通常需要访问客户端请求的详细信息。Nest 提供对底层平台(默认为 Express)请求对象的访问。
我们可以在处理程序的签名中添加 @Req()
装饰器,指示 Nest 注入请求对象,从而访问请求对象
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';
}
}
为了利用express
的类型(如上面的request: Request
请求参数示例),请安装@types/express
包
request对象代表HTTP请求,
具有请求查询字符串、参数、HTTP头信息和正文的属性。
在大多数情况下,无需手动抓取这些属性,我们可以使用专有的装饰器,
例如@Body()
或@Query()
,
这些装饰器开箱即用。下面列出所提供的装饰器以及它们所代表的特定平台对象。
@Request(), @Req() | req |
---|---|
@Response(), @Res() * | 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] |
@Ip() | req.ip |
@HostParam() | req.hosts |
*
为了与底层HTTP平台(例如Express和Fastify)之间的类型兼容,Nest提供了@Res
和@Response()
装饰器。
@Res()
只是@Response()
的别名。两者都直接公开底层平台响应对象接口。
使用它们时,您还应该导入底层库的类型(例如@types/express
)以充分利用他们。
请注意,当您在方法处理程序中注入@Res()
或@Response()
时,
您会将Nest置于该处理程序的特定库的模式,并且您将负责管理响应。
执行此操作时,您必须通过调用响应对象来发出某种类型的响应,否则HTTP服务器将挂起。
例如(res.json(...)
或res.send(...)
)
要了解如何创建您自己的自定义装饰器,请访问本章。
资源
之前,我们定义了一个端点(endpoint)来获取cats资源(GET路由)。 我们还希望提供一个创建新纪录的端点。 为此,我们创建POST处理程序。
import { Controller, Get, Post } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Post()
create(): string {
return 'This action adds a new cat';
}
@Get
findAll(): string {
return 'This action returns all cats';
}
}
就是这么简单。Nest为所有标准HTTP方法提供了装饰器:
@Get
@Post
@Put
@Delete()
@Patch()
@Options()
@Head()
@All()
其中All()
定义了一个处理所有这些端点。
路由通配符
Nest还支持基于模式的路由。例如星号(asterisk)用作通配符,将匹配任意字符组合。
@Get('ab*cd')
findAll() {
return 'This route uses a wildcard';
}
ab*cd
路由路径将匹配abcd
,ab_cd
,abecd
。
字符?
、+
、*
、()
可以在路径中使用,它们是正则表达式的子集。
连字符(-
)和点字符(.
)在基于字符串的路径中按字面解释。
仅express支持路由中间的通配符
状态码
如前所述,默认情况下响应状态码始终为200,POST请求除外,该代码为201。
我们可以通过在处理程序级别添加@HttpCode(...)
装饰器来轻松更改此行为。
@Post()
@HttpCode(204)
create() {
return 'This action adds a new cat';
}
从@nestjs/common
包导入HttpCode
通常,您的状态码不是静态的,而是取决于各种因素。
在这种情况下,您可以使用特定库的响应(使用@Res()
注入)对象(或者,如果发生错误,则抛出异常)。
信息头
要指定自定义响应信息头,您可以使用
@Header
装饰器- 或特定库的响应对象(并直接调用
res.header()
)
@Post()
@Header('Cache-Control', 'none')
create() {
return 'This action adds a new cat'
}
从@nestjs/common
包中导入Header