本文主要簡述API設計的要點。總體會偏向HTTP的接口,部分一樣適合非HTTP的接口。html
控制維護的版本數,不宜過多
)url中指定版本信息
HTTP GET: https://haveibeenpwned.com/api/v2/breachedaccount/foojava
request headernginx
HTTP GET: https://haveibeenpwned.com/api/breachedaccount/foo api-version: 2
spring中直接@RequestMapping(headers="api-version=2")便可以自動分發
git
content-type acceptgithub
HTTP GET: https://haveibeenpwned.com/api/breachedaccount/foo Accept: application/vnd.haveibeenpwned.v2+json
content-type accept(版本單獨字段)web
HTTP GET: https://haveibeenpwned.com/api/breachedaccount/foo Accept: application/vnd.haveibeenpwned+json; version=2.0
對過時版本的處理
)對既有版本的訪問進行監控redis
對要下架的版本隨機返回錯誤算法
兩方認證vs三方認證
)兩方認證,只涉及api服務提供方和使用方;spring
三方認證,多了個用戶,一般是採用OAuth2來進行受權認證。json
下面的這些僅僅涉及兩方認證(雙方認證的 api 一般的認證方式是使用一組 id 和密鑰,用 id 來標記應用,用密鑰來對請求作簽名
):
開啓https(web api的話
)
Http Basic Authentication(通常內網使用配合https
)
在 Http header 中添加鍵值對 Authorization: Basic xxx (xxx 是 username:passowrd base64 值)。
黑白名單(內網白,外網黑
)
JWT (JSON Web Token)(適合移動端
)
JWT認證協議的格式爲Header.Payload.Signature。好比xxxxx.yyyyy.zzzzz。簽名內容是有Header+Payload+Secret經過HMAC SHA256算法加密而成。
具體參考Introduction to JSON Web Tokens
實例
限流方案
簡單的能夠用nginx的ip限流,複雜的能夠借用redis的計數器來實現各類規則的限流。
http的X-RateLimit header
HTTP/1.1 403 Forbidden Date: Tue, 20 Aug 2013 14:50:41 GMT Status: 403 Forbidden X-RateLimit-Limit: 60 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1377013266 { "message": "API rate limit exceeded. \ See http://developer.github.com/v3/ \ #rate-limiting for details." }
業界的兩個方案,一個是Swagger使用Swagger快速打造REST API文檔,一個是最新的spring restdocs
錯誤碼處理
建議充分利用http的錯誤碼,而後再細分,不建議本身再從新自定義一套。
請求成功
200 OK : 請求執行成功並返回相應數據,如 GET
成功
201 Created : 對象建立成功並返回相應資源數據,如 POST
成功;建立完成後響應頭中應該攜帶頭標 Location
,指向新建資源的地址
202 Accepted : 接受請求,但沒法當即完成建立行爲,好比其中涉及到一個須要花費若干小時才能完成的任務。返回的實體中應該包含當前狀態的信息,以及指向處理狀態監視器或狀態預測的指針,以便客戶端可以獲取最新狀態。
204 No Content : 請求執行成功,不返回相應資源數據,如 PATCH
, DELETE
成功
重定向
重定向的新地址都須要在響應頭 Location
中返回
301 Moved Permanently : 被請求的資源已永久移動到新位置
302 Found : 請求的資源如今臨時從不一樣的 URI 響應請求
303 See Other : 對應當前請求的響應能夠在另外一個 URI 上被找到,客戶端應該使用 GET
方法進行請求
307 Temporary Redirect : 對應當前請求的響應能夠在另外一個 URI 上被找到,客戶端應該保持原有的請求方法進行請求
條件請求
客戶端錯誤
400 Bad Request : 請求體包含語法錯誤
401 Unauthorized : 須要驗證用戶身份,若是服務器就算是身份驗證後也不容許客戶訪問資源,應該響應 403 Forbidden
403 Forbidden : 服務器拒絕執行
404 Not Found : 找不到目標資源
405 Method Not Allowed : 不容許執行目標方法,響應中應該帶有 Allow
頭,內容爲對該資源有效的 HTTP 方法
406 Not Acceptable : 服務器不支持客戶端請求的內容格式,但響應裏會包含服務端可以給出的格式的數據,並在 Content-Type
中聲明格式名稱
410 Gone : 被請求的資源已被刪除,只有在肯定了這種狀況是永久性的時候纔可使用,不然建議使用 404 Not Found
413 Payload Too Large : POST
或者 PUT
請求的消息實體過大
415 Unsupported Media Type : 服務器不支持請求中提交的數據的格式
422 Unprocessable Entity : 請求格式正確,可是因爲含有語義錯誤,沒法響應
428 Precondition Required : 要求先決條件,若是想要請求能成功必須知足一些預設的條件
服務端錯誤
500 Internal Server Error : 服務器遇到了一個不曾預料的情況,致使了它沒法完成對請求的處理。
501 Not Implemented : 服務器不支持當前請求所須要的某個功能。501
與 405
的區別是:405
是表示服務端不容許客戶端這麼作,501
是表示客戶端或許能夠這麼作,但服務端尚未實現這個功能
502 Bad Gateway : 做爲網關或者代理工做的服務器嘗試執行請求時,從上游服務器接收到無效的響應。
503 Service Unavailable : 因爲臨時的服務器維護或者過載,服務器當前沒法處理請求。這個情況是臨時的,而且將在一段時間之後恢復。若是可以預計延遲時間,那麼響應中能夠包含一個 Retry-After
頭用以標明這個延遲時間(內容能夠爲數字,單位爲秒;或者是一個 HTTP 協議指定的時間格式)。若是沒有給出這個 Retry-After
信息,那麼客戶端應當以處理 500 響應的方式處理它。
錯誤碼帶描述
503 Service Unavailable { "error_human": "The Database is currently unavailable.", "error_code": "database_unavailable" (使用文字描述比起使用數字code會使開發者更容易懂) }
分頁
GET /employees?left=true&fields=name,joinDate&limit=10&offset=0&sortby=name&order=asc { "data": { "total": 150, "employees": [ { "name": "tom", "joinDate": "2015-10-01" }, { "name": "jack", "joinDate": "2015-10-02" } ] } }
或者採用page的方式同時加入links提示
?page=1&pre_page=10 { "data": { "total": 150, "links": [ { "rel": "next", "href": "?page=2&per_page=10" }, { "rel": "last", "href": "?page=11&per_page=10" } ], "employees": [ { "name": "tom", "joinDate": "2015-10-01" }, { "name": "jack", "joinDate": "2015-10-02" } ] } }
或者
?limit=10: Reduce the number of results returned to the Consumer (for Pagination) ?offset=10: Send sets of information to the Consumer (for Pagination) ?limit=25&offset=50
排序
?sortby=name&order=asc: Sort the results based on the specified attribute (ORDER BY name ASC)
查詢字段選擇
GET http://api.example.org/user/12?fields=id,name,email (SELECT id, name, email FROM user WHERE user.id = 12)
查詢過濾
?q=fluffy+fur(搜索) ?animal_type_id=1: Filter records which match the following condition (WHERE animal_type_id = 1)
其餘
HATEOAS
HATEOAS是Hypermedia as the Engine of Application State的縮寫形式,中文意思爲:超媒體應用狀態引擎。它的核心思想是使用超媒體表達應用狀態,與hypertext-driven思想是一致的。在此以前,咱們大多數的程序業務控制在前臺完成。例如:咱們會在前臺作註冊流程,咱們在前臺斷定下一步應該作什麼,能夠作什麼。當使用HATEOAS時,這些狀態流程控制都在應用程序的後臺完成。咱們使用超媒體來表達前臺作完某一步驟以後能夠作哪些? 這樣一來,前臺的任務就變得至關簡單了,前臺須要處理的是理解狀態表述,數據收集和結果顯示。
url組成
網絡協議(HTTP, HTTPS)
服務器地址
版本
接口名稱(用-代替_
)
?參數列表(以後返回接口instagram是用_代替駝峯的
)
url命名限制
不使用大寫字母
使用中線-代替下劃線_,好比instagram的一個接口,https://api.instagram.com/v1/users/{user-id}/followed-by?access_token=ACCESS-TOKEN
參數列表應該被encode過
聚合資源必須經過父級資源操做
示例: Profile是User的聚合資源,User有一個惟一且私有的Profile資源,只能經過User操做Profile。/users/123456/profiles
組合資源要避免資源路徑嵌套
示例: 一個系統裏面包含多個 applications,一個 application 又包含多個 users。那獲取 user 資源的路徑應該是怎樣的?
GET http://~/$version/systems/:systemId/applications/:applicationId/users/:userId
改成
GET http://~/$version/systems/:systemId GET http://~/$version/applications/:applicationId GET http://~/$version/users/:userId/
HTTP 接口設計指北(推薦
)
Google JSON風格指南 (強烈推薦
)
RESTful最佳實踐(重點推薦
)