blog/docs/auto/api/restful-info.md

199 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: RestFul接口规范
date: 2020-06-24 16:30:08
tags: [接口测试]
categories: [接口测试]
author: 阮一峰
---
## 什么是RestFul
RestFul是在2000年由Roy Thomas Fielding博士在他的博士论文中提出。
他是http 1.0和1.1版本协议的主要设计者apache基金会的第一任主席可以说是现代互联网体系的奠基者。
Fielding将他对互联网软件的架构原则定名为REST即表述层状态转移Representational State Transfer
这是一套在互联网体系下,调用者如何与被调用者(资源实体)进行互动的规范设计。
## RestFul有什么样的规范
在RestFul理论中一个uri地址指向一个资源对象。
### 设计
以不同的请求方式,来实现资源对象的不同操作。
GET :从服务器取出资源(一项或多项)
POST :在服务器新建一个资源
PUT :在服务器更新资源(客户端提供改变后的完整资源)
PATCH :在服务器更新资源(客户端提供改变的属性)
DELETE :从服务器删除资源
例如:
有一个资源对象为user1 是资源对象中的某一个对象中的唯一标识id。
```
GET /user返回所有用户对象的列表数组
GET /user/resource返回单个用户对象
POST /user返回新生成的用户对象
PUT /user/resource返回完整的用户对象
PATCH /user/resource返回完整的用户对象
DELETE /user/resource返回一个空文档
```
### 复数url
既然 URL 是名词,那么应该使用复数,还是单数?
这没有统一的规定但是常见的操作是读取一个集合比如GET /articles读取所有文章这里明显应该是复数。
为了统一起见,建议都使用复数 URL比如GET /articles/2要好于GET /article/2。
### 避免多级URL
常见的情况是,资源需要多级分类,因此很容易写出多级的 URL比如获取某个作者的某一类文章。
```
GET /authors/12/categories/2
```
这种 URL 不利于扩展,语义也不明确,往往要想一会,才能明白含义。
更好的做法是,除了第一级,其他级别都用查询字符串表达。
```
GET /authors/12?categories=2
```
下面是另一个例子,查询已发布的文章。你可能会设计成下面的 URL。
```
GET /articles/published
```
查询字符串的写法明显更好。
```
GET /articles?published=true
```
### 状态码
状态码必须精确
客户端的每一次请求,服务器都必须给出回应。回应包括 HTTP 状态码和数据两部分。
HTTP 状态码就是一个三位数,分成五个类别。
1xx相关信息
2xx操作成功
3xx重定向
4xx客户端错误
5xx服务器错误
这五大类总共包含100多种状态码覆盖了绝大部分可能遇到的情况。
每一种状态码都有标准的(或者约定的)解释,客户端只需查看状态码,就可以判断出发生了什么情况,
所以服务器应该返回尽可能精确的状态码。
API 不需要1xx状态码。
状态码详情可以看[常见HTTP状态码](http://www.angeszhu.cn/auto/api/http-status.html)
### 服务器响应
#### 不要返回纯本文
API 返回的数据格式,不应该是纯文本,而应该是一个 JSON 对象,因为这样才能返回标准的结构化数据。
所以,服务器回应的 HTTP 头的Content-Type属性要设为application/json。
客户端请求时,也要明确告诉服务器,可以接受 JSON 格式,即请求的 HTTP 头的ACCEPT属性也要设成application/json。下面是一个例子。
```
GET /orders/2 HTTP/1.1
Accept: application/json
```
#### 发生错误时,不要返回 200 状态码
有一种不恰当的做法是即使发生错误也返回200状态码把错误信息放在数据体里面就像下面这样。
```
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "failure",
"data": {
"error": "Expected at least two items in list."
}
}
```
上面代码中,解析数据体以后,才能得知操作失败。
这张做法实际上取消了状态码,这是完全不可取的。
正确的做法是,状态码反映发生的错误,具体的错误信息放在数据体里面返回。下面是一个例子。
```
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Invalid payoad.",
"detail": {
"surname": "This field is required."
}
}
```
#### 提供链接
API 的使用者未必知道URL 是怎么设计的。
一个解决方法就是,在回应中,给出相关链接,便于下一步操作。
这样的话,用户只要记住一个 URL就可以发现其他的 URL。这种方法叫做 HATEOAS。
举例来说GitHub 的 API 都在 api.github.com 这个域名。访问它,就可以得到其他 URL。
```
{
...
"feeds_url": "https://api.github.com/feeds",
"followers_url": "https://api.github.com/user/followers",
"following_url": "https://api.github.com/user/following{/target}",
"gists_url": "https://api.github.com/gists{/gist_id}",
"hub_url": "https://api.github.com/hub",
...
}
```
上面的回应中,挑一个 URL 访问,又可以得到别的 URL。
对于用户来说,不需要记住 URL 设计,只要从 api.github.com 一步步查找就可以了。
HATEOAS 的格式没有统一规定上面例子中GitHub 将它们与其他属性放在一起。
更好的做法应该是,将相关链接与其他属性分开。
```
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "In progress",
"links": {[
{ "rel":"cancel", "method": "delete", "href":"/api/status/12345" } ,
{ "rel":"edit", "method": "put", "href":"/api/status/12345" }
]}
}
```
原文链接:[RESTful API 最佳实践](http://www.ruanyifeng.com/blog/2018/10/restful-api-best-practices.html)