控制器
控制器是API的入口点。它们定义HTTP端点并通过提取数据、调用业务逻辑和返回响应来处理传入请求。
概述
在YasuiJS中,控制器是使用@Controller()
装饰器修饰的类,用于将相关端点组合在一起。控制器中的每个方法代表一个HTTP端点,使用@Get()
、@Post()
等方法装饰器定义。
控制器方法可以简单地返回任何值,这些值将自动序列化为JSON并返回200状态码。如果需要更多控制,你可以使用@Res()
直接访问Express响应对象,并使用原生Express方法如res.json()
、res.status()
或res.sendFile()
。
import { Controller, Get, Post } from 'yasui';
@Controller('/api/users')
export class UserController {
@Get('/')
getAllUsers() {
return { users: [] }; // 自动返回JSON
}
}
控制器装饰器
@Controller()
装饰器将类标记为控制器并为其所有路由定义基础路径。
基本用法
@Controller('/api/users')
export class UserController {
// 所有路由都将以/api/users为前缀
}
使用中间件
你可以为控制器中的所有路由应用中间件。在中间件中了解更多。
@Controller('/api/users', AuthMiddleware)
export class UserController {
// 所有路由都将应用AuthMiddleware
}
HTTP方法装饰器
YasuiJS为所有标准HTTP方法提供装饰器。每个装饰器接受一个路径参数(必需)和可选的中间件参数。
@Get(path, ...middlewares)
- 处理GET请求@Post(path, ...middlewares)
- 处理POST请求@Put(path, ...middlewares)
- 处理PUT请求@Delete(path, ...middlewares)
- 处理DELETE请求@Patch(path, ...middlewares)
- 处理PATCH请求
基本路由
@Controller('/api/users')
export class UserController {
@Get('/')
getAllUsers() {
return { users: [] };
}
@Post('/')
createUser() {
return { message: '用户已创建' };
}
@Get('/:id')
getUser() {
// 在路径中使用Express风格的路由参数:
// 路由: GET /api/users/123
return { user: {} };
}
@Put('/:id')
updateUser() {
return { message: '用户已更新' };
}
@Delete('/:id')
deleteUser() {
return { message: '用户已删除' };
}
}
路由级中间件
对特定路由应用中间件。在中间件中了解更多。
@Controller('/api/users')
export class UserController {
@Get('/', ValidationMiddleware)
getAllUsers() {}
}
参数装饰器
使用参数装饰器从HTTP请求中提取数据。YasuiJS根据TypeScript类型自动转换参数以获得更好的类型安全性。
提取请求体
@Body(name?)
- 提取请求体数据
@Controller('/api/users')
export class UserController {
@Post('/')
createUser(@Body() userData: any) {
// 提取整个请求体
return { created: userData };
}
@Post('/partial')
updateUser(@Body('name') name: string) {
// 从请求体中提取特定字段
return { updatedName: name };
}
}
提取参数和请求头
@Param(name, items?)
- 提取路由参数@Query(name, items?)
- 提取查询参数@Header(name, items?)
- 提取请求头
参数会根据其TypeScript类型自动转换。对于非字符串类型的数组,你必须将项目类型指定为第二个参数:
@Controller('/api/users')
export class UserController {
@Get('/:id')
getUser(@Param('id') id: number) {} // 转换为数字
@Get('/search/:term')
searchUsers(
@Param('term') term: string,
@Header('x-api-version') version: number,
@Query('filters', [Boolean]) filters: boolean[],
@Query('settings') settings: { theme: string } | null,
) {
// version: number (请求头转换为数字)
// filters: boolean[] (来自 ?filters=true&filters=false&filters=1)
// settings: object (来自 ?settings={"theme":"dark"} - JSON解析,失败则为null)
return { page, active, tags, priorities };
}
}
自动参数类型转换
YasuiJS根据TypeScript类型自动转换参数:
基本类型
- string - 无转换(默认)
- number - 转换为数字,无效则返回NaN
- boolean - 将"true"/"1"转换为true,其他都转换为false
- Date - 转换为Date对象,无效则返回Invalid Date
- object - 解析JSON字符串,如
?data={"key":"value"}
,失败则返回null
数组类型
TypeScript在运行时无法检测数组项目类型,因此对于非字符串数组必须指定[Type]
:
- string[] - 无需额外配置(默认行为)
- number、boolean或Date数组 - 必须使用第二个参数指定项目类型
类型化数组语法:
@Query('paramName', [Type]) paramName: Type[]
@Param('paramName', [Type]) paramName: Type[]
@Header('headerName', [Type]) headerName: Type[]
请求对象访问
@Req()
- 访问Express Request对象@Res()
- 访问Express Response对象@Next()
- 访问Express NextFunction
import { Request, Response, NextFunction } from 'yasui';
@Controller('/api/users')
export class UserController {
@Get('/')
getAllUsers(
@Req() request: Request,
@Res() response: Response,
@Next() next: NextFunction
) {
console.log(request.url);
return { users: [] };
}
}
响应处理
YasuiJS自动处理响应序列化和状态码。
自动JSON响应
返回任何数据都将自动序列化为JSON:
@Controller('/api/users')
export class UserController {
@Get('/')
getUsers() {
// 自动返回JSON,状态码200
return { users: ['John', 'Jane'] };
}
@Get('/string')
getString() {
// 将字符串作为JSON返回
return 'Hello World';
}
@Get('/number')
getNumber() {
// 将数字作为JSON返回
return 42;
}
}
自定义状态码
@HttpStatus(code)
- 设置自定义HTTP状态码
使用@HttpStatus()
装饰器设置自定义状态码:
import { HttpStatus, HttpCode } from 'yasui';
@Controller('/api/users')
export class UserController {
@Post('/alt')
@HttpStatus(201) // 使用数字
createUserAlt(@Body() userData: any) {
// 返回状态码201 Created
return { created: userData };
}
@Delete('/:id')
@HttpStatus(HttpCode.NO_CONTENT) // 使用HttpCode枚举
deleteUser(@Param('id') id: string) {
// 返回状态码204 No Content
// 204可以不返回任何内容
}
}
手动响应处理
要完全控制,使用Express响应对象:
import { Response } from 'yasui';
@Controller('/api/users')
export class UserController {
@Get('/custom')
customResponse(@Res() res: Response) {
res.status(418).json({
message: "我是茶壶",
custom: true
});
// 直接使用res时不要返回任何内容
}
}
错误处理
让框架自动处理错误或抛出自定义错误。完整的错误处理详情,请参见错误处理。