浅谈 RESTful API

PHP在线

共 2821字,需浏览 6分钟

 · 2020-12-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/v1https://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/orgsHTTP/1.1 200 OKDate: Sun, 22 Apr 2018 03:43:57 GMTContent-Type: application/json; charset=utf-8Content-Length: 5Server: GitHub.comStatus: 200 OKX-RateLimit-Limit: 60 # 最大访问次数X-RateLimit-Remaining: 50 # 剩余的访问次数X-RateLimit-Reset: 1524369179 # 到该时间点,访问次数会重置为 X-RateLimit-LimitCache-Control: public, max-age=60, s-maxage=60Vary: AcceptETag: "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-IntervalAccess-Control-Allow-Origin: *Strict-Transport-Security: max-age=31536000; includeSubdomains; preloadX-Frame-Options: denyX-Content-Type-Options: nosniffX-XSS-Protection: 1; mode=blockReferrer-Policy: origin-when-cross-origin, strict-origin-when-cross-originContent-Security-Policy: default-src 'none'X-Runtime-rack: 0.010912Vary: Accept-EncodingX-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; doneHTTP/1.1 403 Forbidden # 服务器拒绝了Date: Sun, 22 Apr 2018 04:04:15 GMTContent-Type: application/json; charset=utf-8Content-Length: 258Server: GitHub.comStatus: 403 Forbidden # 返回的状态码X-RateLimit-Limit: 60X-RateLimit-Remaining: 0 # 剩余次数为 0 了X-RateLimit-Reset: 1524372880X-GitHub-Media-Type: github.v3; format=jsonAccess-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-IntervalAccess-Control-Allow-Origin: *Strict-Transport-Security: max-age=31536000; includeSubdomains; preloadX-Frame-Options: denyX-Content-Type-Options: nosniffX-XSS-Protection: 1; mode=blockReferrer-Policy: origin-when-cross-origin, strict-origin-when-cross-originContent-Security-Policy: default-src 'none'X-Runtime-rack: 0.012239X-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 的一些理解和总结,后期会补充和完善

浏览 43
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报