天天看點

你真的了解RESTful API嗎?概述RESTful6大原則最佳示例

前不久,在網上看到一個段子,一個碼農去面試,面試官問什麼是RESTful API,這看似一個很簡單的常識問題,碼農卻啞巴了。下面來看一下他們的對話:

面試官:了解RESTful嗎?
我:聽說過。
面試官:那什麼是RESTful?
我:就是用起來很規範,挺好的
面試官:是RESTful挺好的,還是自我感覺挺好的
我:都挺好的。
面試官:... 把門關上。
我:.... 要幹嘛?先關上再說。
面試官:我說出去把門關上。
我:what ?,奪門而去
           

是的,如果沒有去細細的研究,問我我估計也會這麼講,那究竟什麼是RESTful API,它有哪些規範呢?

概述

在沒有前後端分離概念之前,一個網站的完成總是“all in one”,在這個階段,頁面、資料、渲染全部在服務端完成,這樣做的最大的弊端是後期維護,擴充極其痛苦,開發人員必須同時具備前後端知識。

于是後來慢慢的興起了前後端分離的思想:即後端負責資料編造,而前端則負責資料渲染,前端靜态頁面調用指定api擷取到有固定格式的資料,再将資料展示出來,這樣呈現給使用者的就是一個”動态“的過程。

而關于api這部分的設計則成了一個問題。如何設計出一個便于了解,容易使用的api則成了一個問題,而所謂的RESTful就是用來規範我們的API的一種限制。

作為REST,其實是Representational State Transfer(表象層狀态轉變)三個單詞的縮寫,它由Roy Fielding于2000年論文中提出,它代表着分布式服務的架構風格。

要深刻了解消化Representational State Transfer這三個單詞到底意味着什麼,可以從以下幾個方面進行了解:

1.每一個URI代表一種資源;

2.用戶端和伺服器之間,傳遞這種資源的某種表現層;

3.用戶端通過四個HTTP動詞(get、post、put、delete),對伺服器端資源進行操作,實作”表現層狀态轉化”。

RESTful6大原則

REST之父Roy Fielding在論文中闡述REST架構的6大基本原則,它們分别是:

1. C-S架構

資料的存儲在Server端,Client端隻需使用就行。兩端徹底分離的好處使client端代碼的可移植性變強,Server端的拓展性變強。兩端單獨開發,互不幹擾。

2. 無狀态

http請求本身就是無狀态的,基于C-S架構,用戶端的每一次請求帶有充分的資訊能夠讓服務端識别。請求所需的一些資訊都包含在URL的查詢參數、header、div,服務端能夠根據請求的各種參數,無需儲存用戶端的狀态,将響應正确傳回給用戶端。無狀态的特征大大提高的服務端的健壯性和可拓展性。

當然,這種無狀态性的限制也是有缺點的,用戶端的每一次請求都必須帶上相同重複的資訊确定自己的身份和狀态,造成傳輸資料的備援性,但這種确定對于性能和使用來說,幾乎是忽略不計的。

3.統一的接口

REST架構的核心内容,統一的接口對于RESTful服務非常重要。用戶端隻需要關注實作接口就可以,接口的可讀性加強,使用人員友善調用。

REST接口限制定義為:資源識别; 請求動作; 響應資訊; 它表示通過uri标出你要操作的資源,通過請求動作(http method)辨別要執行的操作,通過傳回的狀态碼來表示這次請求的執行結果。

4.一緻的資料格式

服務端傳回的資料格式要麼是XML,要麼是Json(擷取資料),或者直接傳回狀态碼,一些知名網站的開放平台的操作資料的api,post、put、patch都是傳回的一個狀态碼 。

如請求一條微網誌資訊,服務端響應資訊應該包含這條微網誌相關的其他URL,用戶端可以進一步利用這些URL發起請求擷取感興趣的資訊,再如分頁可以從第一頁的傳回資料中擷取下一頁的URT也是基于這個原理。

5.可緩存

在網際網路上,用戶端可以緩存頁面的響應内容。是以響應都應隐式或顯式的定義為可緩存的,若不可緩存則要避免用戶端在多次請求後用舊資料或髒資料來響應。管理得當的緩存會部分地或完全地除去用戶端和服務端之間的互動,進一步改善性能和延展性。

6.按需編碼、可定制代碼

服務端可選擇臨時給用戶端下發一些功能代碼讓用戶端來執行,進而定制和擴充用戶端的某些功能。比如服務端可以傳回一些 Javascript 代碼讓用戶端執行,去實作某些特定的功能。提示:REST架構中的設計準則中,隻有按需編碼為可選項。如果某個服務違反了其他任意一項準則,嚴格意思上不能稱之為RESTful風格。

最佳示例

1. 版本控制

如github開放平台的API:http://developer.github.com/v3/

可以發現,一般的項目加版本v1,v2,v3版本号,為的是相容一些老版本的接口,這個加版本估計隻有大公司大項目才會去使用。

2.參數命名規範

query parameter可以采用駝峰命名法,也可以采用下劃線命名的方式,推薦采用下劃線命名的方式,據說後者比前者的識别度要高,其中,做前端開發基本都後後者,而做伺服器接口開發基本用前者。

