Restful API 設計

1. 簡介

目前 "互聯網軟件"從用客戶端/服務端模式,建立在分布式體系上,通過互聯網通訊,具有高延時、高開發等特點。但是軟件開發和網絡是兩個不同的領域,交集很少。要使得兩個融合,就要考慮如何在互聯網環境使用軟件。

REST 描述了一個架構樣式的網絡系統,2000 年 Roy Fielding 在他的博士論文中首次提出了 REST,同時他也是HTTP協議(1.0版和1.1版)的主要設計者、Apache服務器軟件的作者之一、Apache基金會的第一任主席。

目前主流的三種 Web 服務交互方案:

  • REST:表現層狀態轉化
  • SOAP(Simple Object Access protocol):簡單對象訪問協議
  • XML-RPC

要想理解什么是 REST(Representational State Transfe) 就要理解這里幾個詞是什么意思。

資源(Resources)

REST的名稱"表現層狀態轉化"中,省略了主語。"表現層"其實指的是"資源"(Resources)的"表現層"。

網絡中所謂資源即實體表現的一種,如:文本、圖片、音頻,視頻等。通過調用特定的 URI 來獲取相應資源,因此 URI 就成了每一個資源的地址或獨一無二的識別符。


表現層(Representation)

"資源"是一種信息實體,它可以有多種外在表現形式。我們把"資源"具體呈現出來的形式,叫做它的"表現層"(Representation)。

如:文本可以以 txt、json、xml 等格式表現,甚至是二進制格式,圖片也有 jpg、png 等格式。

URI 只代表資源的實體,不代表它的形式。嚴格地說,有些網址最后的.html 后綴名是不必要的,因為這個后綴名表示格式,屬于"表現層"范疇,而URI應該只代表"資源"的位置。它的具體表現形式,應該在HTTP請求的頭信息中用 Accept 和 Content-Type字段指定,這兩個字段才是對"表現層"的描述。


狀態轉化(State Transfer)

眾所周知互聯網通訊協議 HTTP 協議是無狀態的,所有狀態都保存在服務器上。因此如果客戶端要想操作(獲取、刪除、更新操作數據),就必須讓服務器狀態發生改變(State Transfer)而這種狀態轉化建立在表現層上,所有稱為 表現層狀態轉化

客戶端通過 HTTP 協議可以與服務端進行通信,HTTP 協議中表示操作的四個動作是:

  • GET:獲取資源
  • POST:新建資源
  • PUT:更新資源
  • DELETE:刪除資源

客戶端用到的手段,只能是HTTP協議。具體來說,就是HTTP協議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:GET用來獲取資源,POST用來新建資源(也可以用于更新資源),PUT用來更新資源,DELETE用來刪除資源。


RESTful架構典型的設計誤區

1、URI 中包含動詞:資源是一種實體,應該用名詞,動詞應放在 HTTP 協議中。

# 錯誤,show 為動詞
/posts/show/1# 如果要獲取可用 get
/posts/1
/get/         # 表示 show      

若某些動作用 HTTP 動詞表示不了,可用將動作看做一種資源,如:網上付款 URI 設計:

# 錯誤
POST /accounts/1/transfer/500/to/2# 正確
POST /transaction HTTP/1.1
Host: 127.0.0.1from=1&to=2&amount=500.00

2、在 URI 中加入版本號

# 錯誤
http://www.example.com/app/1.0/foo
http://www.example.com/app/1.1/foo

不同的版本,可以理解成同一種資源的不同表現形式,所以應該采用同一個U RI。版本號可以在HTTP請求頭信息的Accept字段中進行區分(參見 Versioning REST Services):

# 正確
Accept: vnd.example-com.foo+json; version=1.0
Accept: vnd.example-com.foo+json; version=1.1

然而實際開發中,大多開發人員會將版本號放在 URI 中,因為方便。


總結

什么是 RESTful 架構:

  • RESTful 是一種在網絡上能夠開發軟件的體系架構
  • 互聯網之間通訊是資源的一種交互
  • 每個 URI 代表一種資源,通過特定 URI 可以訪問相應資源
  • 資源有不同的表現形式
  • HTTP 協議無狀態
  • 客戶端獲取服務器資源,需要改變其狀態
  • 客戶端通過四個HTTP動詞,對服務器端資源進行操作,實現"表現層狀態轉化"

