API的定义取决于选择的IPC通信方式,假设是消息机制(如 AMQP 或者 STOMP)。API则由消息频道(channel)和消息类型。假设是使用HTTP机制,则是基于请求/响应(调用http的url),这里我们先简述下RestfulAPI的定义。

设计原则

域名

应该尽量将API部署在专用域名之下,如:

https://api.example.com

也能够放在主域名下:

https://example.org/api/

版本号

放入到头信息的Accept中 制定版本号并在版本号之间平缓过渡对于设计和维护一套API是个巨大的挑战。所以。最好在设计之初就使用一些方法来预防可能会遇到的问题。 为了避免API的变动导致用户使用中产生意外结果或调用失败。最好强制要求全部訪问都须要指定版本号号。请避免提供默认版本号号,一旦提供,日后想要改动它会相当困难。 最适合放置版本号号的位置URL中,或者是头信息(HTTP Headers)中在 Accept 段中使用自己定义类型(content type)与其它元数据(metadata)一起提交。

https://api.example.com/v1/

Accept: application/vnd.heroku+json; version=3

提供 Request-Id

为每个请求响应包括一个Request-Id字段,并使用UUID作为该值。通过在client、server或不论什么支持服务上记录该值。它能主我们提供一种机制来跟踪、诊断和调试请求。

路径

资源名

在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词。仅仅能有名词。并且所用的名词往往与数据库的表格名相应。一般来说,数据库中的表都是同种记录的”集合”(collection),所以API中的名词也应该使用复数。 举例来说,有一个API提供动物园(zoo)的信息。还包括各种动物和雇员的信息,则它的路径应该设计成以下这样。

https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees

行为(Actions)

好的末尾不须要为资源指定特殊的行为,但在特殊情况下,为某些资源指定行为却是必要的。

为了描写叙述清楚。在行为前加上一个标准的actions:

/resources/:resource/actions/:action

如:

/runs/{run_id}/actions/stop

路径和属性名

为了和域名命名规则保持一致。使用小写字母并用-切割路径名字。比如:

service-api.com/users
service-api.com/app-setups

属性也使用小写字母,可是属性名要用下划线_切割,以便在Javascript中省略引號。 比如:

service_class: "first"

支持方便的无id间接引用

在某些情况下,让用户提供ID去定位资源是不方便的。比如,一个用户想取得他在Heroku平台app信息,可是这个app的唯一标识是UUID。这样的情况下,你应该支持接口通过名字和ID都能訪问,比如:

$ curl https://service.com/apps/{app_id_or_name}
$ curl https://service.com/apps/97addcf0-c182
$ curl https://service.com/apps/www-prod

不要仅仅接受使用名字而放弃了使用id。

最小化路径嵌套

在一些有父路径/子路径嵌套关系的资源数据模块中,路径可能有非常深的嵌套关系,比如:

/orgs/{org_id}/apps/{app_id}/dynos/{dyno_id}

推荐在根(root)路径下指定资源来限制路径的嵌套深度。

使用嵌套指定范围的资源。在上述样例中,dyno属于app,app属于org能够表示为:

/orgs/{org_id}
/orgs/{org_id}/apps
/apps/{app_id}
/apps/{app_id}/dynos
/dynos/{dyno_id}

HTTP动词

对于资源的详细操作类型,由HTTP动词表示。 经常使用的HTTP动词有以下五个(括号中是相应的SQL命令):

GET(SELECT):从server取出资源(一项或多项)。
POST(CREATE):在server新建一个资源。
PUT(UPDATE):在server更新资源(client提供改变后的完整资源)。
PATCH(UPDATE):在server更新资源(client提供改变的属性)。 DELETE(DELETE):从server删除资源。

一些样例:

GET /zoos:列出全部动物园
POST /zoos:新建一个动物园
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:列出某个指定动物园的全部动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

过滤信息

假设记录数量非常多。server不可能都将它们返回给用户。

API应该提供參数。过滤返回结果。

以下是一些常见的參数:

?limit=10:指定返回记录的数量
?offset=10:指定返回记录的開始位置。
? page=2&per_page=100:指定第几页,以及每页的记录数。
? sortby=name&order=asc:指定返回结果依照哪个属性排序。以及排序顺序。
?animal_type_id=1:指定筛选条件

