好的RESTful API要基於HTTPS來發布 API規模不大時,在域名後面增長 api 目錄,如:https://www.trawe.cn/api/
API規模很大時,使用以api開頭的二級域名,如:https://api.trawe.cn/
git
新版本儘可能對舊版本做兼容github
版本信息放在URL中web
https://api.trawe.cn/v1.2/users/123
{ version: "1.0", .... .... }
使用已的HTTPHeader:Accept Header:Accept: application/json+v1.2 自定義 Header: X-Api-Version: 1.2
1) 命名算法
2) 不管對於單個資源仍是集合,名詞都使用複數形式,這樣便於風格的統一數據庫
GET /tickets # 獲取 tickets 列表 GET /tickets/12 # 獲取一個單獨的 ticket POST /tickets # 建立一個新的 ticket PUT /tickets/12 # 更新 ticket #12 PATCH /tickets/12 # 部分更新 ticket #12 DELETE /tickets/12 # 刪除 ticket #12 GET /tickets/12/messages # 獲取ticket #12下的消息列表 GET /tickets/12/messages/5 # 獲取ticket #12下的編號爲5的消息 POST /tickets/12/messages # 爲ticket #12建立一個新消息 PUT /tickets/12/messages/5 # 更新ticket #12下的編號爲5的消息 PATCH /tickets/12/messages/5 # 部分更新ticket #12下的編號爲5的消息 DELETE /tickets/12/messages/5 # 刪除ticket #12下的編號爲5的消息
3) 對於非CRUD的操做 有很非CRUD服務,能夠把這些服務當作資源,計算的結果是資源的presentation,按服務屬性選擇合適的HTTP方法。json
1. 從新構造這個Action,使得它像一個資源的操做。 這種方法在Action不包含參數的狀況下能夠奏效。例如一個有效的action能夠映射成布爾類型field,而且能夠經過PATCH更新資源。 2. 利用RESTful原則像處理子資源同樣處理它。 例如:Github的API讓你經過PUT /gists/:id/star 來 star a gist ,而經過DELETE /gists/:id/star來進行 unstar 。 3. 有時候你實在是沒有辦法將Action映射到任何有意義的RESTful結構。 例如:多資源搜索沒辦法真正地映射到任何一個資源接入點。這種狀況,/search 將很是有意義,雖然它不是一個名詞,可是這樣作沒有問題,只須要從API消費者的角度作正確的事,並確保所作的一切都用文檔清晰記錄下來了便可。
4) 查詢過濾 過濾: 對每個字段使用一個惟一查詢參數,就能夠實現過濾。 例如: 當經過 /tickets
終端來請求一個票據列表時,咱們須要增長一些限定來查詢那些在售的票。可使用 GET /tickets?state=open
這樣的請求來實現。這裏「state」是一個實現了過濾功能的查詢參數。api
對於經常使用的查詢,有如下兩種處理:跨域
GET /trades?status=closed&sort=created,desc
能夠包裝GET /trades/recently-closed
GET /trades?status=closed&sort=created,desc
能夠標籤化爲 GET /trades#recently-closed
排序: 跟過濾相似,使用排序參數字段來描述排序的規則。 爲適應複雜排序需求,讓排序參數採起逗號分隔的字段列表的形式,每個字段前均可能有一個負號來表示按降序排序。 例如:瀏覽器
排序字段前面的 +表示升序 -表示降序 默認爲升序 GET /tickets?sort=-priority # 獲取票據列表,按優先級字段降序排序 GET /tickets?sort=-priority,created_at # 獲取票據列表,按「priority」字段降序排序。在一個特定的優先級內,較早的票排在前面。
5) 減小層級深度 /
在url中表達層級,用於按實體關聯關係進行對象導航,通常根據id導航。 過深的導航容易致使url膨脹,不易維護,如 GET /zoos/1/areas/3/animals/4
,儘可能使用查詢參數代替路徑中的實體導航,如GET /animals?zoo=1&area=3
緩存
6) 限制返回哪些字段 使用一個字段查詢參數,它包含一個 用逗號隔開的字段列表。例如,下列請求得到的信息將剛剛足夠展現一個在售票的有序列表: GET /tickets?fields=id,subject,customer_name,updated_at&state=open&sort=-updated_at
7) 關於返回結果 一般狀況下只返回JSON
格式結果。 返回結果支持gzip壓縮:進行gzip壓縮的數據可節省50%以上的帶寬 對於須要返回不一樣格式資源的狀況:
Accept:application/xml;q=0.6,application/atom+xml;q=1.0
/users/1.xml
8) 分頁 經常使用的分頁字段以下:
limit=10:指定返回記錄的數量 offset=10:指定返回記錄的開始位置。 page=2&per_page=100:指定第幾頁,以及每頁的記錄數。
9) 緩存 ETag: 當產生一個請求時, 包含一個HTTP 頭,ETag會在裏面置入一個和表達內容對應的哈希值或校驗值。這個值應當跟隨表達內容的變化而變化。如今,若是一個入站HTTP請求包含了一個If-None-Match頭和一個匹配的ETag值,API應當返回一個304未修改狀態碼,而不是返回請求的資源。 Last-Modified: 基本上像ETag那樣工做,不一樣的是它使用時間戳。在響應頭中,Last-Modified包含了一個RFC 1123格式的時間戳,它使用If-Modified-Since來進行驗證。注意,HTTP規範已經有了 3 種不一樣的可接受的日期格式 ,服務器應當準備好接收其中的任何一種。
經常使用:
GET (選擇):從服務器上獲取一個具體的資源或者一個資源列表。 POST (建立): 在服務器上建立一個新的資源。 PUT (更新):以總體的方式更新服務器上的一個資源。 PATCH (更新):只更新服務器上一個資源的一個屬性。 DELETE (刪除):刪除服務器上的一個資源。
不經常使用:
HEAD : 獲取一個資源的元數據,如數據的哈希值或最後的更新時間。 OPTIONS:獲取客戶端能對資源作什麼操做的信息。
請求使用JSON格式時: { method: 'testMethod', // 請求方法名稱 version: '1.0', // 接口版本 token: '0X十六進制', // Token sign_type: 'MD5', // 簽名算法 sign: '0X十六進制', // 簽名 timestamp: '12345678' // 請求的時間戳 } 響應: { code: 0, // 返回碼。 -1:失敗 0:成功 其它:具體業務代碼 message: '處理成功', // 返回碼描述信息 sign: '0X十六進制', // 簽名 ... // 業務數據 }
響應數據不做多餘包裝,以下爲錯誤示例:
{ code: 0, data: {userName: "用戶名"} // 這裏面的data沒有業務含意,僅僅是爲了包裝,因此應該去掉 }
須要進行包裝的狀況:
HTTP定義了一套能夠從API返回的有意義的狀態代碼。 這些代碼可以用來幫助API使用者對不一樣的響應作出相應處理。
200 OK (成功) - 對一次成功的GET, PUT, PATCH 或 DELETE的響應。也可以用於一次未產生建立活動的POST 201 Created (已建立) - 對一次致使建立活動的POST的響應。 同時結合使用一個位置頭信息指向新資源的位置 204 No Content (沒有內容) - 對一次沒有返回主體信息(像一次DELETE請求)的請求的響應 304 Not Modified (未修改) - 當使用HTTP緩存頭信息時使用304 400 Bad Request (錯誤的請求) - 請求是畸形的, 好比沒法解析請求體 401 Unauthorized (未受權) - 當沒有提供或提供了無效認證細節時。若是從瀏覽器使用API,也能夠用來觸發彈出一次認證請求 403 Forbidden (禁止訪問) - 當認證成功可是認證用戶無權訪問該資源時 404 Not Found (未找到) - 當一個不存在的資源被請求時 405 Method Not Allowed (方法被禁止) - 當一個對認證用戶禁止的HTTP方法被請求時 410 Gone (已刪除) - 表示資源在終端再也不可用。當訪問老版本API時,做爲一個通用響應頗有用 415 Unsupported Media Type (不支持的媒體類型) - 若是請求中包含了不正確的內容類型 422 Unprocessable Entity (沒法處理的實體) - 出現驗證錯誤時使用 429 Too Many Requests (請求過多) - 當請求因爲訪問速率限制而被拒絕時
原則
API 可能拋出兩類異常:業務異常和非業務異常。 業務異常由本身的業務代碼拋出,表示一個用例的前置條件不知足、業務規則衝突等,好比參數校驗不經過、權限校驗失敗。 非業務類異常表示不在預期內的問題,一般由類庫、框架拋出,或因爲本身的代碼邏輯錯誤致使,好比數據庫鏈接失敗、空指針異常、除0錯誤等等。
業務類異常必須提供2種信息:
在Controller層使用統一的異常攔截器:
RESTful API最好作到Hypermedia,即返回結果中提供連接,連向其餘API方法,使得用戶不查文檔,也知道下一步應該作什麼。 好比,當用戶向api.example.com的根目錄發出請求,會獲得這樣一個文檔。
{"link": { "rel": "collection https://www.example.com/zoos", "href": "https://api.example.com/zoos", "title": "List of zoos", "type": "application/vnd.yourformat+json" }}
上面代碼表示,文檔中有一個link屬性,用戶讀取這個屬性就知道下一步該調用什麼API了。rel表示這個API與當前網址的關係(collection關係,並給出該collection的網址),href表示API的路徑,title表示API的標題,type表示返回類型。 Hypermedia API的設計被稱爲HATEOAS。Github的API就是這種設計,訪問api.github.com會獲得一個全部可用API的網址列表。
{ "current_user_url": "https://api.github.com/user", "authorizations_url": "https://api.github.com/authorizations", // ... }
從上面能夠看到,若是想獲取當前用戶的信息,應該去訪問api.github.com/user,而後就獲得了下面結果。
{ "message": "Requires authentication", "documentation_url": "https://developer.github.com/v3" }
上面代碼表示,服務器給出了提示信息,以及文檔的網址。