2. RESTful API 設計指南

2.1 協議

API與用戶的通信協議,總是使用HTTPs協議。

2.2 域名

1、應該盡量將 API 部署在專用域名之下,(這中情況會存在跨域問題)

https://api.example.com

2、如果確定 API 很簡單,不會有進一步擴展,可以考慮放在主域名下。

https://example.org/api/

2.3 版本(Versioning)

應該將 API 的版本號放入 URL。

https://api.example.com/v1/

另一種做法是,將版本號放在HTTP頭信息中,但不如放入URL方便和直觀。Github采用這種做法。

2.4 路徑(Endpoint)

路徑又稱"終點"(endpoint),表示 API 的具體網址。

在 RESTful 架構中,每個網址代表一種資源(resource),所以網址中不能有動詞,只能有名詞,而且所用的名詞往往與數據庫的表格名對應。一般來說,數據庫中的表都是同種記錄的"集合"(collection),所以 API 中的名詞也應該使用復數。

舉例來說,有一個API提供動物園(zoo)的信息,還包括各種動物和雇員的信息,則它的路徑應該設計成下面這樣。

  • https://api.example.com/v1/zoos
  • https://api.example.com/v1/animals
  • https://api.example.com/v1/employees

2.5 HTTP動詞

對于資源的具體操作類型,由 HTTP 動詞表示。常用的 HTTP 動詞有下面五個(括號里是對應的SQL命令):

  • GET(SELECT):從服務器取出資源(一項或多項)。
  • POST(CREATE):在服務器新建一個資源。
  • PUT(UPDATE):在服務器更新資源(客戶端提供改變后的完整資源)。
  • PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)。
  • DELETE(DELETE):從服務器刪除資源。

不常用的 HTTP 動詞:

  • HEAD:獲取資源的元數據。
  • OPTIONS:獲取信息,關于資源的哪些屬性是客戶端可以改變的。

下面是一些例子。

  • GET /zoos:列出所有動物園
  • POST /zoos:新建一個動物園
  • GET /zoos/ID:獲取某個指定動物園的信息
  • PUT /zoos/ID:更新某個指定動物園的信息(提供該動物園的全部信息)
  • PATCH /zoos/ID:更新某個指定動物園的信息(提供該動物園的部分信息)
  • DELETE /zoos/ID:刪除某個動物園
  • GET /zoos/ID/animals:列出某個指定動物園的所有動物
  • DELETE /zoos/ID/animals/ID:刪除某個指定動物園的指定動物

2.6 過濾信息(Filtering)

如果記錄數量很多,服務器不可能都將它們返回給用戶。API 應該提供參數,過濾返回結果。

下面是一些常見的參數:

# 指定返回記錄的數量
https://api.example.com/v1/zoos?limit=10# 指定返回記錄的開始位置
https://api.example.com/v1/zoos?offset=10# 指定第幾頁,以及每頁的記錄數
https://api.example.com/v1/zoos?page=2&per_page=100# 指定返回結果按照哪個屬性排序,以及排序順序
https://api.example.com/v1/zoos?sortby=name&order=asc# 指定篩選條件
https://api.example.com/v1/zoos?animal_type_id=1

參數的設計允許存在冗余,即允許API路徑和URL參數偶爾有重復。比如,GET /zoo/ID/animalsGET /animals?zoo_id=ID 的含義是相同的。

2.7 狀態碼(Status Codes)

服務器向用戶返回的狀態碼和提示信息,常見的有以下一些(方括號中是該狀態碼對應的HTTP動詞)。

  • 200 OK - [GET]:服務器成功返回用戶請求的數據,該操作是冪等的(Idempotent)。
  • 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
  • 202 Accepted - [*]:表示一個請求已經進入后臺排隊(異步任務)
  • 204 NO CONTENT - [DELETE]:用戶刪除數據成功。
  • 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操作,該操作是冪等的。
  • 401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。
  • 403 Forbidden - [*] 表示用戶得到授權(與401錯誤相對),但是訪問是被禁止的。
  • 404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操作,該操作是冪等的。
  • 406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)。
  • 410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再得到的。
  • 422 Unprocesable entity - [POST/PUT/PATCH] 當創建一個對象時,發生一個驗證錯誤。
  • 500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將無法判斷發出的請求是否成功。

狀態碼的完全列表參見這里。