參数的设计同意存在冗余,即同意API路径和URL參数偶尔有反复。

比方,GET /zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是同样的。

响应(Responses)

状态码

server向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码相应的HTTP动词):

200 OK - [GET]:server成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或改动数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,server没有进行新建或改动数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、username、password错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),可是訪问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录。server没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比方用户请求JSON格式,可是仅仅有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:server错误发生。用户将无法推断发出的请求是否成功。

提供资源的(UU)ID

在默认情况给每个资源一个id属性。

除非有更好的理由,否则请使用UUID。不要使用那种在server上或是资源中不是全局唯一的标识,尤其是自己主动增长的id。 生成小写的UUID格式 8-4-4-4-12,比如:

"id": "01234567-89ab-cdef-0123-456789abcdef"

提供标准的时间戳

为资源提供默认的创建时间 created_at 和更新时间 updated_at,比如:

{
...
"created_at": "2012-01-01T12:00:00Z",
"updated_at": "2012-01-01T13:00:00Z",
...
}

使用UTC(世界标准时间)时间,用ISO8601进行格式化

在接收和返回时都仅仅使用UTC格式(ISO8601格式的数据)或者使用时间戳。,比如:

"finished_at": "2012-01-01T12:00:00Z"

"timestamp": "1472486035"

错误处理

假设状态码是4xx,就应该向用户返回出错信息。一般来说。返回的信息中将error作为键名。出错信息作为键值就可以。

{
error: "Invalid API key"
}

返回结果

针对不同操作。server向用户返回的结果应该符合以下规范。

GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档

保证响应JSON及最小化

眼下为保证响应最小化,一般使用json字符串,并且请求中多余的空格会添加响应大小,并且如今非常多的HTTPclient都会自己输出可读格式("prettify")的JSON。

所以最好保证响应JSON最小化。比如:

{"beta":false,"email":"alice@heroku.com","id":"01234567-89ab-cdef-0123-456789abcdef","last_login":"2012-01-01T12:00:00Z","created_at":"2012-01-01T12:00:00Z","updated_at":"2012-01-01T12:00:00Z"}

而不是这样:

{
"beta": false,
"email": "alice@heroku.com",
"id": "01234567-89ab-cdef-0123-456789abcdef",
"last_login": "2012-01-01T12:00:00Z",
"created_at": "2012-01-01T12:00:00Z",
"updated_at": "2012-01-01T12:00:00Z"
}

Hypermedia API

RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其它API方法,使得用户不查文档,也知道下一步应该做什么。

比方,当用户向api.example.com的根文件夹发出请求,会得到这样一个文档。

{"link": {
"rel": "collection https://www.example.com/zoos",
"href": "https://api.example.com/zoos",
"title": "List of zoos",
"type": "application/vnd.yourformat+json"
}}

上面代码表示,文档中有一个link属性,用户读取这个属性就知道下一步该调用什么API了。

rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址),href表示API的路径,title表示API的标题。type表示返回类型。 Hypermedia API的设计被称为HATEOAS。

Github的API就是这样的设计。訪问api.github.com会得到一个全部可用API的网址列表。

{
"current_user_url": "https://api.github.com/user",
"authorizations_url": "https://api.github.com/authorizations",
// ...
}

从上面能够看到。假设想获取当前用户的信息,应该去訪问api.github.com/user,然后就得到了以下结果。

{
"message": "Requires authentication",
"documentation_url": "https://developer.github.com/v3"
}

上面代码表示,server给出了提示信息,以及文档的网址。

相关文章链接:

by 刘迎光  
MicroService 微服务QQ群:217722918  
博客MicroService 微服务专栏: http://blog.csdn.net/column/details/microservice.html  

