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. 国内外移动端web适配屏幕方案总结

    基础知识点 设备像素:设备像素又称物理像素(physical pixel),设备能控制显示的最小单位,我们可以把这些像素看作成显示器上一个个的点. iPhone5的物理像素是640X1136. PS: ...

  2. appium安装,和遇到的问题

    https://www.cnblogs.com/fnng/p/4540731.html Appium环境搭建时在cmd中输入appium-doctor命令,提示’appium-doctor’ 不是内部 ...

  3. ccna学习指南第七版

    1.加电post自检    闪存查找ios 可随时从命令行进入设置模式,为此可在特权模式下输入setup    ctrl+c退出特权模式 6.2cli   命令行界面 进入cli router> ...

  4. JSP内置对象的cookie和session实现简单登录界面

    创建一个index.jsp页面 <%@ page language="java" contentType="text/html; charset=utf-8&quo ...

  5. JDBC 学习笔记(八)—— ResultSet

    JDBC 使用 ResultSet 来封装 SQL 的查询结果,可以将 ResultSet 类比为数据库表的查询结果. 它拥有如下两个性质: 可滚动. 可更新. 这两个性质,是在创建 Statemen ...

  6. 近期JS心得

    child和tags都是[{id:1,value:'a'}]的格式,当点击一级标签,要看二级标签是否已经被选中,如果被选中,则清除出去 如果用for循环 再splice的话 当删除掉了一个元素后,数组 ...

  7. iOS粒子效果

    网址链接:http://www.cocoachina.com/bbs/read.php?tid-103257.html http://code.cocoachina.com/view/125060 粒 ...

  8. 用SVGDeveloper制作svg地图

    项目中需要实现巴蜀地区图,并且将其分为川东.川西.川南.川北四个区域,鼠标悬浮对应区域的区块改变颜色.经过网上查询资料,并未找到现成的区域图,于是就利用SVGDeveloper工具绘制. 一.绘制地图 ...

  9. 刷题总结——regular words(hdu1502 dp+高精度加法+压位)

    题目: Problem Description Consider words of length 3n over alphabet {A, B, C} . Denote the number of o ...

  10. 算法复习——区间dp

    感觉对区间dp也不好说些什么直接照搬讲义了2333 例题: 1.引水入城(洛谷1514) 这道题先开始看不出来到底和区间dp有什么卵关系···· 首先肯定是bfs暴力判一判可以覆盖到哪些城市····无 ...