2.8 錯誤處理(Error handling)

如果狀態碼是4xx,就應該向用戶返回出錯信息。一般來說,返回的信息中將 error 作為鍵名,出錯信息作為鍵值即可。

{error: "Invalid API key"
}

2.9 返回結果

針對不同操作,服務器向用戶返回的結果應該符合以下規范。

  • GET /collection:返回資源對象的列表(數組)
  • GET /collection/resource:返回單個資源對象
  • POST /collection:返回新生成的資源對象
  • PUT /collection/resource:返回完整的資源對象
  • PATCH /collection/resource:返回完整的資源對象
  • DELETE /collection/resource:返回一個空文檔

2.10 Hypermedia API

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"
}

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

其他

(1)API 的身份認證應該使用OAuth 2.0框架。

(2)服務器返回的數據格式,應該盡量使用JSON,避免使用XML。

轉載于:https://www.cnblogs.com/midworld/p/11075965.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/393078.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393078.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393078.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

sql行數少于10_如何用少于100行的代碼創建生成藝術

sql行數少于10by Eric Davidson埃里克戴維森(Eric Davidson) 如何用少于100行的代碼創建生成藝術 (How to Create Generative Art In Less Than 100 Lines Of Code) Generative art, like any programming topic, can be intimidating if you’ve never tried it before. I’v…

安裝輸入發

直接在系統 ——系統管理 ——語言支持 選——中文從新啟動 sudo apt-get install scim-pinyin安裝JAVA環境支持 sudo apt-get install sun-java-jre()要是 apt -get 命令不能用 可能是你 的 源有問題 可以 更新一下 在系統 -系統管理 源設置 選這臺灣的 就可以 …

(第2篇)一篇文章教你輕松安裝hadoop

摘要: 這篇文章將會手把手教你安裝hadoop,只要你細心按照文章中的步驟操作,hadoop肯定能正確安裝,絕對不會讓你崩潰 博主福利 給大家贈送一套hadoop視頻課程 授課老師是百度 hadoop 核心架構師 內容包括hadoop入門、hadoop生態架構以及大型ha…

linux cpio到指定目錄,linux cpio命令存取歸檔包中的文件

功能描述使用cpio命令可以通過重定向的方式將文件進行打包備份及還原恢復,它可以解壓縮以“.cpio”或者“.tar”結尾的文件。命令語 法cpio [選項] [目標目錄]選項含義選項含義-o執行 copy-out 模式,建立備份檔。-i執行 copy-in 模式,還原備份…

leetcode劍指 Offer 20. 表示數值的字符串

請實現一個函數用來判斷字符串是否表示數值(包括整數和小數)。例如,字符串"100"、“5e2”、"-123"、“3.1416”、"-1E-16"、“0123"都表示數值,但"12e”、“1a3.14”、“1.2.3”、"…

python接口自動化2-發送post請求

前言 發送post的請求參考例子很簡單,實際遇到的情況卻是很復雜的,首先第一個post請求肯定是登錄了,但登錄是最難處理的。登錄問題解決了,后面都簡單了。 一、查看官方文檔 1.學習一個新的模塊,其實不用去百度什么的&am…

簡介瀏覽器內核與JavaScript引擎

本文介紹了常用瀏覽器內核與JavaScript引擎 一、瀏覽器內核 Rending Engine, 顧名思義,稱之為渲染網頁內容的,將網頁的代碼轉換為你看得見的頁面,因為是排版,所以排版,所以肯定會有排版錯誤等問題。為什么會有排版錯誤…

Linux查看tar實用程序,linux tar指令常用選項

linux的tar指令經常被用到,因為壓縮文件的時候通常需要打包文檔,而tar指令就是打包指令,同時gzip壓縮程序和bzip2壓縮程序都是支持tar指令的,所以tar指令在打包的同時還可以用gzip和bzip進行壓縮,這樣多文件可以打包的…

代碼字體mono_如何構建代碼存儲庫:Multi,Mono或Organic?

代碼字體monoby Chetan Sharma由Chetan Sharma 如何構建代碼存儲庫:Multi,Mono或Organic? (How to Structure Code Repositories: Multi, Mono, or Organic?) The newest debate in town is whether you should keep your services in a si…

leetcode1424. 對角線遍歷 II(排序)

