Skip to content

控制器

提示

要使用内置的 validation 快速创建 CRUD 控制器,你可以使用 CLI 的 增删改查生成器: nest g resource [name]

路由

在下面的示例中,我们将使用 @Controller() 装饰器,即 required 来定义一个基本控制器。 我们将指定 cats 的可选路由路径前缀。 在 @Controller() 装饰器中使用路径前缀可以让我们轻松地对一组相关路由进行分组,并最大限度地减少重复代码。 例如,我们可以选择将一组路由分组,这些路由管理与路由 /cats 下的猫实体的交互。 在这种情况下,我们可以在 @Controller() 装饰器中指定路径前缀 cats,这样我们就不必为文件中的每个路由重复该部分路径。

js
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] 命令。

路由通配符

也支持基于模式的路由。 例如,星号用作通配符,将匹配任何字符组合。

js
@Get('ab*cd')
findAll() {
  return 'This route uses a wildcard';
}

'ab*cd' 路由路径将匹配 abcdab_cdabecd 等。 字符 ?+*() 可以在路由路径中使用,并且是它们对应的正则表达式的子集。 连字符 (-) 和点 (.) 由基于字符串的路径逐字解释。

警告

仅 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(...) 装饰器来轻松更改此行为。

js
@Post()
@HttpCode(204)
create() {
  return 'This action adds a new cat';
}

提示

@nestjs/common 包中导入 HttpCode

标头

要指定自定义响应标头,你可以使用 @Header() 装饰器或库特定的响应对象(并直接调用 res.header())。

js
@Post()
@Header('Cache-Control', 'none')
create() {
  return 'This action adds a new cat';
}

提示

@nestjs/common 包中导入 Header

重定向

要将响应重定向到特定 URL,你可以使用 @Redirect() 装饰器或库特定的响应对象(并直接调用 res.redirect())。

@Redirect() 有两个参数,urlstatusCode,两者都是可选的。 如果省略,statusCode 的默认值为 302 (Found)。

js
@Post()
@Redirect('https://docs.nestjs.com', 301)
create() {
  return 'This action adds a new cat';
}

提示

@nestjs/common 包中导入 Redirect。 有时你可能希望动态确定 HTTP 状态代码或重定向 URL。 通过返回遵循 HttpRedirectResponse 接口(来自 @nestjs/common)的对象来完成此操作。

返回值将覆盖传递给 @Redirect() 装饰器的任何参数。 例如:

js
@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() 装饰器访问以这种方式声明的路由参数,应将其添加到方法签名中。

提示: 带参数的路由应该在任何静态路径之后声明。 这可以防止参数化路径拦截发往静态路径的流量。

js
@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

js
@Get(':id')
findOne(@Param('id') id: string): string {
  return `This action returns a #${id} cat`;
}

子域路由

@Controller 装饰器可以采用 host 选项来要求传入请求的 HTTP 主机匹配某个特定值。

js
@Controller({ host: 'admin.example.com' })
export class AdminController {
  @Get()
  index(): string {
    return 'Admin page';
  }
}

警告:由于 Fastify 缺乏对嵌套路由的支持,因此在使用子域路由时,应使用(默认)Express 适配器。 与路由 path 类似,hosts 选项可以使用标记来捕获主机名中该位置的动态值。 下面 @Controller() 装饰器示例中的主机参数令牌演示了这种用法。 可以使用 @HostParam() 装饰器访问以这种方式声明的主机参数,应将其添加到方法签名中

js
@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 能够自行解析的延迟值。 让我们看一个例子:

js
@Get()
async findAll(): Promise<any[]> {
  return [];
}

上面的代码是完全有效的。 此外,Nest 路由处理程序更强大,因为它能够返回 RxJS 可观察流。 Nest 将自动订阅下面的源并获取最后触发的值(一旦流完成)。

以上两种方法都有效,你可以使用适合你要求的任何方法。

Released under the MIT License.