RESTful API 介紹及設計

2021-12-28 架構師
一:RESTful介紹

在網際網路發展過程中,最開始是以html靜態網頁展示內容,url的表現形式一般為 http://www.example.com/getInfo.html;後來隨著需求不斷提高以及為了應對這種需求,出現了動態網頁技術,在動態網頁技術中http請求的url形式一般為 http://www.example.com/getInfo.java?id=1&name=tom ,或者是重寫後的url形式http://www.example.com/getInfo/id/1/name/tom 等這種形式。其實這種url的形式是不是有點RESTful的樣子了,但是當時還沒有這種思想。

在2000年的時候,Roy Thomas Fielding博士在他的博士論文中提出了一種全球資訊網的軟體架構風格-REST(全稱:Representational State Transfer, 表現層狀態轉換),目的是便於在不同軟體/程序中(例如網際網路)中互相傳遞信息。這種表現層狀態轉換是基於HTTP協議之上而確定的一組約束和屬性,是一種設計提供全球資訊網服務的軟體架構風格。

題外話:他也是HTTP協議(1.0版和1.1版)的主要起草者之一、 Apache伺服器軟體的作者之一、Apache基金會的第一任主席。

符合或兼容於這種架構風格(簡稱為 REST 或 RESTful)的網絡服務,允許客戶端發出以統一資源標識符訪問和操作網絡資源的請求,而與預先定義好的無狀態操作集一致化。因此表現層狀態轉換提供了在網際網路的計算系統之間,彼此資源可交互使用的協作性質。(維基百科)

二:怎麼理解RESTful

上面的說明比較學術,其實我抓住幾個重點詞彙:網絡資源,資源標識符號,無狀態,表現層,狀態轉換。

網絡資源:就是我們需要獲取的數據,比如媒體,文本,圖片,視頻等等都可以看作是一種資源。

表現層:「資源」是一種信息實體,它可以有多種外在表現形式,比如上面網絡資源說明。我們把「資源」具體呈現出來的形式,叫做它的「表現層(Representation)」

資源標識符號:定位資源用的。就像門牌號碼可以定位到具體的房間。怎麼定位到你需要的資源?就需要用一個資源標識符-URI(統一資源定位符)。每種資源對應一個特定的URI。要獲取資源,訪問URI就可以,URI是每一個資源的獨一無二的地址。就像在網絡世界中,IP位址可以定位到獨一無二的一臺伺服器一樣。

無狀態:我們訪問網站時,就是客戶端和服務端的一次交互,這就涉及到數據和狀態的變化。無狀態就是每次訪問時,服務端不會保留客戶端的信息,每一次客戶端訪問服務端都是一次全新的訪問。HTTP協議就是一種無狀態協議。

狀態轉換:HTTP協議是一個無狀態的協議,意思是說所有的狀態都是保存在服務端。那麼客戶端要操作服務端,必須要通過某種手段,讓服務端發生「狀態轉換」(State Transfer)。而這種轉換是建立在表現層之上的,就是「表現層狀態轉換」。
HTTP協議是怎麼做到的?就是通過HTTP協議的方法METHOD來操作:GET、PUT、DELETE、POST、PATCH。它們分別對應的四種基本操作時:GET用來獲取資源,POST用來新建資源(也可以用於更新資源),PUT用來更新資源,DELETE用來刪除資源,PATCH用來更新部分資源。


三:RESTful 架構

有一種資源,每種資源有唯一的URI來標識。

對這種資源進行操作,實現狀態轉換。通常用HTTP的方法來操作。

誰來操作誰呢?客戶端對服務度資源的操作

具備上面的這幾種要素,就是RESTful架構。RESTful是一種設計風格。

四:RESTful API實踐API設計

RESTful API 是基於REST架構設計理念之下利用http協議來描述接口操作接口。
這種API設計主要描述幾個部分:

URL的設計,URL裡面當然包含了資源定位符。

Request參數

Response 返回數據

URL Request

一個URL設計,需要簡單,易懂,看到URL就能知道這個URL的意思,也就是自解釋,自描述。
看看http url的設計,分為協議,域名,path,method,參數。
我們應該可以得到啟發,它其實就是根據http協議而來。
比如獲取僱員url:GET /users, 動作方法+path