微服务指南走北(三):Restful API 设计简述的更多相关文章

  1. Rest Framework简介 和 RESTful API 设计指南

    使用Django Rest Framework之前我们要先知道,它是什么,能干什么用? Django Rest Framework 是一个强大且灵活的工具包,用以构建Web API 为什么要使用Res ...

  2. 理解RESTful架构——Restful API设计指南

    理解RESTful架构 Restful API设计指南 理解RESTful架构 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式 ...

  3. RESTful API 设计指南 (转)

    RESTful API 设计指南 2016-02-23 ImportNew (点击上方公号,可快速关注) 作者:阮一峰 链接:http://www.ruanyifeng.com/blog/2014/0 ...

  4. RESTFul API设计指南及使用说明

    RESTFul API设计指南及使用说明 一. 协议 API与用户的通信协议,使用HTTP协议. 二. 域名 应尽量将API部署在专用域名之下(http://api.example.com) 也可以将 ...

  5. RESTful API 设计指南,RESTful API 设计最佳实践

    RESTful API 设计指南,RESTful API 设计最佳实践 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). ...

  6. 通过Dapr实现一个简单的基于.net的微服务电商系统(三)——一步一步教你如何撸Dapr

    目录:一.通过Dapr实现一个简单的基于.net的微服务电商系统 二.通过Dapr实现一个简单的基于.net的微服务电商系统(二)--通讯框架讲解 三.通过Dapr实现一个简单的基于.net的微服务电 ...

  7. 我是如何根据豆瓣api来理解Restful API设计的

    1.什么是REST REST全称是Representational State Transfer,表述状态转移的意思.它是在Roy Fielding博士论文首次提出.REST本身没有创造新的技术.组件 ...

  8. RESTful API设计相关

    一  RESTful架构 在当今时代,越来越多人意识到了网站即软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high laten ...

  9. RESTful API设计原则与规范

    RESTful API设计原则与规范 一.背景与基础概念 2 二.RESTful API应遵循的原则 3 1.协议(Protocol) 3 2.域名(ROOT URL) 3 3.版本(Versioni ...

随机推荐

  1. 静态代码扫描工具使用教程 - SonarQube+SonarScanner

    预置条件: Jdk已安装 Mysql已安装 1. 下载 SonarQube和Sonar scanner. SonarQube: http://www.sonarqube.org/downloads/ ...

  2. kNN的维数灾难与PCA降维

    主成分分析 PCA 协方差矩阵 假设我们有 \[ X = \begin{pmatrix}X_1\\X_2\\\vdots\\X_m\end{pmatrix}\in\mathbb{R}^{m\times ...

  3. [python工具][2]sublime的快捷键

    十.Sublime Text 快捷键列表 快捷键按类型分列如下: 1.通用  ↑↓← →    上下左右移动光标 Alt    调出菜单 Ctrl + Shift + P    调出命令板(Comma ...

  4. Educational Codeforces Round 20 D. Magazine Ad

    The main city magazine offers its readers an opportunity to publish their ads. The format of the ad ...

  5. asp.net的Context.Cache缓存过期策略

    最近使用Context.Cache需要了解Cache的缓存过期策略. 文章:ASP.NET缓存中Cache过期的三种策略

  6. hihoCoder #1246 王胖浩与环

    题目大意 $n$($1\le n\le 2000$)个正整数 $a_1, a_2, \dots, a_n$($a_i\le 5\times 10^7$)分布在一个圆环上. 定义 $b_k$ 为:将环上 ...

  7. HDU-3729 I'm Telling the Truth

    一个点集是学生,一个点集是排名.然后通过学生的排名范围连线,求此二分图的最大匹配. 本题还要求是最大字典序输出,那么由贪心可得,你让标号从大到小找增广边就行了. #include <cstdli ...

  8. jquery validate用法总结

    jquery validate是本人用过的最好用的验证组件,但其文档写的真是不敢恭维,现将一些常见用法总结如下(持续更新). 1. js触发表单验证 //触发整个表单的验证 $('form').val ...

  9. dom方法insertAfter的实现

    在dom的原生api中,只用insertBefore,没有insertAfter,借助原有的api,可以模拟一个insterAfter. function insterAfter(newElement ...

  10. eclipse中纯java配置log4j日志

    1.新建java项目log4Test 2.新建目录lib,把log4j-1.2.9.jar包放入lib目录 3.右键工程,选择Properties->Java Build Path->Li ...