http://example.com/api/users/today_login 擷取今天登陸的使用者
http://example.com/api/users/today_login&sort=login_desc 擷取今天登陸的使用者、登陸時間降序排列
           

3.url命名規範

API 命名應該采用約定俗成的方式,保持簡潔明了。在RESTful架構中,每個url代表一種資源,是以url中不能有動詞,隻能有名詞,并且名詞中也應該使用複數。實作者應使用相應的Http動詞GET、POST、PUT、PATCH、DELETE、HEAD來操作這些資源即可

不規範的的url,備援沒有意義,形式不固定,不同的開發者還需要了解文檔才能調用。

http://example.com/api/getallUsers       //GET 擷取所有使用者
http://example.com/api/getuser/1          //GET 擷取辨別為1使用者資訊
http://example.com/api/user/delete/1    //GET/POST 删除辨別為1使用者資訊
http://example.com/api/updateUser/1   //POST 更新辨別為1使用者資訊
http://example.com/api/User/add         //POST添加新的使用者
           

規範後的RESTful風格的url,形式固定,可讀性強,根據users名詞和http動詞就可以操作這些資源。

http://example.com/api/users               //GET 擷取所有使用者資訊
http://example.com/api/users/1           //GET 擷取辨別為1使用者資訊
http://example.com/api/users/1          //DELETE 删除辨別為1使用者資訊
http://example.com/api/users/1         //Patch 更新辨別為1使用者部分資訊,包含在div中
http://example.com/api/users           //POST 添加新的使用者
           

4,統一傳回資料格式

對于合法的請求應該傳回統一的資料格式,對于傳回資料,通常會包含如下字段。

  • code——包含一個整數類型的HTTP響應狀态碼。
  • status——包含文本:”success”,”fail”或”error”。HTTP狀态響應碼在500-599之間為”fail”,在400-499之間為”error”,其它均為”success”(例如:響應狀态碼為1XX、2XX和3XX)。這個根據實際情況其實是可要可不要的。
  • message——當狀态值為”fail”和”error”時有效,用于顯示錯誤資訊。參照國際化(il8n)标準,它可以包含資訊号或者編碼,可以隻包含其中一個,或者同時包含并用分隔符隔開。
  • data——包含響應的div。當狀态值為”fail”或”error”時,data僅包含錯誤原因或異常名稱、或者null也是可以的。

例如,傳回成功的響應json格式:

{
  "code": 200,
  "message": "success",
  "data": {
    "userName": "123456",
    "age": 16,
    "address": "beijing"
  }
}
           

傳回失敗的響應json格式:

{
  "code": 401,
  "message": "error  message",
  "data": null
}
           

5. http狀态碼

HTTP狀态碼也是有規律的:

1,請求未成功

2,請求成功、表示成功處理了請求的狀态代碼。

3,請求被重定向、表示要完成請求,需要進一步操作。通常,這些狀态代碼用來重定向。

4, 請求錯誤這些狀态代碼表示請求可能出錯,妨礙了伺服器的處理。

5,(伺服器錯誤)這些狀态代碼表示伺服器在嘗試處理請求時發生内部錯誤。這些錯誤可能是伺服器本身的錯誤,而不是請求出錯。

6. 合理使用query parameter

在請求資料時,用戶端經常會對資料進行過濾和分頁等要求,而這些參數推薦采用HTTP Query Parameter的方式實作。

//比如設計一個最近登陸的所有使用者
http://example.com/api/users?recently_login_day=3
           

//搜尋使用者,并按照注冊時間降序

http://example.com/api/users?recently_login_day=3

//搜尋使用者,并按照注冊時間升序、活躍度降序

http://example.com/api/users?q=key&sort=create_title_asc,liveness_desc

7. 多表、多參數連接配接查詢設計URL

在做單個實體的查詢比較容易和規範操作,但是在實際的API并不是這麼簡單而已,因為常常會設計到多表連接配接、多條件篩選、排序等。

比如我想查詢一個擷取在6月份的訂單中大于500元的且使用者位址是北京,使用者年齡在22歲到40歲、購買金額降序排列的訂單清單,那麼接口可能如下:

http://example.com/api/orders?order_month=6&order_amount_greater=500&address_city=北京&sort=order_amount_desc&age_min=22&age_max=40
           

從這個URL上看,參數衆多、調用起來還得一個一個仔細對着,而且API本身非常不容易維護,命名看起來不是很容易,不能太長,也不能太随意。

在.net WebAPI中,我們可以使用屬性路由,屬性路由就是将路由附加到特定的控制器或操作方法上裝飾Controll及其使用[Route]屬性,一種定義路由的方法稱為屬性路由。

這種好處就是可以精準地控制URL,而不是基于約定的路由,簡直就是為這種多表查詢量身定制似的的。從webapi 2開發,現在是RESTful API開發中最推薦的路由類型。

[Route(“api/orders/{address}/{month}”)]
           

而Action中的查詢參數就隻有金額、排序、年齡。減少了查詢參數、API的可讀性和可維護行增強了。

http://example.com/api/orders/beijing/6?order_amount_greater=500&sort=order_amount_desc&age_min=22&age_max=40
           

是以,在向别人介紹rest的時候,首先需要介紹服務背景,然後再介紹它的一些限制規則,切不可籠統介紹。

繼續閱讀