【REST】RESTful API 淺談

注:本文純屬個人理解的瞎扯淡惶我,本人沒有看過 Roy Thomas Fielding 關(guān)于 REST 的 論文甩恼。

1. 望文生義 RESTful API

RESTful APIRESTful 有一個 -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 接口設計原則

  1. URI指向的是唯一的資源對象

示例: 指向ID為yanbo.aiAccount對象

GET http://~/$version/accounts/yanbo.ai
  1. URI可以隱式指向唯一的集合列表

示例: 隱式地指向trades list 集合

GET http://~/$version/trades/(list)
等同于
GET http://~/$version/trades
  1. 聚合資源必須通過父級資源操作

示例: ProfileUser的聚合資源胯杭,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"
}
  1. 組合資源要避免資源路徑嵌套

看一個路徑嵌套的例子

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組成

  1. 網(wǎng)絡協(xié)議(HTTP, HTTPS)
  2. 服務器地址
  3. 版本
  4. 接口名稱
  5. ?參數(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保證了v1v2接口的共存跟束。

示例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保證了v1v2接口的共存丑孩。

2.1.4 URL定義限制

  1. 不使用大寫字母
  2. 使用中線-代替下劃線_
  3. 參數(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ū)分?

  1. 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)共享的問題拄丰。

  2. 路由規(guī)則(邏輯)
    當我們需要對不同屬性的接口做路由規(guī)則的時候,按功能劃分接口是一個很好的方案俐末。例如:我們要對系統(tǒng)設置接口設置增加更嚴格的調(diào)用限制料按。

2.1.6 緩存

網(wǎng)絡接口相對于堆棧接口來說數(shù)據(jù)傳輸極其不穩(wěn)定,盡可能地減少數(shù)據(jù)傳輸不僅能控制這種風險還能減少流量卓箫。使用緩存還能有效地提高后臺的吞吐量载矿。
后臺在響應請求時使用響應頭E-TagLast-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è)務

  1. 用戶填寫E-Mail與密碼
  2. 完善用戶資料

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)方式的特點有:

  1. 資源所有者可以隨時撤銷授權(quán)許可
  2. 可以通過撤銷token拒絕客戶端的調(diào)用
  3. 資源服務器可以拒絕客戶端的調(diào)用

通過這三種方式可以做到對資源的嚴格保護誊爹。資源的訪問權(quán)限也把握在資源所有者的手中蹬刷,而不是資源服務器。

當然频丘,Oauth2授權(quán)框架也允許受信任的客戶端直接使用token調(diào)用資源服務器獲取資源办成。這種靈活性完全取決于客戶端類型和對資源的保護程度。

為什么授權(quán)碼要放在Http Header中?

  1. WEB服務器對訪問做記錄已經(jīng)成為了行業(yè)的一個標準搂漠,訪問記錄不僅可以用來做訪問量統(tǒng)計還能用來做訪問特征分析迂卢。互聯(lián)網(wǎng)廣告平臺就是利用訪問記錄來做精準營銷的。如果token(授權(quán)碼)包含在URL中就有很大的安全風險而克。
  2. 包含在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 交互原則

  1. 查詢螃壤,過濾條件使用query string。
  2. 用來描述數(shù)據(jù)或者請求的元數(shù)據(jù)放Header中筋帖,例如 X-Result-Fields奸晴。
  3. Content body 僅僅用來傳輸數(shù)據(jù)。
  4. 數(shù)據(jù)要做到拿來就可用的原則日麸,不需要“拆箱”的過程寄啼。
  5. 使用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 屬性定義限制

  1. 不能使用大寫(大小寫友好)
  2. 使用下劃線_命名(連接兩個單詞)
  3. 屬性和字符串值必須使用雙引號""

2.3.4 提取部分字段

無狀態(tài)服務器應該允許客戶端對數(shù)據(jù)按需提取戴陡。在請求頭使用X-Result-Fields指定數(shù)據(jù)返回的字段集合。
例如:trade 有trade_id, trade_name, created_at 三個屬性沟涨,客戶端只需其中的trade_idtrade_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)容:

  1. 錯誤標題 message, 必須
  2. 錯誤代碼 error code, 必須
  3. 錯誤信息 error message, 必須
  4. 資源 resource, 可選
  5. 屬性 field, 可選
  6. 文檔地址 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 錦上添花

  1. 格式化(Pettyprint)JSON數(shù)據(jù)(返回結(jié)果)并且使用gzip壓縮家坎,Pettyprint易于閱讀,多余的空格在經(jīng)過gzip壓縮之后占用空間比壓縮之前更小吝梅。
  2. 重寫Server
  3. 返回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

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虱疏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子苏携,更是在濱河造成了極大的恐慌做瞪,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件右冻,死亡現(xiàn)場離奇詭異装蓬,居然都是意外死亡,警方通過查閱死者的電腦和手機纱扭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門牍帚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人跪但,你說我怎么就攤上這事履羞÷臀” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵忆首,是天一觀的道長爱榔。 經(jīng)常有香客問我,道長糙及,這世上最難降的妖魔是什么详幽? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮浸锨,結(jié)果婚禮上唇聘,老公的妹妹穿的比我還像新娘。我一直安慰自己柱搜,他們只是感情好迟郎,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著聪蘸,像睡著了一般宪肖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上健爬,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天控乾,我揣著相機與錄音,去河邊找鬼娜遵。 笑死蜕衡,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的设拟。 我是一名探鬼主播慨仿,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼纳胧!你這毒婦竟也來了镶骗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤躲雅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后骡和,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體相赁,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年慰于,在試婚紗的時候發(fā)現(xiàn)自己被綠了钮科。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡婆赠,死狀恐怖绵脯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤蛆挫,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布赃承,位于F島的核電站,受9級特大地震影響悴侵,放射性物質(zhì)發(fā)生泄漏瞧剖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一可免、第九天 我趴在偏房一處隱蔽的房頂上張望抓于。 院中可真熱鬧,春花似錦浇借、人聲如沸捉撮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巾遭。三九已至,卻和暖如春修己,著一層夾襖步出監(jiān)牢的瞬間恢总,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工睬愤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留片仿,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓尤辱,卻偏偏與公主長得像砂豌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子光督,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348