在之前的面试过程中,就被问到了什么是RESTful Api。当时的话在这个上面吃了亏,其实也有一直听说RESTful,但就是没有好好去了解过。那么今天就来看看它到底是个啥。
概念
REST(Representational State Transfer),直译是表现层状态转移,是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。
资源
REST中省略了主语,主语就是”资源“,表现层指的是资源的表现层。所谓”资源“,就是网络上的一个实体,或者说是网络上的一个具体信息。可能对应到我们日常开发中,说”资源“是一个数据库表会更容易理解,当然不仅仅只是只数据库表。如果想要访问资源,调用它的URI(统一资源定位符)就可以。
表现层(Representational)
把”资源“具体呈现出来的形式,叫做它的表现层。比如,文本可以用txt
格式表现,也可以用json
格式来表现,图片可以用JPG
格式来表示。
状态转化
访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。
互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。
客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,几个表示操作方式的动词:GET、POST、PUT、DELETE等。
最佳实践
1.URL设计
1.1 动词+宾语
RESTful的核心思想就是,客户端发出的数据操作指令都是”动词+宾语“的结构。比如, GET /articles
这个命令,GET
是动词,/articles
是宾语。动词通常就是五种HTTP的方法,对应CRUD操作。
- GET:读取(Read)
- POST:新建(Create)
- PUT:更新(Update)
- PATCH:更新(Update),通常是部分更新
- DELETE:删除(Delete)
1.2 动词的覆盖
有些客户端只能使用GET
和POST
这两种方法。服务器必须接受POST
模拟其他三个方法(PUT
、PATCH
、DELETE
)。
这时,客户端发出的 HTTP 请求,要在请求头部加上X-HTTP-Method-Override
属性,告诉服务器应该使用哪一个动词,覆盖POST
方法。
POST /api/Person/4 HTTP/1.1
X-HTTP-Method-Override: PUT
1.3 宾语必须是名词,建议复数形式
获取的资源应该是名词,不能是动词。一般来说,资源都是一个集合,推荐复数形式。
比如获取文章的接口,
// 推荐
GET /articles
// 不推荐
GET /article
GET /getArticles
GET /findArticles
1.4 避免多级URL,使用查询字符串
常见的情况是,资源需要多级分类,因此很容易写出多级URL,比如获取某个作者的某一类文章。
GET /authors/12/categories/2
这种 URL 不利于扩展,语义也不明确,往往要想一会,才能明白含义。
更好的做法是,除了第一级,其他级别都用查询字符串表达。
GET /authors/12?categories=2
2.状态码
HTTP的状态码就是一个三位数,分成五个类别。
- 1xx:相关信息
- 2xx:操作成功
- 3xx:重定向
- 4xx:客户端错误
- 5xx:服务器错误
服务器应该返回尽可能准确的状态码。这里不展开说明所有的状态码情况。有兴趣的可以 去MDN HTTP响应状态码 看看。
3.服务器回应
3.1 不要返回纯文本
API返回的数据格式,不应该是纯文本,而应该是一个JSON对象,因为这样才能返回标准的结构化数据。所以服务器回应的HTTP头的Content-Type
属性要设为application/json
。客户端请求时,也要明确告诉服务器,可以接受JSON格式。
3.2 发生错误时,不要返回200状态码
3.3 提供链接
API 的使用者未必知道,URL 是怎么设计的。一个解决方法就是,在回应中,给出相关链接,便于下一步操作。这样的话,用户只要记住一个 URL,就可以发现其他的 URL。这种方法叫做 HATEOAS
(全称是Hypermedia as the engine of application state)。
举例来说,GitHub的API都在 api.github.com 这个域名下。访问它,就可以得到其它URL.
举例
假设我们在设计一个资源是动物园的api,可以这么设计:
缺点
RESTful Api也存在一些缺点,可以适当了解下。
- 比如操作方式繁琐,RESTful API通常根据GET、POST、PUT、DELETE 来区分操作资源的动作,而HTTP Method 本身不可直接见,是隐藏的,而如果将动作放到URL的path上反而清晰可见,更利于团队的理解和交流。
- 并且有些浏览器对GET,POST之外的请求支持不太友好,还需要特殊额外的处理。
- 过分强调资源,而实际业务API可能有各种需求比较复杂,单单使用资源的增删改查可能并不能有效满足使用需求,强行使用RESTful风格API只会增加开发难度和成本。
拓展·HTTP动词
上面说到HTTP的东西有五种,分别是GET
POST
PUT
PATCH
DELETE
.但实际上不止这些。
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
序号 | 方法 | 描述 |
---|---|---|
1 | GET | 请求指定的页面信息,并返回实体主体。 |
2 | POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 |
3 | HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
5 | DELETE | 请求服务器删除指定的页面。 |
5 | PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 。 |
7 | OPTIONS | 允许客户端查看服务器的性能。 |
8 | CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 |
9 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
但是在我的上一家公司中,只允许使用GET
POST
。在做软件的安全扫描时,如果发现使用了GET
POST
之外的接口,必须修改掉,也必须限制开放其它方法。
不禁要问,这个是为什么呢?(其实吧,这个是当时面试官问我的,我没回答上来,😭)
其实吧,这是因为涉及到安全的问题。
1.OPTIONS
OPTIONS方法,将会造成服务器信息暴露,如中间件版本、支持的HTTP方法等。
2.PUT
由于PUT方法自身不带验证机制,利用PUT方法即可快捷简单地入侵服务器,上传Webshell或其他恶意文件,从而获取敏感数据或服务器权限。
3.DELETE
利用DELETE方法可以删除服务器上特定的资源文件,造成恶意攻击。
推荐
看完这篇文章之后,还有兴趣的话,可以去 RESTful API 这个站点看看,设计的蛮好的。
参考资料
1.理解RESTful架构 - 阮一峰的网络日志
2.RESTful API 最佳实践 - 阮一峰的网络日志
3.RESTful API 一种流行的 API 设计风格
完。