動作說明GET讀取 ReadPOST新建 CreatePUT更新 UpdatePATCH更新 Update ,一般為部分更新DELETE刪除 Delete

比如 GET 操作:

GET http://example.com/users 獲取所有的員工信息

GET http://example.com/users/23 獲取員工id=23的信息

方法/資源http://example.com/usershttp://example.com/users/23GET獲取所有的用戶信息獲取用戶id為23的信息POST在所有用戶信息中創建/追加一個新的用戶在id=23號用戶新增信息PUT更新該組用戶信息更新id=23號的用戶信息DELETE刪除所有的用戶信息刪除id=23號用戶信息PATCH更新所有用戶部分信息更新id=23號用戶信息

常見錯誤:
比如新建一個用戶:POST http://example.com/users/22 ,這種形式是錯誤的,應該用
POST http://example.com/users

上面的 example.com/users,users複數形式,而且是名詞。因為常見的操作是一個集合。所以一般建議用複數形式。不推薦使用 example.com/user/1這種形式,而是推薦使用example.com/users/1 複數這種形式。

錯誤的表示形式:

GET http://example.com/getusers - 不要使用這種帶有get動詞的形式

getusers 前面帶一個get是多餘的,因為http請求的動作就是GET,不用寫多餘的動作了。如果這樣寫的話,很容易造成大家理解api不統一。有可能前端和後端人員各自為政,用不同的動詞來操作url,造成大家開發理解的不統一。

類似的還有:

/createUsers

/updateUserInfo

/deleteUser?id=2

統一標準:前後端人員統一用http規定的幾個動作來進行url相關的操作。不需要在url後面加多餘的動作名詞。統一用一個標準,這樣前後端人員理解起來也能統一思想,便於大家協作開發。

在操作資源的時候,最簡單的操作是CURD,但是資源之間相互關聯也很常見,資源嵌套也很常見,比如查找id為10的用戶所有文章,這個URL如何設計?
一種設計:

GET /users/10/articles

獲取article的id=3文章

GET /users/10/articles/3

有人推薦這種方案,這種形式的 URI 一定程度上描述了 user 與 article 之間的一對多關係,但同時,我們就不太能夠分清當前端點返回的數據到底是 user 類型還是 article 類型。
這種設計語義不明確,也不利於擴展。

另一種設計,除了第一級,其他級別都用查詢字符串表達:

GET /articles?user_id=10
推薦使用這種方案。
比如用戶發布文章:GET /atticles?user_id=10&published=true

比如我們用獨立的api域名:api.example.com。
或者在域名後面加 api,這種形式 example.com/api/users 。
這樣有利於以後我們遷移,擴展。

是否在URL中加入版本號,有一個爭論。
有的認為不要在URL中加入版本號,可以在請求頭信息中加入。因為不同的版本,可以理解成同一種資源的不同表現形式,所以應該採用同一個URI。

Accept: application/example.com+json; version=3

有的則認為在URL中放入版本號,操作簡單。在api變更時候,更容易操作些:

GET api.example.com/v1/users

根據個人來選擇,一般推薦在url中寫上版本號。

篩選過濾複雜參數-複雜業務場景

對可選的、複雜的參數,使用查詢字符串querystring(?)

比如說有一些複雜的業務場景,比如對獲取的資源在進行條件篩選,還有排序,分頁等等
對於這些場景,RESTful api又怎麼設計?用querystring

比如某一個用戶已經發表的文章:
GET /users/10/posts?state=published
GET /users/10/posts?published=true

比如用戶分頁:
GET /users?page=1&page_size=10

在加條件,某一個用戶已經發表的文章太多,需要分頁:
GET /users/10/posts?published=true&page=2&page_size=10

針對多個欄位,不同的排序:
搜索用戶,並按照註冊時間升序、活躍度降序
GET /users?q=key&sort=create_time_asc,liveness_desc

GET /users?fields=id,title,desc;

github的搜索某一用戶分頁排序的api:
https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"
查詢的條件q,如果有需要還有分頁page,per_page,排序sort,order。

github某個用戶的repo,類型,分頁,排序
https://api.github.com/users/{user}/repos{?type,page,per_page,sort}",

github的api查看地址:https://api.github.com/

