浅谈 RESTful API
共 2821字,需浏览 6分钟
·
2020-12-10 00:10
什么是 RESTful
RESTful API 设计参考文献列表
What Is REST?
RESTful
是一种软件设计风格,由 Roy Thomas Fielding 在他 2000
年的论文中提出,Fielding
将他对互联网软件的架构原则,定名为 REST
,即 Representational State Transfer
的缩写,译为表现层状态转化,也可理解为用 URL
定位资源,用 HTTP
方法描述操作。
REST
的核心是可编辑的资源及其集合,用符合 Atom
文档标准的 Feed
和 Entry
表示。每个资源或者集合有一个惟一的 URI
。系统以资源为中心,构建并提供一系列的 Web
服务。REST
的基本概念和原则包括:系统上的所有事物都被抽象为资源;每个资源对应唯一的资源标识;对资源的操作不会改变资源标识本身;所有的操作都是无状态的;等等。
为何要用 RESTful
按照 RESTful
架构可以充分的利用 HTTP
协议带给我们的各种功能,算是对 HTTP
协议使用的最佳实践,还有一点就是可以使软件架构设计更加清晰,可维护性更好
如何做 RESTful
RESTful 架构
如果一个架构符合 REST
原则,就称它为 RESTful
架构
从以下三个方面理解 RESTful
架构:
资源 -
Resources
:所谓资源,就是网络上的一个实体,或者说是网络上的一个具体信息表现层 -
Representation
:资源是一种信息实体,它可以有多种外在表现形式。我们把『资源』具体呈现出来的形式,叫做它的『表现层』状态转化 -
State Transfer
:互联网通信协议HTTP协议
,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生『状态转化 -State Transfer
』。而这种转化是建立在表现层之上的,所以就是『表现层状态转化』
也主就是说,遵循 REST
原则,设计出来的一个架构就称为 RESTful
架构,比如:GitHub API
就是一个典型的 RESTful
架构
RESTful API 设计
使用 URL 定位资源
GitHub REST API v3
很大程度上,定义的 API
地址要对程序员友好,并且能在浏览器地址栏容易输入。是的,这两个指标也能检验出那些合格的 API
设计者,我就是这样认为的
应该将
API
部署在专用域名之下,比如:api.example.com
不用大写
用中杠
-
而不是_
参数列表要
encode
URI
中尽量使用名词而不是动词URI
中的名词表示资源集合,使用复数形式虽然
/
在URI
中表达层级,但是避免为了追求REST
导致层级过深,适当使用参数表示,比如:GET /animals?zoo=1&area=3&page=1
版本控制
将版本号直接加入
URL
中
https://api.example.com/v1
https://api.example.com/v2
使用 HTTP 请求头的 Accept 字段进行区分
在这种方式中,客户端在 Accept Header 中存放 Accept: application/vnd.example.v1+json,服务器自定义 Header 返回当前版本信息 X-Example-Media-Type: example.v3; format=json
https://api.example.com/
Accept: application/vnd.example.v1+json
Accept: application/vnd.example.v2+json
请求 GitHub 查看头中自定义的 X-GitHub-Media-Type
$ curl -i https://api.github.com/users/octocat/orgs
HTTP/1.1 200 OK
Date: Sun, 22 Apr 2018 03:43:57 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 5
Server: GitHub.com
Status: 200 OK
X-RateLimit-Limit: 60 # 最大访问次数
X-RateLimit-Remaining: 50 # 剩余的访问次数
X-RateLimit-Reset: 1524369179 # 到该时间点,访问次数会重置为 X-RateLimit-Limit
Cache-Control: public, max-age=60, s-maxage=60
Vary: Accept
ETag: "98f0c1b396a4e5d54f4d5fe561d54b44"
X-GitHub-Media-Type: github.v3; format=json # GitHub 服务端自定义 Header 返回当前版本信息
Access-Control-Expose-Headers: ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
X-Runtime-rack: 0.010912
Vary: Accept-Encoding
X-GitHub-Request-Id: E5BC:17C8:C2B264:1064F09:5ADC04FD
[
]
请求 GitHub
接口超过限制次数后的响应
// 当请求到第 61 次时的响应结果
$ for (( i=0; i<61; i=i+1 )); do curl -i https://api.github.com/users/octocat/orgs; done
HTTP/1.1 403 Forbidden # 服务器拒绝了
Date: Sun, 22 Apr 2018 04:04:15 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 258
Server: GitHub.com
Status: 403 Forbidden # 返回的状态码
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0 # 剩余次数为 0 了
X-RateLimit-Reset: 1524372880
X-GitHub-Media-Type: github.v3; format=json
Access-Control-Expose-Headers: ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
X-Runtime-rack: 0.012239
X-GitHub-Request-Id: E756:2E0E:75FBFF:A0DA73:5ADC09BF
{
"message": "API rate limit exceeded for 221.223.47.129. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
"documentation_url": "https://developer.github.com/v3/#rate-limiting"
}
自定义 Header 头
X-Api-Version: 1
使用 HTTP 方法
安全性:不会改变资源状态,可以理解为只读的
幂等性:执行
1
次和执行N
次,对资源状态改变的效果是等价的,也就是说无论你执行多少次重复的操作都不会给资源造成变更
使用 HTTP 响应代码
请求成功
重定向
条件请求
客户端错误
服务端错误
响应数据格式
为什么都反对 XML 而支持使用 JSON?
当然轮子哥是这样说的『在我长时间使用
XML
和JSON
的过程中我发现,其实他们是不可互相替代的。我们只能说如今大部分适合XML
的程序要么都写完了要么都不时髦了,现在需要JSON
的还没写的程序多一点』
GitHub
是在请求的 body
体中使用 JSON
格式来返回数据的
$ curl -i https://api.github.com -u foo:bar
...
{
"message": "Bad credentials",
"documentation_url": "https://developer.github.com/v3"
}
编写文档
一个好的文档也反应出接口开发者的素养(当然那些赶项目进度的除外,笔者确实也经历过这种场景,项目急吼吼的上,就感觉明天做不出来,后天公司就要倒闭的这种,不要说写文档,就自己写的代码 Review
一下都是浪费时间。如果条件允许,我个人还是愿意把程序和文档都写好的)。当然,通过这些,你也看到了我的素养确实也不高,找了一个赶进度的借口不写文档,你愿意这么理解我也就不说什么了
文档的一些原则
每一个接口的请求参数,每个参数的类型限制,是否必填,可选的值等都进行明确
响应结果集中的每个参数都有明确的解释
对于特定场景和专门适配的接口,提供详细的说明,怎么的场景下调用之类等等
显然,这么宏大的标题可不是写一篇文章就能搞定的,以上这些就是我对 RESTful API
的一些理解和总结,后期会补充和完善