控制器
提示
要使用内置的 validation 快速创建 CRUD 控制器,你可以使用 CLI 的
增删改查生成器
: nest g resource [name]
路由
在下面的示例中,我们将使用 @Controller() 装饰器,即 required 来定义一个基本控制器。 我们将指定 cats
的可选路由路径前缀。 在 @Controller()
装饰器中使用路径前缀可以让我们轻松地对一组相关路由进行分组,并最大限度地减少重复代码。 例如,我们可以选择将一组路由分组,这些路由管理与路由 /cats
下的猫实体的交互。 在这种情况下,我们可以在 @Controller()
装饰器中指定路径前缀 cats
,这样我们就不必为文件中的每个路由重复该部分路径。
import { Controller, Get } 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()
定义了一个端点来处理所有这些。
提示
要使用 CLI 创建控制器,只需执行 $
nest g controller [name]
命令。
路由通配符
也支持基于模式的路由。 例如,星号用作通配符,将匹配任何字符组合。
@Get('ab*cd')
findAll() {
return 'This route uses a wildcard';
}
'ab*cd'
路由路径将匹配 abcd
、ab_cd
、abecd
等。 字符 ?
、+
、*
和 ()
可以在路由路径中使用,并且是它们对应的正则表达式的子集。 连字符 (-
) 和点 (.)
由基于字符串的路径逐字解释。
警告
仅 express 支持路由中间的通配符。
装饰器
装饰器 | 关键词 |
---|---|
@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()
的别名。 两者都直接暴露底层原生平台 response
对象接口。 使用它们时,你还应该导入底层库(例如 @types/express
)的类型以充分利用它们。 请注意,当你在方法处理程序中注入 @Res()
或 @Response()
时,你将 Nest 放入该处理程序的 库特定模式 中,并且你负责管理响应。 这样做时,你必须通过调用 response
对象(例如,res.json(...)
或 res.send(...)
)来触发某种响应,否则 HTTP 服务器将挂起。
状态码
默认情况下响应 状态码 始终为 200,但 POST 请求除外,其为 201。 我们可以通过在处理程序级别添加 @HttpCode(...)
装饰器来轻松更改此行为。
@Post()
@HttpCode(204)
create() {
return 'This action adds a new cat';
}
提示
从
@nestjs/common
包中导入HttpCode
。
标头
要指定自定义响应标头,你可以使用 @Header() 装饰器或库特定的响应对象(并直接调用 res.header())。
@Post()
@Header('Cache-Control', 'none')
create() {
return 'This action adds a new cat';
}
提示
从
@nestjs/common
包中导入Header
。
重定向
要将响应重定向到特定 URL,你可以使用 @Redirect()
装饰器或库特定的响应对象(并直接调用 res.redirect()
)。
@Redirect()
有两个参数,url
和 statusCode
,两者都是可选的。 如果省略,statusCode
的默认值为 302
(Found
)。
@Post()
@Redirect('https://docs.nestjs.com', 301)
create() {
return 'This action adds a new cat';
}
提示
从
@nestjs/common
包中导入Redirect
。 有时你可能希望动态确定 HTTP 状态代码或重定向 URL。 通过返回遵循HttpRedirectResponse
接口(来自@nestjs/common
)的对象来完成此操作。
返回值将覆盖传递给 @Redirect()
装饰器的任何参数。 例如:
@Get('docs')
@Redirect('https://nest.nodejs.cn', 302)
getDocs(@Query('version') version) {
if (version && version === '5') {
return { url: 'https://nest.nodejs.cn/v5/' };
}
}
路由参数
当你需要接受 动态数据 作为请求的一部分时,具有静态路径的路由将不起作用(例如,GET /cats/1
以获取 ID 为 1
的猫)。 为了定义带参数的路由,我们可以在路由的路径中添加路由参数 tokens,以捕获请求 URL 中该位置的动态值。 下面 @Get()
装饰器示例中的路由参数令牌演示了这种用法。 可以使用 @Param()
装饰器访问以这种方式声明的路由参数,应将其添加到方法签名中。
提示: 带参数的路由应该在任何静态路径之后声明。 这可以防止参数化路径拦截发往静态路径的流量。
@Get(':id')
findOne(@Param() params: any): string {
console.log(params.id);
return `This action returns a #${params.id} cat`;
}
@Param()
用于装饰方法参数(上例中的 params
),并使 route 参数可用作方法主体内该装饰方法参数的属性。 如上面的代码所示,我们可以通过引用 params.id
来访问 id
参数。 也可以传入一个特定的参数 token 给装饰器,然后在方法体中直接通过名称引用路由参数。
提示: 从
@nestjs/common
包中导入Param
。
@Get(':id')
findOne(@Param('id') id: string): string {
return `This action returns a #${id} cat`;
}
子域路由
@Controller
装饰器可以采用 host
选项来要求传入请求的 HTTP 主机匹配某个特定值。
@Controller({ host: 'admin.example.com' })
export class AdminController {
@Get()
index(): string {
return 'Admin page';
}
}
警告:由于 Fastify 缺乏对嵌套路由的支持,因此在使用子域路由时,应使用(默认)Express 适配器。 与路由
path
类似,hosts
选项可以使用标记来捕获主机名中该位置的动态值。 下面@Controller()
装饰器示例中的主机参数令牌演示了这种用法。 可以使用@HostParam()
装饰器访问以这种方式声明的主机参数,应将其添加到方法签名中
@Controller({ host: ':account.example.com' })
export class AccountController {
@Get()
getInfo(@HostParam('account') account: string) {
return account;
}
}
作用域
对于来自不同编程语言背景的人来说,得知在 Nest 中几乎所有内容都是在传入请求之间共享的,可能会出乎意料。 我们有一个到数据库的连接池、具有全局状态的单例服务等。请记住,Node.js 不遵循请求/响应多线程无状态模型,在该模型中每个请求都由单独的线程处理。 因此,对于我们的应用,使用单例实例完全是 safe。
异步性
我们热爱现代 JavaScript,我们知道数据提取主要是 asynchronous。 这就是 Nest 支持 async
功能并与它配合使用的原因。
提示:详细了解
async / await
功能 此处
每个异步函数都必须返回 Promise
。 这意味着你可以返回一个 Nest 能够自行解析的延迟值。 让我们看一个例子:
@Get()
async findAll(): Promise<any[]> {
return [];
}
上面的代码是完全有效的。 此外,Nest 路由处理程序更强大,因为它能够返回 RxJS 可观察流。 Nest 将自动订阅下面的源并获取最后触发的值(一旦流完成)。
以上两种方法都有效,你可以使用适合你要求的任何方法。