一些非資源的特殊請求

有時API調用並不涉及資源(如計算,翻譯或轉換)。例:

GET /translate?from=de_DE&to=en_US&text=Hallo
GET /calculate?para2=23&para2=432

在這種情況下,API響應不會返回任何資源。而是執行一個操作並將結果返回給客戶端。因此,您應該在URL中使用動詞而不是名詞,來清楚的區分資源請求和非資源請求。

返回格式和狀態碼統一

比如返回一個統一json格式:

Copy

{
code: 200, //返回的狀態碼
message: "200 OK", //返回信息簡單說明
data: { //返回的數據,如果返回時錯誤,那麼具體內容就是錯誤信息

}
}

狀態碼信息

1xx:相關信息
2xx:操作成功
3xx:重定向
4xx:客戶端錯誤
5xx:伺服器錯誤

2xx 狀態碼

200 表示操作成功,但是不同的方法可以返回更精確的狀態碼

GET: 200 OK
POST: 201 Created
PUT: 200 OK
PATCH: 200 OK
DELETE: 204 No Content

使用狀態碼 202 有時候會比 使用狀態啊嗎 201 是更好的選擇,狀態碼 202 的意思是:服務端已接收到了請求,但是還沒有創建任何資源,但結果一切正常

我分享兩種特別適合使用 202 Accepted 狀態碼的業務場景:

3xx 狀態碼

重定向,需要進一步的操作以完成請求

301 Moved Permanently:永久移動。請求的資源已被永久的移動到新URI,返回信息會包括新的URI,瀏覽器會自動定向到新URI。今後任何新的請求都應使用新的URI代替
302 Found:已找到。請求的資源已經在其他臨時位置找到,並應該在響應頭中返回該位置。只有GET和HEAD請求應該重定向到該位置。
304 Not Modified:未修改。所請求的資源未修改,伺服器返回此狀態碼時,不會返回任何資源。客戶端通常會緩存訪問過的資源,通過提供一個頭信息指出客戶端希望只返回在指定日期之後修改的資源

4xx 狀態碼

4xx 狀態碼表示客戶端的錯誤,主要有以下幾種:

400 Bad Request:伺服器不理解客戶端的請求,未做任何處理
401 Unauthorized:用戶未提供身份驗證憑據,或者沒有通過身份驗證
403 Forbidden:用戶通過了身份驗證,但是不具有訪問資源所需的權限
404 Not Found:所請求的資源不存在,或不可用
405 Method Not Allowed:該http方法不被允許。
406 Not Acceptable :GET, 用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)。
410 gone : 這個url對應的資源現在不可用。
415 Unsupported Media Type:客戶端要求的返回格式不支持。比如,API 只能返回 JSON 格式,但是客戶端要求返回 XML 格式
429 Too Many Requests : 請求太多 -由於速率限制而拒絕請求時

5xx 狀態碼

5xx 狀態碼表示服務端錯誤

500 Internal Server Error:客戶端請求有效,伺服器處理時發生了意外
502 Bad Gateway:作為網關或者代理工作的伺服器嘗試執行請求時,從上遊伺服器接收到無效的響應
503 Service Unavailable:伺服器無法處理請求,一般用於網站維護狀態
505 HTTP Version Not Supported: 伺服器不支持,或者拒絕支持在請求中使用的HTTP版本

Hypermedia API

RESTful API最好做到Hypermedia,即返回結果中提供連結,連向其他API方法,使得用戶不查文檔,也知道下一步應該做什麼。比如,當用戶向api.example.com的根目錄發出請求,會得到這樣一個文檔。

