注:本文純屬個人理解的瞎扯淡惶我,本人沒有看過 Roy Thomas Fielding 關(guān)于 REST 的 論文甩恼。
1. 望文生義 RESTful API
RESTful API 中 RESTful 有一個 -ful
詞綴捌蚊,明顯的毁欣,它是一個形容詞躲叼。
前面的 REST(Representational State Transfer) 就是個名詞厉亏,百度翻譯為:表述性狀態(tài)轉(zhuǎn)移。
表述性狀態(tài)轉(zhuǎn)移這個詞不好理解榔袋,因為在中文里沒有這么說的周拐,但是既然他是個形容詞,那么 RESTful API 強行翻譯一下就是:表述性狀態(tài)轉(zhuǎn)移的接口凰兑,在這里名詞作形容詞太拗口妥粟,準確來說應該是表述性狀態(tài)轉(zhuǎn)移那樣的接口,那么問題來了吏够,這不就等于沒說嗎勾给?其實也不是滩报,比如我們描述某個人,會說:那帥樣播急、那死樣脓钾,說的就是帥帥的那樣的、死氣沉沉那樣的桩警,是不是和前面說的很像可训,只是因為我們的語言習慣中沒有詞綴,而且默認轉(zhuǎn)移這個詞不是動詞就是名稱捶枢,那么就讓我們強行把它認作形容詞握截,一旦接受這個設定,好像就不是那么難以理解了烂叔。
但是強行認作形容詞總感覺有點怪怪的谨胞,于是就有人把 REST 來源文章標題中的 style 拿過來,翻譯成表述性狀態(tài)轉(zhuǎn)移風格的接口蒜鸡,這么一來就順多了胯努。但是 REST 本身就是原文中說到的那種軟件體系結(jié)構(gòu)風格的一種實現(xiàn),所以我認為約束一詞能更好的描述它术瓮,這樣一來就成了符合表述性狀態(tài)轉(zhuǎn)移約束的接口康聂,而這個約束是根據(jù) Roy Thomas Fielding 在論文中所描述的風格制定的。
現(xiàn)在明白了 RESTful API 是符合某種約束的接口胞四,那么這個約束是什么恬汁?這就要看表述性狀態(tài)轉(zhuǎn)移是什么了。我們可以把它拆開辜伟,變成 表述性
狀態(tài)
轉(zhuǎn)移
氓侧,其中,轉(zhuǎn)移是狀態(tài)的轉(zhuǎn)移导狡,狀態(tài)是以某種表述形式轉(zhuǎn)移的约巷。前面說到那帥樣、那死樣指的是人旱捧,那個這里是誰的狀態(tài)在轉(zhuǎn)移独郎?
是資源,以我們習慣的主謂賓形式講枚赡,就是以某種表述形式轉(zhuǎn)移資源的狀態(tài)氓癌,那么 RESTful API 就是以某種表述形式轉(zhuǎn)移資源狀態(tài)的接口。其中表述形式可以是 JSON贫橙、XML 等任何形式贪婉,狀態(tài)在我理解即資源本身,因為事物的狀態(tài)信息就是它自己(我也不知道從哪聽說的 0.0)卢肃。這時會注意到上面我說 RESTful 是形容詞疲迂,為什么又變成了以某種表述形式轉(zhuǎn)移資源狀態(tài)這樣的動詞了才顿,這只是英文和中文在表述上的不同,中文中形容詞后面往往跟著一個字:的尤蒿,所以這個的是不能分開的郑气,以某種表述形式轉(zhuǎn)移資源狀態(tài)的就是形容詞啦。
接下來就需要討論一下風格和約束了优质。
首先是風格竣贪,其在新華詞典中的解釋為:某一時期流行的一種藝術(shù)形式军洼,這也很好地詮釋了 REST 的目的:一種在未來十年或更久巩螃,不會過時的服務接口。就是說 REST 終究會過時匕争,但他目前很流行避乏。
風格是寬泛且多變的,拿服裝舉例甘桑,一個時代拍皮、一個民族、一個流派跑杭、一種性格狮荔、一種價值取向等都會衍生出一種服裝風格域蜗,像是常服、旗袍、晚宴裝宝鼓、Lolita 等。在 Lolita 這一風格中又會有甜美队询、古典往踢、哥特、龐克椭盏、和風组砚、田園等風格,在風格的風格中掏颊,又會有各種各樣的表現(xiàn)形式糟红。
那么這里的風格是什么?上面說到乌叶,轉(zhuǎn)移的是資源的狀態(tài)盆偿,所以我認為這里的風格就是:以資源為中心。
然后是約束枉昏,約束不同于規(guī)范陈肛,它是在一定的范圍內(nèi)有自由空間的,約束不會說你只能干什么兄裂,它只會說你不能干什么句旱,比如法律和道德就是約束阳藻。法律由國家制定,道德由社會發(fā)展自然形成谈撒,在 REST 中腥泥,約束由使用者自己定義,只要是以資源為中心風格的就可以啃匿。
但是有一個約束是自定義約束都要包括的蛔外,因為狀態(tài)只是在不停的轉(zhuǎn)移,它沒有變溯乒,所以這個約束就是:資源狀態(tài)在轉(zhuǎn)移過程中不能發(fā)生改變夹厌。
有人會說新增、刪除就改變了狀態(tài)啊裆悄。是的矛纹,新增、刪除肯定會改變資源狀態(tài)光稼,但是在我理解中或南,新增、刪除這種改變資源狀態(tài)的艾君,本身就不是轉(zhuǎn)移采够,所以不符合這個約束也是正常的,但是我們可以將這些操作的形式冰垄,在 API 表現(xiàn)上設計成和轉(zhuǎn)移一樣蹬癌,這樣看上去就很順眼了。
注意:只要 API 用的舒服播演,代碼敲得舒心冀瓦,不需要為了 REST 而 REST。如果你覺得 REST 使你快樂写烤,那就 REST翼闽,如果你覺得 REST 沒什么好處,反而是一大堆限制洲炊,那就不要 REST感局,畢竟人生苦短,開心就好暂衡。
2. HTTP RESTful API
上面說到 RESTful API 是一種風格的約束询微,所以 HTTP RESTful API 是 RESTful API 的一種實現(xiàn)。除了 HTTP狂巢,也可以用 MQTT撑毛、OpenWire、WebSocket 等協(xié)議實現(xiàn)這種約束唧领。但是因為 B/S 架構(gòu)使用非常廣泛藻雌,目前所說的 RESTful API 基本都是 HTTP 上的實現(xiàn)雌续。
本章照搬 RESTful 接口最佳實踐。
2.1 接口路徑設計
2.1.1 接口設計原則
- URI指向的是唯一的資源對象
示例: 指向ID為yanbo.ai
的Account
對象
GET http://~/$version/accounts/yanbo.ai
- URI可以隱式指向唯一的集合列表
示例: 隱式地指向trades list 集合
GET http://~/$version/trades/(list)
等同于
GET http://~/$version/trades
- 聚合資源必須通過父級資源操作
示例: Profile
是User
的聚合資源胯杭,User
有一個唯一且私有的Profile
資源驯杜,只能通過User
操作Profile
更新user_id為123456的Profile資源
PUT http://~/$version/users/123456/profiles
Request Body:
{
"full_name": "yanbo.ai",
"state": "Shanghai",
"title": "Senior software engineer"
}
- 組合資源要避免資源路徑嵌套
看一個路徑嵌套的例子
GET http://~/$version/systems/:systemId/applications/:applicationId/users/:userId
這樣做是不合理的,它會讓你的接口變得越來越混亂和缺少靈活性做个。正確的做法是:
GET http://~/$version/systems/:systemId
GET http://~/$version/applications/:applicationId
GET http://~/$version/users/:userId/
2.1.2 Http Methods
HTTP Operation | Description |
---|---|
GET | 獲取鸽心,查找 |
POST | 新增創(chuàng)建 |
PUT | 更新 |
PATCH | 部分更新 |
DELETE | 刪除 |
2.1.3 URL組成
- 網(wǎng)絡協(xié)議(HTTP, HTTPS)
- 服務器地址
- 版本
- 接口名稱
- ?參數(shù)列表
為什么需要版本?
當服務被更多其他系統(tǒng)使用的時候,服務的可用性和上下兼容變得至關(guān)重要居暖。被外部系統(tǒng)依賴的服務在升級時是一個非常麻煩的事情顽频,既要發(fā)布新的接口,又要保留舊的接口留出時間讓調(diào)用者去升級膝但。在URL中加入Version標示能很好地解決上下兼容(新老版本共存)問題冲九。
示例1: URL中新增了Path parameter
v1版本
GET http://~/v1/trades?user_id=123456
v2版本
GET http://~/v2/:user_id/trades
示例1中的user_id
參數(shù)在v2版本被加入到path parameter
中,使用$version
保證了v1
和v2
接口的共存跟束。
示例2: 數(shù)據(jù)接口發(fā)生變化
v1版本
GET http://~/v1/accounts/yanbo.ai
Response Body:
{
"user_name": "yanbo.ai",
"e_mail": "yanbo.ai@gmail.com",
"state": "Shanghai",
"title": "Senior software engineer"
}
v2版本
GET http://~/v2/accounts/yanbo.ai
Response Body:
{
"user_name": "yanbo.ai",
"e_mail": "yanbo.ai@gmail.com",
"profile": {
"state": "Shanghai",
"title": "Senior software engineer"
}
}
示例2中的接口返回數(shù)據(jù)結(jié)構(gòu)已經(jīng)發(fā)生了變化。使用$version
保證了v1
和v2
接口的共存丑孩。
2.1.4 URL定義限制
- 不使用大寫字母
- 使用中線-代替下劃線_
- 參數(shù)列表應該被encode過
2.1.5 接口分類
資源對象的CURD操作
GET http://~/$version/trades 獲取trades列表
GET http://~/$version/trades/:id 根據(jù)id獲取單個trade
POST http://~/$version/trades 創(chuàng)建trade
PUT http://~/$version/trades/:id 根據(jù)id更新trade
PATCH http://~/$version/trades/:id 根據(jù)id部分更新trade
DELETE http://~/$version/trades/:id 根據(jù)id刪除trade
服務型接口
使用services
標識冀宴,根據(jù)服務的屬性選擇http方法。
http://~/services/$version/server-name
系統(tǒng)設置
使用settings
標識温学,根據(jù)服務的屬性選擇http方法略贮。
http://~/settings/$version/server-name
示例1: 搜索
GET http://~/services/$version/search?q=filter?category=file
示例2: 任務隊列操作
PUT http://~/services/$version/queued/jobs 往任務隊列里面添加一個新的任務
DELETE http://~/services/$version/queued/jobs/:id 根據(jù)id刪除任務
示例3: 更改界面語言環(huán)境
PUT http://~/settings/$version/gui/lang
{
"lang": "zh-CN"
}
為什么需要區(qū)分?
Microservices
Microservices
是一個全新的概念,它主要的觀點是將一個大型的服務系統(tǒng)分解成多個微型系統(tǒng)仗岖。每個微型系統(tǒng)都能獨立工作逃延,并且提供各種不同的服務。獨立運行的特點使微型系統(tǒng)之間不會產(chǎn)生相互影響轧拄,其中的一個微型系統(tǒng)宕機并不會牽連到其他的微型系統(tǒng)揽祥。這種架構(gòu)使[分布式系統(tǒng)的節(jié)點數(shù)量][6]大大提升。因為RESTful服務是無狀態(tài)的檩电,所以這種分解并不會帶來狀態(tài)共享的問題拄丰。路由規(guī)則(邏輯)
當我們需要對不同屬性的接口做路由規(guī)則的時候,按功能劃分接口是一個很好的方案俐末。例如:我們要對系統(tǒng)設置接口設置增加更嚴格的調(diào)用限制料按。
2.1.6 緩存
網(wǎng)絡接口相對于堆棧接口來說數(shù)據(jù)傳輸極其不穩(wěn)定,盡可能地減少數(shù)據(jù)傳輸不僅能控制這種風險還能減少流量卓箫。使用緩存還能有效地提高后臺的吞吐量载矿。
后臺在響應請求時使用響應頭E-Tag
或Last-Modified
來標記數(shù)據(jù)的版本,前臺在發(fā)送請求時將數(shù)據(jù)版本通過請求頭If-None-Match
幫助后臺判斷緩存的使用烹卒。
Request Header
If-None-Match: 2390239059405940
Response Header
E-Tag: 2390239059405940
Last-Modified: 2014-04-05T14:30Z
2.1.7 Bookmarker
在實際的環(huán)境中闷盔,有大量的查詢需求是相同的魂挂。將這些搜索需求標簽化能降低使用難度也可以達到重用的目的。
示例1: 查找狀態(tài)為關(guān)閉的訂單
普通方式
GET http://~/$version/trades?status=closed&sorting=-created_at
Bookmarker
GET http://~/$version/trades#recently_closed
或
GET http://~/$version/trades/recently_closed
2.1.8 HATEOAS
HATEOAS通過Web Linking的方式來描述程序的狀態(tài)信息
Link 主要包含以下屬性:
Property | Description |
---|---|
rel | 關(guān)聯(lián)內(nèi)容 |
href | URL |
type | 媒體類型 |
method | Http Method |
title | 標題 |
arguments | 參數(shù)列表 |
value | 返回值 |
Rel
可能為以下值:
Value | Description |
---|---|
next | 下一步 |
prev | 上一步 |
first | 第一步馁筐,最前 |
last | 最后一步涂召,最后 |
source | 來源 |
self | 資源自身,相對于this |
Web Linking 可以通過兩種方式傳遞至客戶端:
Http Header
Link: <http://~/$version/trades?page_no=10>; rel="next", <http://~/$version/trades?page_no=19>; rel="last"
Http JSON Body
{
"links": [
{
"rel": "next",
"href": "http://~/$version/trades?page_no=1"
},
{
"rel": "last",
"href": "http://~/$version/trades?page_no=19"
}
]
}
示例1: 用戶注冊業(yè)務
- 用戶填寫E-Mail與密碼
- 完善用戶資料
Register Request
POST http://~/$version/accounts
Headers:
Accept: application/json
Content-Type: application/json;charset=utf-8
Body:
{
"username": "yanbo.ai@gmail.com",
"e_mail": "yanbo.ai@gmail.com",
"password": "balabala"
}
Register Response
Headers:
Content-Type: application/json;charset=utf-8
Status: 201 Created
Body:
{
"uri": "http://~/$version/accounts/yanbo.ai",
"identity": "yanbo.ai",
"created_at": "2014-04-05T14:30Z",
"links": [
{
"rel": "next",
"href": "http://~/$version/accounts/yanbo.ai/profiles",
"method": "POST",
"title": "Editing Profiles",
"arguments": "status=editing"
}
]
}
Profile Request
POST http://~/$version/accounts/yanbo.ai/profiles
Headers:
Accept: application/json
Content-Type: application/json;charset=utf-8
Body:
{
"full_name": "yanbo.ai",
"state": "Shanghai",
"title": "Senior software engineer"
}
Profile Response
Headers:
Content-Type: application/json;charset=utf-8
Status: 201 Created
Body:
{
"uri": "http://~/$version/accounts/yanbo.ai/profiles",
"identity": "yanbo.ai",
"created_at": "2014-04-05T14:30Z"
}
HATEOAS在解決什么問題?
HATEOAS是Hypermedia as the Engine of Application State的縮寫形式敏沉,中文意思為:超媒體應用狀態(tài)引擎果正。它的核心思想是使用超媒體表達應用狀態(tài),與hypertext-driven思想是一致的盟迟。在此之前秋泳,我們大多數(shù)的程序業(yè)務控制在前臺完成。例如:我們會在前臺做注冊流程攒菠,我們在前臺判定下一步應該做什么迫皱,可以做什么。當使用HATEOAS時辖众,這些狀態(tài)流程控制都在應用程序的后臺完成卓起。我們使用超媒體來表達前臺做完某一步驟之后可以做哪些? 這樣一來,前臺的任務就變得相當簡單了凹炸,前臺需要處理的是理解狀態(tài)表述戏阅,數(shù)據(jù)收集和結(jié)果顯示。
2.1.9 分頁
Request
GET http://~/$version/trades?page=10&pre_page=100
Response
Link Header
Link: <http://~/$version/trades?page=11&pre_page=100>; rel="next", <http://~/$version/trades?page=19&pre_page=100>; rel="last"
JSON Body
{
"links": [
{
"rel": "next",
"href": "http://~/$version/trades?page=11&pre_page=100"
},
{
"rel": "last",
"href": "http://~/$version/trades?page=19&pre_page=100"
}
]
}
2.2 安全
2.2.1 調(diào)用限制
為保證服務的可用性應對服務進行調(diào)用過載保護
Response Headers
X-RateLimit-Limit: 3000 調(diào)用量的最大限制
X-RateLimit-Reset: 1403162176516 調(diào)用限制重置時間
X-RateLimit-Remaining: 299 剩余的調(diào)用量
2.2.2 安全驗證
RESTful服務使用Oauth2的方式進行調(diào)用授權(quán)啤它,使用http請求頭Authorization
設置授權(quán)碼; 必須使用User-Agent
設置客戶端信息, 無User-Agent
請求頭的請求應該被拒絕訪問奕筐。
Request Header
User-Agent: Data-Server-Client
Authorzation: Bearer 383w9JKJLJFw4ewpie2wefmjdlJLDJF
為什么建議使用Oauth2授權(quán)?
Oauth2的參與者為:客戶端,資源所有者变骡,授權(quán)服務器离赫,資源服務器∷担客戶端先從資源所有者得到授權(quán)碼之后使用授權(quán)碼從授權(quán)服務器得到token
渊胸,再使用token
調(diào)用資源服務器獲取經(jīng)過資源所有者授權(quán)使用的資源。這種授權(quán)方式的特點有:
- 資源所有者可以隨時撤銷授權(quán)許可
- 可以通過撤銷token拒絕客戶端的調(diào)用
- 資源服務器可以拒絕客戶端的調(diào)用
通過這三種方式可以做到對資源的嚴格保護誊爹。資源的訪問權(quán)限也把握在資源所有者的手中蹬刷,而不是資源服務器。
當然频丘,Oauth2授權(quán)框架也允許受信任的客戶端直接使用token調(diào)用資源服務器獲取資源办成。這種靈活性完全取決于客戶端類型和對資源的保護程度。
為什么授權(quán)碼要放在Http Header中?
- WEB服務器對訪問做記錄已經(jīng)成為了行業(yè)的一個標準搂漠,訪問記錄不僅可以用來做訪問量統(tǒng)計還能用來做訪問特征分析迂卢。互聯(lián)網(wǎng)廣告平臺就是利用訪問記錄來做精準營銷的。如果token(授權(quán)碼)包含在URL中就有很大的安全風險而克。
- 包含在URL中的token串可能被進行重定向傳遞靶壮。通過這兩種方式入侵者可以不通過授權(quán)而使用泄漏的授權(quán)碼訪問那些受保護的數(shù)據(jù),會造成數(shù)據(jù)泄漏的風險员萍。
以Tomcat為例腾降,訪問日志為:
127.0.0.1 - - [24/Jun/2014:14:38:04 +0800] "GET /v1/accounts/yanbo.ai?token=dgdreLJLJLER798989erJKJK HTTPS/1.1" 200 343
通過對訪問日志的提取,很容易得到token信息碎绎。
2.3 數(shù)據(jù)設計
2.3.1 交互原則
- 查詢螃壤,過濾條件使用query string。
- 用來描述數(shù)據(jù)或者請求的元數(shù)據(jù)放Header中筋帖,例如
X-Result-Fields
奸晴。 - Content body 僅僅用來傳輸數(shù)據(jù)。
- 數(shù)據(jù)要做到拿來就可用的原則日麸,不需要“拆箱”的過程寄啼。
- 使用ISO-8601格式表達時間字段,例如:
2014-04-05T14:30Z
代箭。
2.3.2 結(jié)構(gòu)
使用JSON格式傳輸數(shù)據(jù)墩划,在http請求頭和響應頭申明Content-Type。返回的數(shù)據(jù)結(jié)構(gòu)應該做到盡可能簡單梢卸,不要過于包裝走诞。響應狀態(tài)應該包含在響應頭中!
Request
Accept: application/json
Content-Type: application/json;charset=UTF-8
Response
Content-Type: application/json;charset=UTF-8
錯誤的做法
{
"status": 200,
"data": {
"trade_id": 1234,
"trade_name": "Bala bala"
}
}
正確的做法
Response Headers:
Status: 200
Response Body:
{
"trade_id": 1234,
"trade_name": "Bala bala"
}
示例1: 創(chuàng)建User對象
POST http://~/$version/users
Request
headers:
Accept: application/json
Content-Type: application/json;charset=UTF-8
body:
{
"user_name": "Andy Ai"
}
Response
status: 201 Created
headers:
Content-Type: application/json;charset=UTF-8
body:
{
"uri": "http://~/$version/users/1234",
"identity": 1234,
"created_at": "2014-04-05T14:30Z",
"links": [
{
"rel": "next",
"href": "http://~/gui/users/1234"
}
]
}
為什么是JSON?
JSON
是一種可以跨平臺高擴展的輕量級的數(shù)據(jù)交換格式蛤高。易于人閱讀和編寫,同時也易于機器解析和生成碑幅。
2.3.3 屬性定義限制
- 不能使用大寫(大小寫友好)
- 使用下劃線_命名(連接兩個單詞)
- 屬性和字符串值必須使用雙引號""
2.3.4 提取部分字段
無狀態(tài)服務器應該允許客戶端對數(shù)據(jù)按需提取戴陡。在請求頭使用X-Result-Fields
指定數(shù)據(jù)返回的字段集合。
例如:trade 有trade_id
, trade_name
, created_at
三個屬性沟涨,客戶端只需其中的trade_id
與trade_name
屬性恤批。
Request Header
X-Result-Fields: trade_id,trade_name
2.3.5 子對象描述
數(shù)據(jù)里面的子對象使用URI描述不應該被提取,除非用戶指定需要提取子對象
示例: ·trade·里面的·order·對象
錯誤的做法
{
"trade_id": "123456789",
"full_path": null,
"order": {
"order_id": "987654321"
}
}
正確的做法
{
"trade_id": "123456789",
"order": "http://~/$version/orders/987654321"
}
應用指定提取子對象裹赴,需要在請求頭聲明X-Expansion-Fields
Request
X-Expansion-Fields: true
為什么要客戶端指定提取子對象時才提取?
懶模式服務能夠最大程度地節(jié)省運算資源喜庞。雖然與客戶端交互的次數(shù)有所增加,但是能做到按需提取棋返,按需響應延都,這也是響應式設計的一大特點【ⅲ客戶端的用戶行為模式無法真實地模擬晰房,也就無法確定哪些資源需要做到一次性推送,讓客戶端按需使用是一個不錯的方式。
關(guān)于空字段
應該在返回結(jié)果里面剔除空字段殊者,因為null值傳輸?shù)娇蛻舳瞬]有實際的含義与境,反而增加了占用空間。
Tips
使用HTTP Header時猖吴,優(yōu)先使用合適的標準頭屬性摔刁。用X-
作為前綴自定義一個頭屬性,例如: X-Result-Fields
2.4 狀態(tài)碼&錯誤處理
2.4.1 應用狀態(tài)碼
Code | HTTP Operation | Body Contents | Description |
---|---|---|---|
102 Processing | GET, POST, PUT, DELETE, PATCH | 處理狀態(tài)的信息 | 當前請求正在處理 |
200 Ok | GET, PUT | 資源 | 操作成功 |
201 Created | POST, PUT | 資源, 元數(shù)據(jù) | 對象創(chuàng)建成功 |
202 Accepted | POST, PUT, DELETE, PATCH | 處理信息 | 請求已經(jīng)被接受 |
204 No Content | DELETE, PUT, PATCH | N/A | 操作已經(jīng)執(zhí)行成功海蔽,但是沒有返回數(shù)據(jù) |
301 Moved Permanently | GET | link | 資源已被移除 |
303 See Other | GET | link | 重定向 |
304 Not Modified | GET | N/A | 資源沒有被修改 |
400 Bad Request | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 參數(shù)列表錯誤(缺少共屈,格式不匹配) |
401 Unauthorized | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 未授權(quán) |
403 Forbidden | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 訪問受限,授權(quán)過期 |
404 Not Found | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 資源准潭,服務未找到 |
405 Method Not Allowed | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 不允許的http方法 |
406 Not Acceptable | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 媒體內(nèi)容不符合要求 |
408 Request Timeout | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 請求超時 |
409 Conflict | GET, POST, PUT | 錯誤提示 | 資源沖突趁俊,重復的資源 |
415 Unsupported Media Type | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 不支持的數(shù)據(jù)(媒體)類型 |
422 Unprocessable Entity | GET, POST, PUT, PATCH | 錯誤提示 | 請求格式正確,但是由于含有語義錯誤刑然,無法響應寺擂。 |
423 Locked | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 當前資源被鎖定 |
429 Too Many Requests | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 請求過多被限制 |
500 Internal Server Error | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 系統(tǒng)內(nèi)部錯誤 |
501 Not Implemented | GET, POST, PUT, DELETE, PATCH | 錯誤提示 | 接口未實現(xiàn) |
2.4.2 容器狀態(tài)碼
Code | HTTP Operation | Body Contents | Description |
---|---|---|---|
303 | GET | link | 靜態(tài)資源被移除,應用限制使用 |
503 | GET, POST, PUT, DELETE, PATCH | text body | 服務器宕機 |
Tips
4開頭的錯誤用來表達來自于客戶端的錯誤,例如: 未授權(quán)泼掠,參數(shù)缺失怔软。5開頭的錯誤用來表達服務端的錯誤,例如: 在連接外部系統(tǒng)(DB)發(fā)生的IO錯誤择镇。
2.4.5 錯誤信息格式
錯誤信息應該包含下列內(nèi)容:
- 錯誤標題
message
, 必須 - 錯誤代碼
error code
, 必須 - 錯誤信息
error message
, 必須 - 資源
resource
, 可選 - 屬性
field
, 可選 - 文檔地址
document
, 可選
Tips
Error Code
盡可能做到簡潔明了挡逼,提取異常的關(guān)鍵字并且使用下劃線_把它們連接起來。
示例: 調(diào)用頻率超過限制腻豌,Response:
Headers:
Content-Type: application/json;charset=UTF-8
X-RateLimit-Limit: 3000
X-RateLimit-Reset: 1403162176516
X-RateLimit-Remaining: 0
{
"message": "Message title",
"errors": [
{
"code": "rate_limit_exceeded",
"message": "Too Many Requests. API rate limit exceeded",
"document": "https://developer.github.com/v3/gists/"
}
]
}
2.5 錦上添花
- 格式化(Pettyprint)JSON數(shù)據(jù)(返回結(jié)果)并且使用gzip壓縮家坎,Pettyprint易于閱讀,多余的空格在經(jīng)過gzip壓縮之后占用空間比壓縮之前更小吝梅。
- 重寫
Server
頭 - 返回
X-Powered-By
Response Headers
X-Pretty-Print: true
Content-Encoding: gzip
Server: ods@shuyun.com
X-Powered-By: yanbo.ai;email=yanbo.ai@gmail.com
參考