通用设计规则

资源:往往对应着后台系统中对象,比如一个用户User,一个待办事项todo item,一个任务Task等等

用对应的接口表示要对资源进行何种操作,想要实现什么目的:

HTTP Verb=HTTP Method=HTTP方法 操作类型=CRUD 可能返回的状态码 是否幂等Idempotent 是否安全Safe
OPTIONS 询问该接口/端点支持哪些方法 200 OK
POST Create创建
  • 正常
    • 201 (Created)
  • 异常
    • 404 (Not Found)
    • 409 (Conflict)
GET Read读取
  • 正常:
    • 200 (OK)
  • 异常:
    • 404 (Not Found)
HEAD 同GET但是返回BODY为空 同GET
PUT Replace替换
  • 正常:
    • 200 (OK)
  • 异常
    • 405 (Method Not Allowed)
    • 204 (No Content)
    • 404 (Not Found)
PATCH Update/Modify更新
  • 正常:
    • 200 (OK)
  • 异常
    • 405 (Method Not Allowed)
    • 204 (No Content)
    • 404 (Not Found)
DELETE Delete删除
  • 正常:
    • 200 (OK)
    • 204 (No Content)
  • 异常:
    • 404 (Not Found)
    • 405 (Method Not Allowed)

举例:RESTful的某个类似于外卖的项目的API

此处给出之前做过一个项目的RESTful的API,供参考:

  • 用户
    • 获取用户ID:支持多个参数,根据参数不同返回对应的值
      • GET /v1.0/open/userId?type=phone&phone={phone}
      • GET /v1.0/open/userId?type=email&email={email}
      • GET /v1.0/open/userId?type=facebook&facebookUserId={facebookUserId}
    • 获取用户信息
      • GET /v1.0/users/{userId}
    • 修改用户信息
      • PUT /v1.0/users/{userId}/info
    • 修改密码
      • PUT /v1.0/users/{userId}/password
  • 订单
    • 获取订单任务信息
      • GET /v1.0/tasks/{taskId}/users/{userId}
    • 发布任务
      • POST /v1.0/tasks/users/{userId}
    • 发单人确认任务信息
      • PUT /v1.0/tasks/{taskId}/users/{userId}/confirmInfo

常见问题

在具体设计接口时,会遇到一些具体的某些接口,到底应该用哪个HTTP方法等方面的问题,整理如下供参考:

更新资源到底应该用PATCH还是PUT?

对于更新一个资源,很多人都会遇到这个问题,到底应该用PATCH还是PUT

现解释如下:

HTTP的官方规范定义中,其实是:

HTTP方法 主要目的 传入参数 额外说明或注意事项
PUT 把某个资源的整体的信息替换 该资源的 全部 的字段 换言之:当某些字段没有传的话,则直接设置为null
PATCH 把某个资源的部分信息更新 该资源的(你想要更新数据的那)部分的字段 PATCH是在PUT之后才提出来,进入官方规范的。目的就是,只更新你传了值的那些字段,保留其他字段的已有的值

最佳实践==大家的实际做法

只不过,现在大家的常见的,实际的做法往往是:

PUT实现了PATCH的效果:

使用PUT,但只传递部分字段,然后更新相应的字段

举例说明

有一个user用户,信息是:

{
  "name": "zhangsan",
  "email": "xxx@x.com"
}

按照PUT的规范来说,如果想要更新这个用户的邮箱,则需要传递:

PUT /user/some_user_id

{
  "name": "zhangsan",
  "email": "yyy@y.com"
}

否则如果传递:

PUT /user/some_user_id

{
  "email": "yyy@y.com"
}

REST标准中PUT就会认为,你没有其他字段,包括name,则会去设置name为null

-> 这样才是原本想要的replace替换的效果

而如果只是想要更新用户邮箱,应该去用PATCH,传递:

PATCH /user/some_user_id

{
  "email": "yyy@y.com"
}

然后才可以实现:只更新email字段,保留其他字段的已有的值

但是现在实际上大部人都是为了省事,也可以说作为最佳实践,用PUT代替PATCH,传入

PUT /user/some_user_id

{
  "email": "yyy@y.com"
}

去实现(只)更新email邮箱,而保留其他(比如用户名name)的效果。

POST创建资源成功后是返回200还是201?

虽然按照REST协议来说,POST了新建的,应该返回201

但是为了统一处理,以及:很多开发者未必能很好的处理201,所以:

对于操作成功的,都正常返回200即可。

然后在response中返回对应的信息

比如:

新建的对象的详细信息

或者只是新建对象的id

结论:

  • HTTP协议规范POST创建成功后,应该返回201,以及对应的新的资源的id
    • 用户再通过新建资源的id,去获取资源详情
  • 最佳实践:大家实际的常见做法则是,直接返回新建资源的所有的详情的json,其中包括id

DELETE应该返回什么?

综合官网和其他文档后,REST服务器端对于DELETE请求应该返回什么状态码,以及具体返回什么值,详细解释如下:

  • 202=Accepted:表示接受了此删除请求
    • 但是暂时还没执行
    • 或者目前执行删除动作,但是还没有完成
      • 之后(服务器端)会完成删除动作
  • 204=No Content:已经执行了删除动作,内容被删除了,没有内容了
  • 200=OK:内容已删除,同时返回body信息,包含具体的删除的详情
    • response的body中包含额外关于删除的相关信息
      • 比如之前帖子中提到的,删除了具体哪个内容,已删除的状态,甚至删除了符合对应条件的多个内容等等

目前自己所理解的最佳实践是第三种:

  • 返回状态码200=OK
  • 返回什么值:根据之前的最佳实践:code、message、data,应该返回:
{
  "code": 200,
  "message": "Question deleted for id 5c1777e1cc6df4563adf4a50",
  "data": {
    "deletedCount": 1
  }
}

且更加细节的做法是:当检测到想要删除一个已经删除的内容,则提示已经删除了:

{
  "code": 200,
  "message": "Question already deleted for id 5c1777e1cc6df4563adf4a50",
  "data": {
    "deletedCount": 0
  }
}

results matching ""

    No results matching ""