{
"link": {
"rel": "collection https://www.example.com/users",
"href": "https://api.example.com/users",
"title": "List of users",
"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的網址列表。

// https://api.github.com/

{
"current_user_url": "https://api.github.com/user",
"current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}",
"authorizations_url": "https://api.github.com/authorizations",
"code_search_url": "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}",
"commit_search_url": "https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}",
"emails_url": "https://api.github.com/user/emails",
"emojis_url": "https://api.github.com/emojis",

... ...
}

想獲取當前用戶信息,訪問 https://api.github.com/user,會返回

// https://api.github.com/user

{
"message": "Requires authentication",
"documentation_url": "https://developer.github.com/v3/users/#get-the-authenticated-user"
}

上面代碼表示,伺服器給出了提示信息,以及文檔的網址。

上面介紹的,其實是martin fowler 劃分RESTful api4個等級最高的一個等級:
他畫的api 4個等級圖:


(from: https://martinfowler.com/articles/richardsonMaturityModel.html)

總結URL上的一些設計技巧

使用 / 來表示資源層級關係

使用 ? 來過濾資源

使用 , 或 ; 來表示資源同級層關係

使用 _ 或 - 來表示更友好的URL形式

一些設計也可以參考github的v3: https://developer.github.com/v3/
或者一些其他大廠twitter, https://developer.twitter.com/en,
google等等

參考

https://zh.wikipedia.org/wiki/REST

http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

https://www.ruanyifeng.com/blog/2018/10/restful-api-best-practices.html

https://www.ruanyifeng.com/blog/2011/09/restful.html

https://blog.florimondmanca.com/restful-api-design-13-best-practices-to-make-your-users-happy

https://martinfowler.com/articles/richardsonMaturityModel.html

https://zh.wikipedia.org/wiki/HTTP狀態碼

https://www.w3.org/Protocols/rfc2616/rfc2616.html

·END·

如果您喜歡本文,歡迎點擊右上角,把文章分享到朋友圈~~

作者:九卷

來源:www.cnblogs.com/jiujuan/p/12791574.html

版權申明:內容來源網絡,版權歸原創者所有。除非無法確認,我們都會標明作者及出處,如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝!

我們都是架構師!

關注架構師(JiaGouX),添加「星標」

獲取每天技術乾貨,一起成為牛逼架構師

技術群請加若飛:1321113940 進架構師群

投稿、合作、版權等郵箱:admin@137x.com

相關焦點

  • 我是如何根據豆瓣api來理解Restful API設計的
    REST有著優雅、簡潔的特性,本文是根據豆瓣api來談談自己對restful的一些理解。2.URI規範URI 的格式:URI的格式定義如下:  URI = scheme "://" authority "/" path [ "?" query ] [ "#" fragment ]uri代表的是一種資源,要做到優雅、簡潔。
  • RESTful API 設計指南
    這導致API構架的流行,甚至出現」API First」的設計思想。RESTful API是目前比較成熟的一套網際網路應用程式的API設計理論。我以前寫過一篇《理解RESTful架構》,探討如何理解這個概念。今天,我將介紹RESTful API的設計細節,探討如何設計一套合理、好用的API。我的主要參考了兩篇文章(1,2)。
  • Restful API設計規範
    在當前流行的前後端分離架構,人們發現原來這套用於超文本傳輸的協議是如此適合用於設計基於網際網路的api接口,基於http動詞以及標準的http status返回信息,能夠非常好地描述api的特性,並且可讀性非常好。
  • Laravel 開發 RESTful API 的一些心得
    大方面,會涉及到給別人用的使用OAuth,自己使用的用token就足夠了設計最初,最好在路由加個版本號,方便以後擴展。只要 dist目錄的東西和根目錄的 index.html我還把 swagger-editor的 index.html改成了 edit.html,然後把這兩個東西整合到同一個目錄(記得修改css,js的位置)新建兩個文件 api.json, api.yaml 大概就和圖中差不多要修改圖中箭頭所示成為 api.json的位置
  • RESTful API 設計規範
    為了更好的討論規範帶來的爭議及問題,現已把該文檔整理並開源到 github (https://github.com/godruoyi/restful-api-specification),關於大家補充及提 issue。
  • axios中restful api的使用
    1引子在前端發送網絡請求的時候,現在最經常使用的是axios, 而axios的api中我們(確切說是我)最常用的就是post,而其他api很少有用到的場景。最近在做一個簡單需求(增刪改查)的時候,後端給的接口是restful風格的。看看吧:嗯,看到上圖我還沒感覺到什麼,接著看:
  • php Restful設計思路與步驟
    >文章來自於:博客文章連結博客https://blog.csdn.net/jj546630576/article/details/77948445商務合作請加微信號(QQ):2230304070 詳聊1、restful
  • 教你 10 分鐘構建一套 RESTful API 服務( 中 )
    if __name__ == '__main__':    app.run()從 flask_restful 文件中導入 Api、Resource 兩個類,使用上面的 app 對象,構建一個 api 對象,接著準備一個列表數據from flask_restful import Api,Resourceapp
  • Java springMVC] Restful風格API接口設計
    Restful風格API接口開發springMVC篇 Restful風格的API是一種軟體架構風格,設計風格而不是標準,只是提供了一組設計原則和約束條件
  • RESTful API設計的一點經驗
    前段時間的工作涉及產品開放API的設計與實現,整個過程大致可分為以下幾個步驟:根據需求、原有資料庫設計等,花了半天左右的工夫完成初稿
  • RESTful API 編寫指南
    更多關於CORS的介紹,有興趣的同學可以查看阮一峰老師的跨域資源共享 CORS 詳解6. URL RulesRESTful API 是寫給開發者來消費的,其命名和結構需要有意義。因此,在設計和編寫URL時,要符合一些規範。Url rules 可以單獨寫一篇博客來詳細闡述,本文只列出一些關鍵點。
  • 良好的 API 設計指南-RESTful API
    比如:http://api.qc.com/v1/newsfeed: 獲取某人的新鮮;http://api.qc.com/v1/friends: 獲取某人關系列表;http://api.qc.com/v1/profile: 獲取某人的詳細信息;URL是對資源描述的抽象,資源的描述一定是名詞,如果引入了動詞,那這個URL就表示了一個動作,而非一個資源
  • RESTful架構和RESTful API設計總結
    作者:智明書連結:https://www.jianshu.com/p/955eb2faa354REST這個詞是2000年Roy Fielding在他的博士論文中提出的,Fielding參與了http協議的設計
  • 理解RESTful API 架構設計規範與實踐
    摘要本文介紹了 REST 的由來,對 REST 的風格架構設計指導原則做了詳細的說明
  • 理解 RESTful API 設計規範
    ,它是用於Web數據接口的設計。它是基於HTTP、URI、XML、JSON等標準和協議,支持輕量級、跨平臺、跨語言的架構設計。一、理解為什麼要使用RESTful API設計規範?因此為了解決這個問題慢慢就出現了前後端分離的思想: 即後端負責數據接口, 前端負責數據渲染, 前端只需要請求下api接口拿到數據,然後再將數據顯示出來。因此後端開發人員需要設計api接口,因此為了統一規範: 社區就出現了 RESTful API 規範,其實該規範很早就有的,只是最近慢慢流行起來,RESTful API 可以通過一套統一的接口為所有web相關提供服務,實現前後端分離。
  • RESTFUL API 安全設計指南
    /ordersGET 獲取某個特定資源的信息 http://xx.com/api/orders/123POST 創建新資源 http://xx.com/api/ordersPUT 更新資源 http://xx.com/api/orders/123DELETE 刪除資源
  • 深入淺出RESTful API設計,小白也能看懂!
    因此,本文本著深入淺出的方法,加上圖片解釋的形式,為大家介紹一下RESTful API設計過程中應該注意的細節,以及其中的設計原理,讓零基礎的小白用戶也能理解。簡單來說,RESTful API 是基於HTTP協議產生的一種相對簡單的API設計方案,屬於無狀態傳輸。
  • 基於API而設計,你是如何調用接口與編寫接口的呢
    ;}點擊測試(對於客戶端而言,也是直接調用這樣的地址):http://www.mano100.cn/api/test/index.phphttp://www.mano100.cn/test/index.php?a=get_usershttp://www.mano100.cn/test/index.php?
  • RESTful API 設計學習筆記
    作者 : 韓子遲|原文:閱讀原文本文主要參考阮一峰的 RESTful API 設計指南
  • 深入理解 RESTful Api 架構
    RESTful Api 與 SOAP Web API 在 URL 形式上的對比從設計一個刪除評論的 api 說起 我們可以這樣設計成類似於:http://mengkang.net/?也有人如此設計而使用PUT,比如需要對 github 上的某人的項目 star ,則可能會設計成:http://github.com/xxx/zhoumengkang/projectname/star 這裡把「對這個項目已經點讚過」看成了一個資源,那麼就可以用PUT,因為要刪除這個資源時,還是訪問這個 URL。