架构社区程序员

RestFul设计规范

2018-05-11  本文已影响122人  不务正业的coder

1、说明

在整个文档中,会有一些对于标准和实践的推荐和建议。一些实践是非常重要的,必须严格执行,另一些指导准则并不一定处处适用,但是会在特定的场景下带来益处。为了清楚陈述规范和实践的意图,我们会使用如下术语。

2、通用命名约定

命名指南 中的”Restful接口”章节,不一致时以本文档为准。

3、基本设计规范

3.1 关注点分离

设计的时候尽量保持简单,一定要分离请求和响应时关注的不同部分,如:URL、Method、HEADER、body、HTTP Status Codes

3.2 使用HTTPS★

  1. 外部服务一定要使用TLS(就是HTTPS)来访问API,没有必要指出什么时候需要用,什么时候不需要用,只管任何时候都用它;
  2. 内部服务应该使用TLS,当前阶段不作为强制规范;
  3. 对所有非TLS的请求返回403 Forbidden,不要用重定向,这会允许一些不良的客户端行为,而又没有任何好处。依赖重定向的客户端会使流量翻倍,而让TLS毫无意义 — 敏感数据已经在第一次请求时发送出来了。

3.3 版本化API ★

REST版本化和多版本间过渡,是RESTful架构设计和运行时的挑战。因此,最好在一开始就考虑版本。

  1. 一定要在PATH上定义接口版本,如:
    1. https://xxx.xxx.com/upp/cpg/v1
    2. https://xxx.xxx.com/upp/cpg/v2
  2. 如果需要A/B Test,一定要在Request Header上定义,详见Requests设计规
  3. 一定不要提供默认版本,而由客户端显式指定它使用哪一个特定的版本。

3.4 RequestId追溯★

每个API请求一定要包含一个唯一的UUID

UUID存放在HEAD的X-OHM-Request-Id中,用来追溯。 由客户端,服务器和任何后端服务上记录这些值。 当出现问题时,根据这个值可以更容易地找出问题并更迅速地提供解决方案。它提供了一种机制来跟踪,诊断和调试REST请求。

3.5权限分离★

一定要通过url****和端口区分公共、私有、管理api,如:

  1. 公共(public):https://xxx.xxx.com/upp/v1/ 【可选端口:80,8000-8999】
  2. 私有(private):https://internal.xxx.xxx.com:9000/v1/ 【可选端口:9000-9899】
  3. 管理(admin):https://admin.xxx.xxx.com:9900/v1/【可选端口:9900-9999】

3.6 Etags缓存

可以在所有的请求中带上 ETag 头 ,用于识别返回资源的特定版本。用户可以在随后的请求中通过提供If-None-Match头的值来检查内容是否需要更新。

3.7 Ranges分页

可以对所有可能产生大量数据的响应,可以使用Content-Range头来标记分页请求。

3.8过滤、选择、排序

**过滤 Filtering **:

使用唯一的查询参数进行过滤:

curl +X GET https://xxx.xxx.com/v1/cars?color=red 返回红色的cars
curl +X GET https://xxx.xxx.com/v1/cars?seatsTo=2 返回小于两座位的cars集合

选择 Field selection

移动端能够显示其中一些字段,它们其实不需要一个资源的所有字段,给API消费者一个选择字段的能力,这会降低网络流量,提高API可用性。

curl +X GET https://xxx.xxx.com/v1/cars?fields=manufacturer,model,id,color

排序 Sorting :

允许针对多个字段排序

curl +X GET https://xxx.xxx.com/v1/cars?sort=-manufactorer,+model

这是返回根据生产者降序和模型升序排列的car集合

4 请求Requests设计规范

4.1 资源名 ★

  1. 一定使用名词而不是动词
    1. curl +X GET https://xxx.xxx.com/v1/users/{userId}
    2. curl +X GET https://xxx.xxx.com/v1/getUserByID
  2. 一定使用复数名词
    1. /users ý/user
    2. /users/{userId}/apps ý/user/{userId}/app
  3. 使用资源名称的复数版本除非有关资源是在系统内的单(例如,系统的整体状态可能是/status)。这使得它在你提到的特定资源的方式是一致的。

4.2 请求头★

Host: xxx.xxx.xxx.com

Date: Mon, 22 Aug 2016 11:21:04 GMT

User-Agent: Apache-HttpClient/4.1.2 (java 1.6)

**Content-Type: application/x-www-form-urlencoded; charset=UTF-8 **

//请求体类型,请根据实际请求体内容设置

Accept: application/json

//请求响应体类型,部分API可以根据指定的响应类型来返回对应数据格式,建议手动指定此请求头,如果不设置,部分HTTP客户端会设置默认值/,导致签名错误

X-OHM-App-Version: 1.0.0.2a

//APP版本号,用于请求路由、A/B Test等场景

