首页 » linux » 正文

RESTful API 设计

准备知识

HTTP的头域包括四个部分:

  • 通用头:通用头部是客户端和服务器都可以使用的头部,可以在客户端、服务器和其他应用程序之间提供一些非常有用的通用功能,如Date头部
  • 请求头:请求头部是请求报文特有的,它们为服务器提供了一些额外信息,例如客户端希望接收什么类型数据的Accept头部
  • 响应头:响应头部便于客户端提供信息,例如表示客服端在与哪种类型的服务器进行交互的Server头部
  • 实体头:实体头部指的是用于实体主体部分的头部,例如表示主体部分内容类型的Content-Type头部

设计RESTful API之前,必须了解的几个HTTP头信息:

  • Accept:请求头,表示发送端(客户端)希望接收的数据类型,比如: Accept: application/json, text/json
  • Content-Type:实体头,表示发送端(客户端 或 服务端)发送的实体数据类型,比如 Content-Type: text/html; charset=UTF-8

REST概念

  略… …

设计准则

1 版本

API的版本在设计时应该强制性要求,这样未来更改API结构时,不会破坏旧版本的兼容。版本常用的设计方式有两种:

  • 一种设计方式是版本号作为URL的一部分,例如: api.jd.com/uchance/v1/…
  • 另一种方式比较巧妙,也是推荐的做法,使用Accept HTTP请求头传递版本信息,Github就是这么做的: Accept: application/vnd.github.v3+json

2 命名

在对资源命名时要使用名词,不要使用动词。HTTP提供的GET、POST、PUT、DELETE方法让你可以操作数据:

  • GET         api.jd.com/uchance/products                                      # 获取产品列表
  • POST       api.jd.com/uchance/products                                      # 添加产品
  • PUT         api.jd.com/uchance/products/1                                   # 修改ID为1的产品
  • DELETE   api.jd.com/uchance/products/1                                   # 删除ID为1的产品

3 单数还是复数

在资源命名时要使用名词的复数,不然单数、复数混合很快会变的混乱和不一致,即使POST、PUT、DELETE也应该使用复数。

4 嵌套资源

当我们想获取一个资源集合的子集合时,应该进行嵌套设计。例如我们要获取订单列表:

  • GET  api.jd.com/uchance/products/1/orders                              # 以产品维度,获取产品编号为1的所有订单列表
  • GET  api.jd.com/uchance/users/1/orders                                   # 以用户维度,获取用户编号为1的所有订单列表

5 分页

当返回的数据量比较大时,我们需要分页,分页的做法一般是作为HTTP参数传递:

  • GET  api.jd.com/uchance/products?page=1&limit=20               # 获取产品列表,页码为1,每页显示20条

6 状态码

返回内容(成功或失败)时,应当使用合适的HTTP状态码,GO专享因为微信端的历史原因,没有完全按照HTTP Status Codes规范。

下边是一些常用的HTTP状态码:

  • 成功时的状态码
    200:成功,表示服务器已经成功处理了请求
    201:创建,表示服务器执行成功,并且创建了新的资源
    202:已接受,表示服务器已经接受了请求,当请求排队等待进行后台处理时,应该使用它(异步任务)
    204:空内容,应该在请求被正确执行,但没有返回任何内容时使用(例如当你删除某些东西)
    … …
  • 失败时的状态码
    400:错误请求,当请求参数或内容有误时使用
    401:无权限,当请求没有权限时使用
    403:被进制,当请求成功(有权限401),但是操作被禁止(比如没有DELETE权限)
    406:不接受,当请求的内容不被服务器接受时,例如服务器接受XML,但客户端提交的是JSON
    410:结束,当请求的资源被永久删除时返回
    422:验证错误,当创建对象时发生验证错误
    … …

设计误区

下边是一些错误的设计示例:

  • GET  api.jd.com/uchance/product                                              # 使用单数的资源名称
  • GET  api.jd.com/uchance/products/1?limit=20                           # 分页参数不能作为资源
  • POST  api.jd.com/uchance/products/create                               # 使用动词命名资源

设计实例

请求设计示例:

  • GET   api.jd.com/uchance/products?page=1&limit=20&type=1 # 获取产品列表,过滤参数为page=1、limit=20、type=1
  • GET   api.jd.com/uchance/products/1                                       # 获取编号为1的产品
  • GET   api.jd.com/uchance/products/form                                  # 获取产品新建页数据
  • POST api.jd.com/uchance/products                                          # 新建产品(提交产品新建数据)
  • GET   api.jd.com/uchance/products/1/form                               # 获取产品编号为1的修改页数据
  • PUT   api.jd.com/uchance/products/1                                        # 修改产品编号为1的产品(提交产品修改数据)
  • DELETE  api.jd.com/uchance/products/1                                  # 删除产品编号为1的产品

 

该文档参考了以下链接:

https://developer.github.com/guides/traversing-with-pagination/

https://developer.github.com/v3/media/#request-specific-version

https://bourgeois.me/

发表评论