NestJS之02-RESTful 风格设计

709 阅读6分钟

1. 什么是RESTful

RESTful 是一种设计 Web API 的风格,强调使用统一资源标识符(Uniform Resource Identifier,URI)和 HTTP 协议对资源进行操作,以实现资源的状态转换和状态展示。以下是 RESTful 设计的一些基本约束和最佳实践:

  1. 资源是指网络上的一种实体,可以是一种文档、一幅图片、一种服务、一组数据等。每个资源都有唯一的标识符(URI)来标识。
  2. 使用 HTTP 动词(GET、POST、PUT、DELETE 等)对资源进行操作,并使用 HTTP 响应码来表示操作结果。
  3. 使用客户端-服务器架构,客户端和服务器之间的界面由资源标识符隔离,这样可以使得客户端和服务器可以独立演化,并提高了系统的可扩展性。
  4. 尽量使用无状态通信,减少对服务器的负担,并提高系统的可缓存性。
  5. 为每个资源定义资源的表现形式,并使用 Content-Type 标头来指示所返回的内容类型。
  6. 路径参数和查询参数分别用于标识和操作资源,路径参数用于标识资源,查询参数用于操作资源。

例如:

操作传统接口RESTful接口
获取列表http://localhost:8080/api/get_list?id=1http://localhost:8080/api/get_list/1 使用GET
更新http://localhost:8080/api/update_list?id=1接口同上 使用PATCH
删除http://localhost:8080/api/delete_list?id=1接口同上 使用DELETE
增加http://localhost:8080/api/add_list接口同上 使用POST

根据 RESTful API 的设计原则,一般使用以下 HTTP 请求方法来进行增删改查:

  • GET:获取指定资源,一般用于查询操作。
  • POST:创建一条新资源,一般用于新增操作。
  • PUT / PATCH:更新指定资源,一般用于修改操作。PUT 用于替换整个资源,PATCH 用于部分更新。
  • DELETE:删除指定资源,一般用于删除操作。

在 NestJS 中,通过使用 @Get@Post@Put@Patch@Delete 装饰器,可以实现对应的 HTTP 请求方法。在控制器的方法中,可以使用 @Param@Query@Body 等装饰器来获取请求参数,并使用服务层提供的方法进行相应的业务操作。

2. NestJS中如何使用

user1.controller.ts

import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { User1Service } from './user1.service';
import { CreateUser1Dto } from './dto/create-user1.dto';
import { UpdateUser1Dto } from './dto/update-user1.dto';

@Controller('user1')
export class User1Controller {
  constructor(private readonly user1Service: User1Service) {}

  @Post()
  create(@Body() createUser1Dto: CreateUser1Dto) {
    return this.user1Service.create(createUser1Dto);
  }

  @Get()
  findAll() {
    return this.user1Service.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.user1Service.findOne(+id);
  }

  @Patch(':id')
  update(@Param('id') id: string, @Body() updateUser1Dto: UpdateUser1Dto) {
    return this.user1Service.update(+id, updateUser1Dto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.user1Service.remove(+id);
  }
}

user1.servive.ts

import { Injectable } from '@nestjs/common';
import { CreateUser1Dto } from './dto/create-user1.dto';
import { UpdateUser1Dto } from './dto/update-user1.dto';

@Injectable()
export class User1Service {
  create(createUser1Dto: CreateUser1Dto) {
    return 'This action adds a new user1';
  }

  findAll() {
    return `This action returns all user1`;
  }

  findOne(id: number) {
    return `This action returns a #${id} user1`;
  }

  update(id: number, updateUser1Dto: UpdateUser1Dto) {
    return `This action updates a #${id} user1`;
  }

  remove(id: number) {
    return `This action removes a #${id} user1`;
  }
}

image.png

开启3000端口进行请求:

参数携带id使用 /id

查询所有 image.png 查询单条

image.png

实现其他操作修改请求方式,浏览器地址栏默认是get请求。

3. RESTful 版本控制

RESTful API 版本控制是指在更新 API 接口时,通过改变 API 的版本信息来实现不同版本 API 的兼容性,在不影响旧版本 API 的情况下推动 API 的升级。这样可以避免因为 API 的变更导致现有的应用无法正常使用。

在 NestJS 中,根据官方文档,实现 RESTful API 的版本控制时,VersioningType 有以下四种方式:

  1. URI

URI 方式即通过在 URI 中添加版本号前缀的方式实现版本控制。例如,可以通过给请求的 URI 中添加 /v1 或者 /v2 前缀来实现不同版本的 API 区分。

  1. Header

Header 方式即通过请求头中添加版本号信息的方式实现版本控制。例如,可以通过在请求头中添加 X-API-VERSION: 1.0 这样的自定义头信息来实现版本区分。

  1. Media Type

Media Type 方式即通过在请求头中使用不同的 Media Type 来区分不同版本的 API。例如,可以通过在 Accept Header 中添加不同的 Media Type 来区分不同版本的 API,例如 application/vnd.company.product.v1+json

  1. Custom

Custom 方式即自定义一种方式来实现版本控制,例如通过在 URL Query 参数中添加版本号来实现版本区分,例如 api/user?version=1

一般使用第一种,如何进行设置

main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { VersioningType } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableVersioning({
    type: VersioningType.URI,
  });
  await app.listen(3000);
}
bootstrap();

user1.controller.ts

  1. 控制所有
@Controller('user1')
===修改后===>
@Controller({
  path: 'user1',
  version: '1',
})

image.png

  1. 控制单个接口
@Controller('user1')

@Get(':id')
@Version('2')
findOne(@Param('id') id: string) {
  return this.user1Service.findOne(+id);
}

image.png

4. http 状态码

常见的 HTTP 状态码及其含义如下:

  • 1xx(信息性状态码):服务器收到请求,需要请求者继续执行操作。

    • 100(继续):客户端应该继续发送请求。
    • 101 (切换协议):客户端要求服务器协议转换。
  • 2xx(成功状态码):请求已经被服务器接收、理解并接受。

    • 200(成功):请求已成功,请求所希望的响应头或数据体将随此响应返回。
    • 201(已创建):请求已经被实现,而且有一个新的资源已经依据请求的需要而建立。
    • 204(无内容):服务器成功处理了请求,但没有返回任何内容。
  • 3xx(重定向状态码):需要客户端采取进一步的操作。

    • 301(永久重定向):请求的网页已永久移动到新位置。
    • 302(临时重定向):请求的网页已经临时移动到新位置。
    • 304(未修改):资源未被修改,服务器返回此状态码时,不会返回任何资源。
  • 4xx(客户端错误状态码):请求包含语法错误或无法完成请求。

    • 400(客户端请求的语法错误):服务器无法理解请求。
    • 401(未授权):请求要求身份验证。
    • 403(禁止):服务器接受请求,但被拒绝处理。
    • 404(未找到):服务器无法找到请求的资源。
    • 408(请求超时):服务器等候请求时发生超时。
  • 5xx(服务器错误状态码):服务器在处理请求时发生错误。

    • 500(服务器内部错误):请求未完成。服务器遇到了意外情况,导致无法完成请求。
    • 502(错误网关):服务作为网关或代理角色时,从上游服务器接收到无效的响应。
    • 504(网关超时):服务作为网关或代理角色时,未及时从上游服务器接收请求。