RestFul设计规范

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中的定义:

  • 1xx (Informational): The request was received, continuing process
  • 2xx (Successful): The request was successfully received, understood, and accepted
  • 3xx (Redirection): Further action needs to be taken in order to complete the request
  • 4xx (Client Error): The request contains bad syntax or cannot be fulfilled
  • 5xx (Server Error): The server failed to fulfill an apparently valid request

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

  • 200 OK: 请求GET调用成功,对于DELETE方法同步调用完成,或为PUT方法调用,同步更新现有资源
  • 201: 请求POST调用成功,同步完成,或为PUT调用同步创建了一个新的资源
  • 202: 接受POST、PUT、DELETE请求,将异步处理请求结果

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

  • 400 Bad Request:请求失败,普通业务异常 & 服务器不理解请求语法
  • 401 Unauthorized: 请求失败,因为用户没有通过验证
  • **403 ** Forbidden: 请求失败,因为用户没有权限访问特定资源
  • 404 Not Found:请求失败,未找到该资源
  • 408 Request Timeout:请求超时
  • 429 Too Many Requests:超频调用,请稍后再试
  • 500 Internal Server Error:服务器内部错误,检查网站状态或报告问题

5.2 UTC时间并用ISO8601格式化 ★

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

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

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

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

  • code:一个机器可读的错误,
  • message:一个人类可读的错误message,
  • extraCode: 附加错误码,一般用于返回外部服务原始错误码, (可选)
  • extraMessage: 附加错误消息,一般用于返回外部服务原始错误消息,(可选)
  • tracestack:一个程序员可读的错误tracestack,(可选)
  • url:一个url为客户端提供进一步错误信息和解决方案(可选)

示例:

| |

[](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级别的描述,还要提供概要级别的信息,

如:

  • 授权,包括获得和使用授权Token。
  • API的稳定性和版本,包括如何选择现有的API版本。
  • 通用请求和响应头。
  • 错误的序列化格式。
  • 各种语言的客户端如何使用API的例子。

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)]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,628评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,744评论 25 707
  • 去年有段时间得空,就把谷歌GAE的API权威指南看了一遍,收获颇丰,特别是在自己几乎独立开发了公司的云数据中心之后...
    骑单车的勋爵阅读 20,474评论 0 41
  • 21.离婚 隔壁老王已经快50岁了,为生第三胎经常跟他老婆吵架,只因前面两胎都是女儿。老王觉得很没面子,在亲戚面前...
    默夜清辉阅读 357评论 0 0
  • gulp使用流程:安装nodejs -> 全局安装gulp -> 项目安装gulp以及gulp插件 -> 配置gu...
    liuwan阅读 1,595评论 0 0