APIサーバーを構築していると、 APIの後方互換を持たせるために、/v1/
や/v2/
といったREST APIにバージョンを持たせると思います。
3年前にNestJSでAPIバージョニングをするという記事が書かれていますが、NestJS v8から、新しい機能として実装されましたので、その機能を紹介します。
手順
有効にする方法は至って簡単
次のコードを追加するだけ!
main.ts
const app = await NestFactory.create(AppModule);
+ app.enableVersioning({
+ type: VersioningType.URI,
+ });
await app.listen(3000);
Controllerに宣言するパターン
例えば次のようなコントローラー
user.controller.ts
+ @Controller({ version: ['1', '2'], path: 'users' })
+ // `https://api.example.com/v1/user` -> OK
+ // `https://api.example.com/v2/user` -> OK
+ // `https://api.example.com/v3/user` -> 404
export class UserController {
constructor(private userService: UserService) {}
@Get('/:id')
findOneById(@Param('id') id: string) {
return this.userService.findOneById(id)
}
@Post()
async create(@Body() body: CreateUserDTO) {
const result = await this.userService.create(body)
return result
}
@Put('/:id')
async update(@Body() body: UpdateUserDTO, @Param('id') id: string) {
const result = await this.userService.update(id, body)
return result
}
}
Routeに宣言するパターン
user.controller.ts
@Controller('users')
export class UserController {
constructor(private userService: UserService) {}
+ @Version(['1', '2'])
+ // `https://api.example.com/v1/user` -> OK
+ // `https://api.example.com/v2/user` -> OK
+ // `https://api.example.com/v3/user` -> 404
@Get('/:id')
findOneById(@Param('id') id: string) {
return this.userService.findOneById(id)
}
@Post()
async create(@Body() body: CreateUserDTO) {
const result = await this.userService.create(body)
return result
}
@Put('/:id')
async update(@Body() body: UpdateUserDTO, @Param('id') id: string) {
const result = await this.userService.update(id, body)
return result
}
}
デフォルトのバージョンを宣言する
defaultVersion
を指定しておくと、全てのController、Routeにデフォルトのバージョンが宣言されます。
main.ts
const app = await NestFactory.create(AppModule);
app.enableVersioning({
type: VersioningType.URI,
+ defaultVersion: ['1', '2'],
});
await app.listen(3000);
VERSION_NEUTRAL
について
VERSION_NEUTRAL
を宣言した場合、そのAPIにはバージョンが宣言されません。
user.controller.ts
@Controller('users')
export class UserController {
constructor(private userService: UserService) {}
+ @Version([VERSION_NEUTRAL])
+ // `https://api.example.com/user` -> OK
+ // `https://api.example.com/v1/user` -> 404
@Get('/:id')
findOneById(@Param('id') id: string) {
return this.userService.findOneById(id)
}
@Post()
async create(@Body() body: CreateUserDTO) {
const result = await this.userService.create(body)
return result
}
@Put('/:id')
async update(@Body() body: UpdateUserDTO, @Param('id') id: string) {
const result = await this.userService.update(id, body)
return result
}
}
公式ドキュメント
詳しくは公式ドキュメントがわかりやすいです。