转载来自:http://www.javashuo.com/article/p-zbtovhub-t.htmlphp
本文是为 腾讯大渝网 API开发规范拟定的一个beta版,文章大量参考了目前比较常见的RESETful API设计。html
为了更好的讨论规范带来的争议及问题,现已把该文档整理并开源到 github。前端
为了不歧义,文档大量使用了「能愿动词」,对应的解释以下:nginx
在经过API于后端服务通讯的过程当中,应该使用HTTPS协议。git
API的根入口点应尽量保持足够简单,这里有两个常见的URL根例子:github
若是你的应用很庞大或者你预计它将会变的很庞大,那应该将API放到子域下。这种作法能够保持某些规模化上的灵活性。json
全部的API必须保持向后兼容,你必须在引入新版本API的同时确保旧版本API仍然可用。因此应该为其提供版本支持。后端
目前比较常见的两种版本号形式:api
api.example.com/v1/*
这种作法是版本号直观、易于调试;另外一种作法是,将版本号放在HTTP Header头中:服务器
Accept: application/vnd.example.com.v1+json
其中vnd表示Standards Tree标准树类型,有三个不一样的树:x,prs和vnd。你使用的标准树须要取决于你开发的项目
后面几个参数依次为应用名称(通常为应用域名)、版本号、指望的返回格式。
至于具体把版本号放在什么地方,这个问题一直存在很大的争议,但因为咱们大多数时间都在使用Laravel开发,应该使用 dingo/api 来快速构建应用,它采用第二种方式来管理API版本,而且已集成了标准的HTTP Response。
端点就是指向特定资源或资源集合的URL。在端点的设计中,你必须遵照下列约定:
来看一个反例
再来看一个正列
对于资源的具体操做类型,由HTTP动词表示。经常使用的HTTP动词有下面五个(括号里是对应的SQL命令)。
其中
1 删除资源必须用DELETE方法
2 建立新的资源必须使用POST方法
3 更新资源应该使用PUT方法
4 获取资源信息必须使用GET方法
针对每个端点来讲,下面列出全部可行的HTTP动词和端点的组合
请求方法 | URL | 描述 |
---|---|---|
GET | /zoos | 列出全部的动物园(ID和名称,不要太详细) |
POST | /zoos | 新增一个新的动物园 |
GET | /zoos/{zoo} | 获取指定动物园详情 |
PUT | /zoos/{zoo} | 更新指定动物园(整个对象) |
PATCH | /zoos/{zoo} | 更新动物园(部分对象) |
DELETE | /zoos/{zoo} | 删除指定动物园 |
GET | /zoos/{zoo}/animals | 检索指定动物园下的动物列表(ID和名称,不要太详细) |
GET | /animals | 列出全部动物(ID和名称)。 |
POST | /animals | 新增新的动物 |
GET | /animals/{animal} | 获取指定的动物详情 |
PUT | /animals/{animal} | 更新指定的动物(整个对象) |
PATCH | /animals/{animal} | 更新指定的动物(部分对象) |
GET | /animal_types | 获取全部动物类型(ID和名称,不要太详细) |
GET | /animal_types/{type} | 获取指定的动物类型详情 |
GET | /employees | 检索整个雇员列表 |
GET | /employees/{employee} | 检索指定特定的员工 |
GET | /zoos/{zoo}/employees | 检索在这个动物园工做的雇员的名单(身份证和姓名) |
POST | /employees | 新增指定新员工 |
POST | /zoos/{zoo}/employees | 在特定的动物园雇佣一名员工 |
DELETE | /zoos/{zoo}/employees/{employee} | 从某个动物园解雇一名员工 |
若是记录数量不少,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。下面是一些常见的参数。
全部URL参数必须是全小写,必须使用下划线类型的参数形式。
常用的、复杂的查询应该标签化,下降维护成本。如
GET /trades?status=closed&sort=sortby=name&order=asc # 可为其定制快捷方式 GET /trades/recently_closed
应该使用OAuth2.0的方式为 API 调用者提供登陆认证。必须先经过登陆接口获取Access Token后再经过该token调用须要身份认证的API。
Oauth 的端点设计示列
客户端在得到access token的同时必须在响应中包含一个名为expires_in的数据,它表示当前得到的token会在多少秒后失效。
{ "access_token": "token....", "token_type": "Bearer", "expires_in": 3600 }
客户端在请求须要认证的API时,必须在请求头Authorization中带上access_token。
Authorization: Bearer token...
当超过指定的秒数后,access token就会过时,再次用过时/或无效的token访问时,服务端应该返回invalid_token的错误或401错误码。
HTTP/1.1 401 Unauthorized Content-Type: application/json Cache-Control: no-store Pragma: no-cache { "error": "invalid_token" }
Laravel 开发中,应该使用 JWT 来为管理你的 Token,而且必定不可在api中间件中开启请求session。
全部的API响应,必须遵照HTTP设计规范,必须选择合适的HTTP状态码。必定不可全部接口都返回状态码为200的HTTP响应,如:
HTTP/1.1 200 ok Content-Type: application/json Server: example.com { "code": 0, "msg": "success", "data": { "username": "username" } }
或
HTTP/1.1 200 ok Content-Type: application/json Server: example.com { "code": -1, "msg": "该活动不存在", }
下表列举了常见的HTTP状态码
状态码 | 描述 |
---|---|
1xx | 表明请求已被接受,须要继续处理 |
2xx | 请求已成功,请求所但愿的响应头或数据体将随此响应返回 |
3xx | 重定向 |
4xx | 客户端缘由引发的错误 |
5xx | 服务端缘由引发的错误 |
只有来自客户端的请求被正确的处理后才能返回2xx的响应,因此当 API 返回2xx类型的状态码时,前端必须认定该请求已处理成功。
必须强调的是,全部API必定不可返回1xx类型的状态码。当API发生错误时,必须返回出错时的详细信息。目前常见返回错误信息的方法有两种:
一、将错误详细放入HTTP响应首部;
X-MYNAME-ERROR-CODE: 4001 X-MYNAME-ERROR-MESSAGE: Bad authentication token X-MYNAME-ERROR-INFO: http://docs.example.com/api/v1/authentication
二、直接放入响应实体中;
HTTP/1.1 401 Unauthorized Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 10:02:59 GMT Connection: keep-alive {"error_code":40100,"message":"Unauthorized"}
考虑到易读性和客户端的易处理性,咱们必须把错误信息直接放到响应实体中,而且错误格式应该知足以下格式:
{ "message": "您查找的资源不存在", "error_code": 404001 }
其中错误码(error_code)必须和HTTP状态码对应,也方便错误码归类,如:
HTTP/1.1 429 Too Many Requests Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 10:15:52 GMT Connection: keep-alive {"error_code":429001,"message":"你操做太频繁了"}
HTTP/1.1 403 Forbidden Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 10:19:27 GMT Connection: keep-alive {"error_code":403002,"message":"用户已禁用"}
应该在返回的错误信息中,同时包含面向开发者和面向用户的提示信息,前者可方便开发人员调试,后者可直接展现给终端用户查看如:
{ "message": "直接展现给终端用户的错误信息", "error_code": "业务错误码", "error": "供开发者查看的错误信息", "debug": [ "错误堆栈,必须开启 debug 才存在" ] }
下面详细列举了各类状况 API 的返回说明。
200状态码是最多见的HTTP状态码,在全部 成功 的GET请求中,必须返回此状态码。HTTP响应实体部分必须直接就是数据,不要作多余的包装。
错误示例:
HTTP/1.1 200 ok Content-Type: application/json Server: example.com { "user": { "id":1, "nickname":"fwest", "username": "example" } }
正确示例:
一、获取单个资源详情
{ "id": 1, "username": "godruoyi", "age": 88, }
二、获取资源集合
[ { "id": 1, "username": "godruoyi", "age": 88, }, { "id": 2, "username": "foo", "age": 88, } ]
三、额外的媒体信息
{ "data": [ { "id": 1, "avatar": "https://lorempixel.com/640/480/?32556", "nickname": "fwest", "last_logined_time": "2018-05-29 04:56:43", "has_registed": true }, { "id": 2, "avatar": "https://lorempixel.com/640/480/?86144", "nickname": "zschowalter", "last_logined_time": "2018-06-16 15:18:34", "has_registed": true } ], "meta": { "pagination": { "total": 101, "count": 2, "per_page": 2, "current_page": 1, "total_pages": 51, "links": { "next": "http://api.example.com?page=2" } } } }
其中,分页和其余额外的媒体信息,必须放到meta字段中。
当服务器建立数据成功时,应该返回此状态码。常见的应用场景是使用POST提交用户信息,如:
等,均可以返回201状态码。须要注意的是,你能够选择在用户建立成功后返回新用户的数据
HTTP/1.1 201 Created Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Date: Sun, 24 Jun 2018 09:13:40 GMT Connection: keep-alive { "id": 1, "avatar": "https:\/\/lorempixel.com\/640\/480\/?32556", "nickname": "fwest", "last_logined_time": "2018-05-29 04:56:43", "created_at": "2018-06-16 17:55:55", "updated_at": "2018-06-16 17:55:55" }
也能够返回一个响应实体为空的HTTP Response如:
HTTP/1.1 201 Created Server: nginx/1.11.9 Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Date: Sun, 24 Jun 2018 09:12:20 GMT Connection: keep-alive
这里咱们应该采用第二种方式,由于大多数状况下,客户端只须要知道该请求操做成功与否,并不须要返回新资源的信息。
该状态码表示服务器已经接受到了来自客户端的请求,但还未开始处理。经常使用短信发送、邮件通知、模板消息推送等这类很耗时须要队列支持的场景中;
返回该状态码时,响应实体必须为空。
HTTP/1.1 202 Accepted Server: nginx/1.11.9 Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Date: Sun, 24 Jun 2018 09:25:15 GMT Connection: keep-alive
该状态码表示响应实体不包含任何数据,其中:
HTTP/1.1 204 No Content Server: nginx/1.11.9 Date: Sun, 24 Jun 2018 09:29:12 GMT Connection: keep-alive
全部API必定不可返回3xx类型的状态码。由于3xx类型的响应格式通常为下列格式:
HTTP/1.1 302 Found Server: nginx/1.11.9 Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 09:41:50 GMT Location: https://example.com Connection: keep-alive <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta http-equiv="refresh" content="0;url=https://example.com" /> <title>Redirecting to https://example.com</title> </head> <body> Redirecting to <a href="https://example.com">https://example.com</a>. </body> </html>
API必定不可返回纯HTML结构的响应;若必定要使用重定向功能,应该返回一个响应实体为空的3xx响应,并在响应头中加上Location字段:
HTTP/1.1 302 Found Server: nginx/1.11.9 Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Date: Sun, 24 Jun 2018 09:52:50 GMT Location: https://godruoyi.com Connection: keep-alive
因为明显的客户端错误(例如,请求语法格式错误、无效的请求、无效的签名等),服务器应该放弃该请求。
当服务器没法从其余 4xx 类型的状态码中找出合适的来表示错误类型时,都必须返回该状态码。
HTTP/1.1 400 Bad Request Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 13:22:36 GMT Connection: keep-alive {"error_code":40000,"message":"无效的签名"}
该状态码表示当前请求须要身份认证,如下状况都必须返回该状态码。
客户端在收到401响应后,都应该提示用户进行下一步的登陆操做。
HTTP/1.1 401 Unauthorized Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked WWW-Authenticate: JWTAuth Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 13:17:02 GMT Connection: keep-alive "message":"Token Signature could not be verified.","error_code": "40100"}
该状态码能够简单的理解为没有权限访问该请求,服务器收到请求但拒绝提供服务。
如当普通用户请求操做管理员用户时,必须返回该状态码。
HTTP/1.1 403 Forbidden Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 13:05:34 GMT Connection: keep-alive {"error_code":40301,"message":"权限不足"}
该状态码表示用户请求的资源不存在,如
都必须返回该状态码,若该资源已永久不存在,则应该返回410响应。
当客户端使用的HTTP请求方法不被服务器容许时,必须返回该状态码。
如客户端调用了POST方法来访问只支持 GET 方法的 API
该响应必须返回一个Allow头信息用以表示出当前资源可以接受的请求方法的列表。
HTTP/1.1 405 Method Not Allowed Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Allow: GET, HEAD Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 12:30:57 GMT Connection: keep-alive {"message":"405 Method Not Allowed","error_code": 40500}
API在不支持客户端指定的数据格式时,应该返回此状态码。如支持JSON和XML输出的API被指定返回YAML格式的数据时。
Http 协议通常经过请求首部的 Accept 来指定数据格式
客户端请求超时时必须返回该状态码,须要注意的时,该状态码表示 客户端请求超时,在涉及第三方API调用超时时,必定不可返回该状态码。
该状态码表示由于请求存在冲突没法处理。如经过手机号码提供注册功能的API,当用户提交的手机号已存在时,必须返回此状态码。
HTTP/1.1 409 Conflict Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 12:19:04 GMT Connection: keep-alive {"error_code":40900,"message":"手机号已存在"}
和404相似,该状态码也表示请求的资源不存在,只是410状态码进一步表示所请求的资源已不存在,而且将来也不会存在。在收到410状态码后,客户端应该中止再次请求该资源。
该状态码表示服务器拒绝处理当前请求,由于该请求提交的实体数据大小超过了服务器愿意或者可以处理的范围。
此种状况下,服务器能够关闭链接以避免客户端继续发送此请求。
若是这个情况是临时的,服务器应该返回一个Retry-After的响应头,以告知客户端能够在多少时间之后从新尝试。
该状态码表示请求的URI长度超过了服务器可以解释的长度,所以服务器拒绝对该请求提供服务。
一般表示服务器不支持客户端请求首部Content-Type指定的数据格式。如在只接受JSON格式的API中放入XML类型的数据并向服务器发送,都应该返回该状态码。
该状态码也可用于如:只容许上传图片格式的文件,可是客户端提交媒体文件非法或不是图片类型,这时应该返回该状态码:
HTTP/1.1 415 Unsupported Media Type Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 12:09:40 GMT Connection: keep-alive {"error_code":41500,"message":"不容许上传的图片格式"}
该状态码表示用户请求次数超过容许范围。如API设定为60次/分钟,当用户在一分钟内请求次数超过 60 次后,都应该返回该状态码。而且也应该在响应首部中加上下列头部:
X-RateLimit-Limit: 10 请求速率(由应用设定,其单位通常为小时/分钟等,这里是 10次/5分钟) X-RateLimit-Remaining: 0 当前剩余的请求数量 X-RateLimit-Reset: 1529839462 重置时间 Retry-After: 120 下一次访问应该等待的时间(秒)
列子
HTTP/1.1 429 Too Many Requests Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked X-RateLimit-Limit: 10 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1529839462 Retry-After: 290 Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 11:19:32 GMT Connection: keep-alive {"message":"You have exceeded your rate limit.","error_code":42900}
必须为全部的 API 设置 Rate Limit 支持。
该状态码必须在服务器出错时抛出,对于全部的500错误,都应该提供完整的错误信息支持,也方便跟踪调试。
该状态码表示服务器暂时处理不可用状态,当服务器须要维护或第三方API请求超时/不可达时,都应该返回该状态码,其中如果主动关闭 API 服务,应该在返回的响应首部加上Retry-After头部,表示多少秒后能够再次访问。
HTTP/1.1 503 Service Unavailable Server: nginx/1.11.9 Content-Type: application/json Transfer-Encoding: chunked Cache-Control: no-cache, private Date: Sun, 24 Jun 2018 10:56:20 GMT Retry-After: 60 Connection: keep-alive {"error_code":50300,"message":"服务维护中"}
其余HTTP状态码请参考 HTTP 状态码- 维基百科。
http://www.gitout.cn/?p=2536