X-OHM-Stage: RELEASE

//请求API的Stage,如TEST、RELEASE,API提供者可以选择发布到哪个Stage,只有发布到指定Stage后API才可以调用,否则会提示API找不到/Invalid Url/签名失败等错误

X-OHM-ClientKey: 60022326

//请求的AppKey,只有获得API授权后才可以调用

X-OHM-Time: 2016-04-06T12:00:00Z

//请求时间戳

**X-OHM-RequestId(必须): 7AD052CB-EE8B-4DFD-BBAF-EFB340E0A5AF **

//请求唯一标识,UUID,建议15分钟内Request-Id不能重复,与时间戳结合使用起到防重放作用

X-OHM-Signature: FJleSrCYPGCU7dMlLTG+UD3Bc5Elh3TV3CWHtSKh1Ys=

//请求签名,用于验签,防止伪造请求,根据接口的安全等级自定义规则,一般httpmethod、header、body、url的重要信息都要包含

X-OHM-UserId:

** X-OHM-UserToken:**

//用户Id和Token

X-OHM-Request-Mode:Debug

//是否开启Debug模式,不设置默认关闭,一般API调试阶段可以打开此设置,打开会接口会返回更相信的deug信息;生产上不允许打开。

X-{产品代码}-XXX

//自定义请求头,如X-UPP-XXX

4.3 操作

一般CRUD操作不需要定义在url中,但如果需要一些特殊的操作可以用actions作为path

示例:/apps/{appId}/actions/start

4.4 正确使用http method ★

仅使用以下四个方法:POST/GET/PUT/DELETE

4.5 少用路径嵌套★

数据模型可能有父子嵌套关系,路径可能深度嵌套

示例:https://xxx.xxx.com/v1/users/{userId}/apps/{appId}/docker/{dockerId}

宁愿在根路径上限制资源嵌套,使用嵌套来表示作用域的集合

例如:一个docker属于一个应用,一个应用属于一个用户

示例:

                     [https://xxx.xxx.com/v1/users/{userId](https://xxx.xxx.com/v1/users/%7BuserId)}

                     [https://xxx.xxx.com/v1/users/{userId}/apps](https://xxx.xxx.com/v1/users/%7BuserId%7D/apps)

                     [https://xxx.xxx.com/v1/apps/{appId](https://xxx.xxx.com/v1/apps/%7BappId)}

                     [https://xxx.xxx.com/v1/apps/{appId}/dockers](https://xxx.xxx.com/v1/apps/%7BappId%7D/dockers)

                     [https://xxx.xxx.com/v1/dockers/{dockerId](https://xxx.xxx.com/v1/dockers/%7BdockerId)}

5 响应Responses设计规范

5.1 返回适当的状态码 ★

rfc7231#section-6中的定义:

成功的响应一定要从以下返回码中进行选择:

错误的响应一定要从以下返回码中进行选择,特别注意400错误,普通业务异常一定要返回400

5.2 UTC时间并用ISO8601格式化 ★

接受和返回时一定只用UTC时间,并用ISO8601格式化,如:

"finishedAt": "2016-04-06T12:00:00Z"

5.3 生成结构化的错误信息 ★

在报错时生成一致结构的响应请求,包括:

示例:

| |

[](https://docs.xxx.xxx.com/XXX)

|

6 文档和其他(参考)

6.1 提供机器可读的json schema

提供机器可读的JSON schema来描述你的API,可以用prmd来管理JSON schema,用prmd verify来确保它通过验证

6.2 提供人类可读的文档

提供人类可读的文档帮助客户端开发者们理解你的API。

如果你使用了prmd来创建schema,那么你可以简单的通过prmd doc命令来生成Markdown的endpoint级别的文档。

除了endpoint级别的描述,还要提供概要级别的信息,

如:

6.3 提供可执行的示例

提供可执行的例子,这样用户可以直接在终端输入并看到可以用的API请求。最好的情况是,这些例子可以直接复制粘贴,以最小化用户试用API的成本,

如:

$ export TOKEN=... # acquire from dashboard

$ curl -is https://$TOKEN@xxx.xxx.com/v1/users

如果你使用prmd来生成Markdown文档,免费获得了可执行的示例。

6.4 提供mockapi

[图片上传失败...(image-b07de4-1526024018097)]

6.5 描述稳定性

描述你API的稳定性,以及哪些endpoint依赖于其成熟度,比如使用prototype,development或者production的标识。

可参考 Heroku API compatibility policy 了解哪些接口是稳定的,哪些可能有变动。

一旦你的API宣布为 production-ready 和 稳定版,不要在该API版本上做任何不向前兼容的修改。如果你需要做不向前兼容的修改,创建一个新的版本号。

[图片上传失败...(image-c70619-1526024018097)]

上一篇 下一篇

猜你喜欢

热点阅读