給你一個列表 nums ,里面每一個元素都是一個整數列表。請你依照下面各圖的規則,按順序返回 nums 中對角線上的整數。 示例 1: 輸入:nums [[1,2,3],[4,5,6],[7,8,9]] 輸出:[1,4,2,7,5,3,8,6,9] 代碼 class Solution …

DaVinci各版本安裝指南

鏈接: https://pan.baidu.com/s/1g1kaXZxcw-etsJENiW2IUQ?pwd0531 ? #2024版 1.鼠標右擊【DaVinci_Resolve_Studio_18.5(64bit)】壓縮包(win11及以上系統需先點擊“顯示更多選項”)【解壓到 DaVinci_Resolve_Studio_18.5(64bit)】。 2.打開解壓后的文…

使用 Servlet 讀取表單數據

Technorati 標簽: servlet;java 一、概述 Servlet 有一個比較好的功能就是可以自動處理表單提交的數據。我們只需要調用HttpServletRequest#getParameter(String name),就可以獲得指定參數的值(String),注意此方法是大小寫敏感的。…

linux文檔權限

1、登錄 root 用戶:su - mac一開始進入創建的用戶是具有管理員權限的用戶,但是密碼卻不是進入 root 用戶的密碼,可以使用 sudo su - 免密進入 root 用戶。 2、退出 root 用戶:exit 3、列出檔案(包括隱藏的檔案&#xf…

小程序 仿麥當勞_手機上的麥當勞和星巴克:為什么現在首先使用移動應用程序...

小程序 仿麥當勞by James Hsu由徐H 手機上的麥當勞和星巴克:為什么現在首先使用移動應用程序 (McDonald’s and Starbucks on Your Phone: Why Mobile Apps Are Now First on the Menu) One Friday this July, I got excited about McDonalds. So excited that I s…

MyLinkedList

/*** 節點類* author JP* */ class Node {Object value;//節點元素值Node pre;//上一個節點Node next;//下一個節點public Node(Object value) {this.value value;} }/*** 鏈表類* author JP**/ public class MyLinkedList {Node cur;//目前指向的節點Node head;//頭結點Node …

linux開啟ping服務,Linux 云服務器禁止和開啟Ping

原標題:Linux 云服務器禁止和開啟Ping在使用Linux服務器的時候,一般系統默認是開啟ping的,比如我們可以ping測試網絡的延遲質量。當然也有部分服務商是可以通過安全組設置禁止ping的,我們可以設置安全組對應項目開啟或禁止ping&am…

leetcode1432. 改變一個整數能得到的最大差值(貪心)

給你一個整數 num 。你可以對它進行如下步驟恰好 兩次 &#xff1a; 選擇一個數字 x (0 < x < 9). 選擇另一個數字 y (0 < y < 9) 。數字 y 可以等于 x 。 將 num 中所有出現 x 的數位都用 y 替換。 得到的新的整數 不能 有前導 0 &#xff0c;得到的新整數也 不能…

oracle之 Oracle歸檔日志管理

在Oracle中&#xff0c;數據一般是存放在數據文件中&#xff0c;不過數據庫與Oracle最大的區別之一就是數據庫可以在數據出錯的時候進行恢復。這個也就是我們常見的Oracle中的重做日志(REDO FILE)的功能了。在重做日志分成2部分&#xff0c;一個是在線重做日志文件&#xff0c;…

linux 安裝rmp服務,Linux LAMP服務的rpm包安裝與配置

1.apache(httpd) 所在光盤裝包apr-xxx.rpm (二)postgresql-libs-xxx.rpm (二)apr-util-xxx.rpm (二)http-xxx.rpm (二)2.mysql (二)裝包perl-DBI-xxx.rpm (二)mysql-xxx.rpm (二)3.mysqlserver裝包perl-DBD-mysql-xxx.rpm (二)mysql-server-xxx.rpm (二)4.PHP裝包gmp-xxx.rpm (…

紅外感應模塊+蜂鳴器實現簡易報警(轉)

拿到了一個紅外感應模塊HC-SR501&#xff0c;于是就用它和蜂鳴器簡單試驗了下。主要是試驗一下這個紅外感應模塊的功能&#xff0c;所以代碼也寫的很隨便啦&#xff0c;邏輯上也欠考慮。實現基本功能&#xff1a;運行腳本后&#xff0c;感應模塊每隔一定時間檢測&#xff0c;如…