欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
優(yōu)秀REST風(fēng)格 API的設計原則

設計優(yōu)秀的REST風(fēng)格API非常困難!API是服務(wù)提供方和使用方之間的契約,打破該契約將會(huì )給服務(wù)端開(kāi)發(fā)人員招來(lái)非常大的麻煩,這些麻煩來(lái)自于使用API的開(kāi)發(fā)人員,因為對API的改動(dòng)會(huì )導致他們的移動(dòng)app無(wú)法工作。一個(gè)好的文檔對于解決這些事情能起到事半功倍的作用,但是絕對多數程序員都不喜歡寫(xiě)文檔。

如果想讓服務(wù)端的價(jià)值更好的體現出來(lái),就要好好設計API。通過(guò)這些API,你的服務(wù)/核心程序將有可能成為其他項目所依賴(lài)的平臺;目前的大公司:Facebook、Twitter、Google、Github、Amazon、Netflix等等無(wú)不依賴(lài)API,如果沒(méi)有精心設計的API對外開(kāi)發(fā)它們的數據,這些公司也就不會(huì )像今天這么強大。事實(shí)上,整個(gè)產(chǎn)業(yè)存在的目的就是消費上述平臺提供的數據。

你提供的API越易用,就會(huì )有越多人愿意使用它。

如果在設計API時(shí)能遵循本文檔提出的原則,那么你設計出的API就能讓調用方更容易理解和使用,也能大幅減少調用方對你的抱怨;我已將文檔內容按主題分別進(jìn)行詳細描述,讀者可選擇自己感興趣的主題,而無(wú)需順序閱讀。

本文檔中所使用的術(shù)語(yǔ)及其含義如下:

 

  •   Resource(資源):?jiǎn)蝹€(gè)實(shí)例對象,例如animal(一只動(dòng)物);[逍遙子筆記:Roy ThomasFielding(REST風(fēng)格的提出者)如此解釋資源的含義:一個(gè)資源可以是一份文檔、一張圖片、一個(gè)與時(shí)間相關(guān)的服務(wù)(例如:洛杉磯今天的天氣)等等,資源是實(shí)體的概念性映射,而不是實(shí)體本身;個(gè)人理解:一張圖片是一個(gè)資源,但是在我本機中有一個(gè)的名字叫做“jason.txt”的、實(shí)實(shí)在在的文件實(shí)體,就不能稱(chēng)作資源,它是資源實(shí)體,簡(jiǎn)單而言:“資源”與“資源實(shí)體”之間猶如類(lèi)和對象的關(guān)系。]
  •   Collection(集合):集合是一組同類(lèi)的實(shí)例對象,例如animals(一群動(dòng)物)。
  •   HTTP:一種在網(wǎng)絡(luò )上傳輸的通信協(xié)議;
  •   Consumer(使用方、用戶(hù)):能夠發(fā)送http請求的客戶(hù)端程序;[逍遙子筆記:這里Consumer實(shí)際是指API的調用方,如果直譯成消費者更讓人困惑]
  •   Third Party Developer(第三方開(kāi)發(fā)人員):不是你項目項目團隊的成員,但希望使用你的服務(wù)的那些開(kāi)發(fā)人員;
  •   Server(服務(wù)器):能夠被Consumer通過(guò)網(wǎng)絡(luò )訪(fǎng)問(wèn)的HTTP服務(wù)器/程序;
  •   Endpoint(端點(diǎn)):服務(wù)器提供的一個(gè)URL,它標識了一個(gè)資源(Resource)或者集合(Collection);[逍遙子筆記:這里理解為URL最后面的那個(gè)字段更合適,例如URL: https://api.example.com/vi/zoos的端點(diǎn)就是:/zoos;]
  •   Idempotent(冪等):多次重復操作得到的結果一樣;
  •   URL Segment(URL片段):從某個(gè)URL中取出的一小部分片段;

 

數據設計和抽象

規劃API的展示形式可能比你想象的要簡(jiǎn)單,首先要確定你的數據是如何設計以及核心程序是如何工作的?在新開(kāi)發(fā)項目中進(jìn)行API設計會(huì )比較容易,如果要對一個(gè)已經(jīng)存在的項目進(jìn)行修改使之符合REST風(fēng)格,那么你就需要在抽象方面多下功夫了。[逍遙子筆記:按照RoyThomas Fielding對REST的設計,REST風(fēng)格更適用于以數據為中心的架構,而非以計算為中心的架構]

有時(shí),集合(Collection)可以表示數據庫里的一張表,資源(Resource)表示表中的一行。[逍遙子筆記:這里的比喻感覺(jué)有些不恰當,數據庫的一行對應的是一個(gè)資源實(shí)體,而非資源!]但是多數情況不是這樣簡(jiǎn)單。事實(shí)上,你的API應該是對數據和業(yè)務(wù)邏輯的“盡可能的”抽象。非常重要的一點(diǎn)是:復雜的應用數據將會(huì )讓第三方開(kāi)發(fā)人員理解和使用起來(lái)非常困難,如果你這么做了,他們就不想使用你的API了。[逍遙子筆記:設計API時(shí),參數和返回值的數據不應太復雜,否則開(kāi)發(fā)人員發(fā)起調用和處理返回結果時(shí)都要處理半天,非常麻煩!]

有些情況下,服務(wù)的數據不能通過(guò)API暴露出來(lái)。一個(gè)常見(jiàn)的例子就是許多API都不允許第三方開(kāi)發(fā)人員創(chuàng )建用戶(hù)。[逍遙子筆記:設計API時(shí),需要提供什么功能時(shí)就提供什么API出來(lái),不要過(guò)早、過(guò)多暴露不必要的API接口,我們開(kāi)發(fā)過(guò)程中通常會(huì )遇到這種情況:無(wú)論能否用到,先把自己服務(wù)的所有功能暴露出來(lái)再說(shuō),說(shuō)不定就用上了,到時(shí)候就省得再修改了!]

動(dòng)作(Verbs)

你肯定知道HTTP的GET和POST請求,這是兩個(gè)通過(guò)瀏覽器訪(fǎng)問(wèn)各種網(wǎng)頁(yè)時(shí)最常用的請求。術(shù)語(yǔ)POST甚至變成一個(gè)人們的常用語(yǔ),即使不知道互聯(lián)網(wǎng)如何工作的用戶(hù)也知道能POST信息到朋友的Facebook留言板里。

你需要了解這里列出的4.5個(gè)非常重要的HTTP動(dòng)作,這里的0.5個(gè)是指PATCH,因為它在功能上與PUT非常類(lèi)似,剩下4個(gè)通常被API開(kāi)發(fā)人員兩兩結合使用[逍遙子筆記:例如GET和POST,PUT和DELETE]。這里是這些動(dòng)作以及它們對應的數據庫調用(我認為大多開(kāi)發(fā)人員更熟悉數據庫操作而不是設計API)。[逍遙子筆記:正式基于作者的這個(gè)理解,所以本文的很多地方都是用數據庫來(lái)解釋API,其實(shí)這個(gè)也非常恰當,因為REST架構風(fēng)格是基于資源的,而數據庫也是資源的一種形式。下面這些解釋中,括號里的內容就是與該HTTP動(dòng)詞類(lèi)似的數據庫操作]

 

  •   GET(SELECT):從服務(wù)器獲取一個(gè)指定資源或一個(gè)資源集合;
  •   POST(CREATE):在服務(wù)器上創(chuàng )建一個(gè)資源;
  •   PUT(UPDATE):更新服務(wù)器上的一個(gè)資源,需要提供整個(gè)資源;
  •   PATCH(UPDATE):更新服務(wù)器上的一個(gè)資源,只提供資源中改變的那部分屬性;
  •   DELETE(DELETE):移除服務(wù)器上的一個(gè)資源;

 

還有兩個(gè)不常見(jiàn)的HTTP動(dòng)作:

 

  •   HEAD – 獲取一個(gè)資源的元數據,例如一組hash數據或者資源的最近一次更新時(shí)間;
  •   OPTIONS – 獲取當前用戶(hù)(Consumer)對資源的訪(fǎng)問(wèn)權限;

 

一個(gè)優(yōu)秀的API將會(huì )充分利用這4.5個(gè)HTTP動(dòng)作讓第三方開(kāi)發(fā)人員與自己的數據交互,并且URL中決不包含動(dòng)作/動(dòng)詞。[逍遙子筆記:URL是對資源描述的抽象,資源的描述一定是名詞,如果引入了動(dòng)詞,那這個(gè)URL就表示了一個(gè)動(dòng)作,而非一個(gè)資源,這樣就偏離了REST的設計思想]

通常,GET請求能夠被瀏覽器緩存(而且通常都會(huì )這么做),例如,當用戶(hù)發(fā)起第二次POST請求時(shí),緩存的GET請求(依賴(lài)于緩存首部)能夠加快用戶(hù)的訪(fǎng)問(wèn)速度。一個(gè)HEAD請求基本上就是一個(gè)沒(méi)有返回體的GET請求,因此也能被緩存。

版本控制

無(wú)論你在設計什么系統,也不管你事先做了多么詳盡的計劃,隨著(zhù)時(shí)間的推移和業(yè)務(wù)的發(fā)展,你的程序總會(huì )發(fā)生變化,數據關(guān)系也會(huì )發(fā)生變化,資源可能會(huì )被添加或者刪除一些屬性。只要軟件還在生存期內并且還有人在用它,開(kāi)發(fā)人員就得面對這些問(wèn)題,對于A(yíng)PI設計來(lái)說(shuō),尤其如此。[逍遙子筆記:根據RoyThomas Fielding對資源的解釋?zhuān)嘿Y源描述和資源實(shí)體是分開(kāi)的,而設計REST API是基于資源描述,當資源實(shí)體發(fā)生變更時(shí),只要修改資源描述和資源實(shí)體的映射,就能保證資源描述不變,進(jìn)而保證所設計的API不變,所有使用API的第三方程序也不需要做任何修改,因此,REST風(fēng)格就是用于解耦這種服務(wù)端和客戶(hù)端的關(guān)系]

API是一份調用方(Consumer)和服務(wù)器之間已達成的契約,更改服務(wù)器的API必然會(huì )影響其向后兼容性,對契約的破壞將會(huì )招致使用方(Consumer)的抱怨,如果你改動(dòng)很大,他們可能會(huì )放棄使用你的服務(wù)。為了確保服務(wù)器程序能夠進(jìn)化升級,同時(shí)能夠讓使用方感到滿(mǎn)意,你需要在引入新版本API的同時(shí)繼續讓舊版本的API正常工作。

注意,如果你只是簡(jiǎn)單地為API增加一些新特性,例如為資源增加新屬性(這些新屬性并非必須的,沒(méi)有它們資源也能工作),或者新增了端點(diǎn),那就不需要升級API的版本號,因為這些變化并不會(huì )破壞向后的兼容性。當然,你還是需要更新API設計文檔(你和調用方的契約)。[逍遙子筆記:文檔對于A(yíng)PI來(lái)說(shuō)太重要了,沒(méi)有好的文檔必然沒(méi)有好的API,因此API和它的文檔一定同步修改,甚至要先修改文檔]

過(guò)一段時(shí)間之后,你可以告訴調用方不建議(deprecate)使用舊版本[逍遙子筆記:就像java里面的depredated注釋一樣,用于告訴使用方,我不建議你使用它了,過(guò)一段時(shí)間之后我可能就不支持它了]。不建議使用一個(gè)API并不意味著(zhù)馬上就要關(guān)閉它或者降低它的服務(wù)質(zhì)量,而是告訴你的API使用人員他們需要版本升級,舊的版本將在未來(lái)一段時(shí)間之后被停止服務(wù)。[逍遙子筆記:通過(guò)過(guò)渡期來(lái)提醒用戶(hù)升級API,明確告訴調用方什么API處在過(guò)渡期,過(guò)渡期內新老版本同時(shí)都能工作,但老版本在過(guò)渡期之后就會(huì )被去掉]

在URL中加入版本號是一個(gè)優(yōu)秀的API設計,當然還有另一個(gè)常用的解決辦法就是把版本號放在請求首部中[逍遙子筆記:HTTP請求的accept字段],根據多年與第三方開(kāi)發(fā)人員打交道的經(jīng)驗,我可以告訴你把版本號放在URL里要比放在請求的首部中更容易實(shí)現和使用。[逍遙子筆記:對這種方法還有一些疑問(wèn),個(gè)人理解,版本應該標識資源,也就是版本是針對URL尾部的端點(diǎn),例如https://api.example.com/vi/zoos中的/zoos,按照這種思路,當一個(gè)項目包含很多類(lèi)型的資源,這些資源需要要分級進(jìn)行展示,此時(shí)版本號放在URL里可能遇到很多問(wèn)題,例如:有個(gè)即時(shí)通信項目IM,它包含user_info(用戶(hù)信息),user_rel(用戶(hù)關(guān)系),message三個(gè)資源大類(lèi),其中user_info又分為公開(kāi)信息public和私有信息private兩個(gè)類(lèi)型,public類(lèi)型包括個(gè)人簡(jiǎn)介的二維碼信息self_info,private類(lèi)型包括個(gè)人的應用鎖信息lock, user_rel(用戶(hù)關(guān)系)類(lèi)型包括好友關(guān)系friends和群組groups兩個(gè)類(lèi)型,groups包含群成員member和群信息info兩個(gè)子類(lèi)型資源,messge包含新聊天消息new和歷史聊天消息history,這些資源組織成樹(shù)狀結構后如下圖所示:

 

假設我的URL根(在本文后面將會(huì )介紹URL的根)為:https://test.jason.com/im/*,那么上述資源對應的URL為:

(1)https://test.jason.com/im/user_info/public/self_info 

該URL表示資源:用戶(hù)個(gè)人簡(jiǎn)介的二維碼信息;

(2)https://test.jason.com/im/user_info/private/lock

該URL表示資源:用戶(hù)的應用鎖信息;

(3)https://test.jason.com/im/user_rel/friends

該URL表示資源:用戶(hù)的好友信息

(4)https://test.jason.com/im/user_rel/groups/member

該URL表示資源:群組的群成員

(5)https://test.jason.com/im/user_rel/groups/info

該URL表示資源:群組的信息

(6)https://test.jason.com/im/message/new

該URL表示資源:用戶(hù)新聊天消息

(7)https://test.jason.com/im/message/history

該URL表示資源:用戶(hù)的歷史聊天消息

問(wèn)題是:在這種情況下版本號應該放在URL的那個(gè)地方?

如果版本號是針對IM整個(gè)項目,例如這里的IM項目整體分為v1和v2兩個(gè)大版本,此時(shí)的URL首部就能改成:https://test.jason.com/im/v1/*,https://test.jason.com/im/v2/*,實(shí)際的URL資源將變成:https://test.jason.com/im/v1/message/new。

如果版本號是針對IM項目中的某個(gè)子類(lèi),例如這里的message類(lèi)型分為v1和v2兩個(gè)版本,那么消息類(lèi)的URL根就會(huì )變成:https://test.jason.com/im/message/v1/*,https://test.jason.com/im/message/v2/*,實(shí)際的URL資源將會(huì )變成:https://test.jason.com/im/message/v1/new。

如果版本號針對的資源類(lèi)型更詳細,那么版本號就會(huì )更靠后。在一些負責類(lèi)型的項目中,資源的類(lèi)型也會(huì )非常復雜,層級也更深,按照本文作者建議的方法就很難確定v1的位置]

分析

跟蹤各版本/端點(diǎn)的API被調用的情況[逍遙子筆記:由此可見(jiàn)版本號對應URL末尾的“端點(diǎn)”]??梢酝ㄟ^(guò)在數據庫中為每個(gè)API增加一個(gè)計數器來(lái)實(shí)現,來(lái)一個(gè)請求就將對應的使用計數加1。統計各API的調用情況會(huì )帶來(lái)很多好處,例如,優(yōu)化調用頻度最高的API。

為了構建第三方開(kāi)發(fā)人員喜歡的API,最重要事情是確定何時(shí)不建議(deprecate)用戶(hù)使用舊版本API,你可以使用這些不建議的(deprecated)API來(lái)告知第三方開(kāi)發(fā)人員,這是在你廢掉舊版本之前提醒他們的一個(gè)好途徑。

通知第三方開(kāi)發(fā)人員的過(guò)程可以自動(dòng)化完成,例如,每調用10,000次deprecated API就給相應開(kāi)發(fā)人員發(fā)一個(gè)郵件提醒。

API的根URL

無(wú)論你是否相信,API的根設計非常重要。當開(kāi)發(fā)人員接手一個(gè)使用你的API所開(kāi)發(fā)的舊項目,并且需要為它增加新特性的時(shí)候,他可能完全不了解你的服務(wù),或許他們知道的就是所調用的一系列URL。重要的是你API的URL根應該盡可能簡(jiǎn)單,一個(gè)又長(cháng)又復雜的URL看起來(lái)就嚇人,它很可能就把這些第三方開(kāi)發(fā)人員嚇跑了。

這里有兩個(gè)普通的URL根:

 

  •   https//example.org/api/vi/*
  •   https//example.com/vi/*

 

如果你的應用程序很龐大,或者未來(lái)它可能變得很龐大,你可以把API放在各自的子域內,這么做可以讓你的程序在以后的發(fā)展中更靈活、更容易擴展。[逍遙子筆記:這里作者想表達的意思好像是把URL所表示的資源進(jìn)行分類(lèi)、分層級,不同的資源放在不同的類(lèi)中]

如果你的程序不會(huì )變得這么大,或者你想簡(jiǎn)化程序的使用(例如,你想通過(guò)一個(gè)框架同時(shí)提供網(wǎng)站和API服務(wù)),就把你的API放在URL的根域(例如:/api/)之后。

最好讓你API的根也包含內容。例如,訪(fǎng)問(wèn)githubAPI的根就會(huì )得到一個(gè)端點(diǎn)(端點(diǎn)代表資源)列表。我更偏好使用根URL獲取那些對“正在迷茫中的”開(kāi)發(fā)人員來(lái)說(shuō)有用的信息,例如:怎么獲取API的開(kāi)發(fā)者文檔。

注意使用HTTPS前綴,一個(gè)好的RESTfulAPI必須使用HTTPS作為前綴。[逍遙子筆記:例如:https://api.example.com/v1/zoos]

端點(diǎn)

端點(diǎn)是URL中用于標識一個(gè)特定資源或資源集合的那部分URL片段。[逍遙子筆記:例如:https://api.example.com/v1/zoos中的/zoos]

假如你想構建用于表示多個(gè)動(dòng)物園資源的API,其中,每個(gè)動(dòng)物園都包含很多動(dòng)物(每個(gè)動(dòng)物只能屬于一個(gè)動(dòng)物園),顧員(他們可以在多個(gè)動(dòng)物園工作),并且需要跟蹤每個(gè)動(dòng)物的詳細信息,那么這些API的端點(diǎn)可能如下所示:[逍遙子筆記:下列URL中紅色加粗的后綴就是端點(diǎn)]

 

 

在介紹這些端點(diǎn)的作用時(shí),你需要給出這些端點(diǎn)以及操作它們的HTTP動(dòng)作。例如下面給出的是剛才所構建動(dòng)物園API列表的功能,注意,我在每個(gè)端點(diǎn)前面都加上了HTTP動(dòng)作,就像HTTP請求中所使用的那樣。

 

  •   GET    /zoos:列出所有的動(dòng)物園(包括動(dòng)物園的ID、名稱(chēng)以及簡(jiǎn)介);
  •   POST   /zoos: 創(chuàng )建一個(gè)新的動(dòng)物園;
  •   GET    /zoos/ZID:獲取一個(gè)完整的動(dòng)物園對象;[逍遙子筆記:這里的動(dòng)物園對象僅僅指“動(dòng)物園”,例如“動(dòng)物園”的ID、名稱(chēng)、介紹等信息,而不包含該動(dòng)物園中的動(dòng)物、雇員等下轄類(lèi)型的信息]
  •   PUT    /zoos/ZID:更新一個(gè)動(dòng)物對象(包含全部信息);
  •   PATCH  /zoos/ZID:更新一個(gè)動(dòng)物對象(包含部分信息);
  •   DELETE /zoos/ZID:          刪除一個(gè)動(dòng)物園對象;
  •   GET    /zoos/ZID/animals:獲取指定動(dòng)物園的全部動(dòng)物信息(包括動(dòng)物的ID和名稱(chēng));
  •   GET    /animals:是指列出所有動(dòng)物信息;
  •   POST  /animals: 創(chuàng )建一個(gè)新的動(dòng)物;
  •   GET   /animals/AID: 獲取某個(gè)動(dòng)物的對象信息;
  •   PUT   /animals/AID:更新一個(gè)動(dòng)物的對象信息(提供對象的全部?jì)热荩?/li>
  •   PATCH  /animals/AID:更新一個(gè)動(dòng)物的對象信息(提供對象的部分內容);
  •   GET    /animal_types: 獲取所有的動(dòng)物類(lèi)型信息;
  •   GET    /animal_types/ATID: 獲取指定動(dòng)物類(lèi)型的類(lèi)型描述信息;
  •   GET    /employees:獲取所有的雇員列表;
  •   GET    /employees/EID:獲取一個(gè)指定雇員的信息;
  •   GET    /zoos/ZID/employees:獲取指定動(dòng)物園的全部雇員列表;
  •   POST   /employees:創(chuàng )建一個(gè)新雇員;
  •   POST   /zoos/ZID/employees:為指定動(dòng)物園增加一個(gè)雇員;
  •   DELETE /zoos/ZID/employees/EID:解雇指定動(dòng)物園的某個(gè)雇員;

 

上述列表中,ZID表示動(dòng)物園的ID,AID表示動(dòng)物ID,EID表示雇員ID,ATID表示動(dòng)物類(lèi)型ID,在文檔中給出關(guān)鍵詞及含義是一個(gè)非常好的習慣。

在上面的例子中我已簡(jiǎn)要列出常見(jiàn)API的URL前綴,這種簡(jiǎn)化方式(省略URL前綴)非常有利于溝通,但是在你的API文檔當中,還是要使用全部的URL(例如:GET https://api.example.com/vi/animal_type/ATID)。[逍遙子筆記:在非正式文檔中介紹一個(gè)API時(shí)可以采用端點(diǎn)代替完成URL這種方法:HTTP動(dòng)作+端點(diǎn)+該端點(diǎn)的功能說(shuō)明,端點(diǎn)要比完整URL短的多,這樣更容易表述,也不影響理解,但是在正式文檔中還是要把URL寫(xiě)全]

這里需要注意數據之間關(guān)系的展示,尤其是雇員和動(dòng)物園之間的多對多的關(guān)系。你可以通過(guò)增加URL的方式來(lái)表示更多的數據關(guān)系[逍遙子筆記:根據RoyThomas Fielding對資源的解釋?zhuān)P(guān)系也是一種資源,因此,在遇到多對多的數據關(guān)系時(shí),可以將數據關(guān)系進(jìn)行拆分,并為每個(gè)關(guān)系都增加一個(gè)URL]。當然,這里并沒(méi)有一個(gè)HTTP操作能表示解除雇員,但是我們可以通過(guò)刪除指定動(dòng)物園的雇員的方式來(lái)達到同樣的效果。[逍遙子筆記:這是對上面“DELETE/zoos/ZID/employees/EID:解雇指定動(dòng)物園的某個(gè)雇員”這個(gè)條目的解釋]

過(guò)濾器

當用戶(hù)請求獲取一組對象列表時(shí),你就需要對結果進(jìn)行過(guò)濾并返回一組嚴格符合用戶(hù)要求的對象。有時(shí)返回結果的數量可能非常大,但是你也不能隨意對此進(jìn)行約束,因為這種服務(wù)端的隨意約束會(huì )造成第三方開(kāi)發(fā)人員的困惑。如果用戶(hù)請求了一個(gè)集合,并對返回結果進(jìn)行遍歷,然后只要前100個(gè)對象,那么這里就需要由用戶(hù)來(lái)指明這個(gè)限制量。這樣用戶(hù)就不會(huì )有這樣的疑惑:是他們程序的bug還是接口限制了100條?還是網(wǎng)絡(luò )只允許傳這么大的包?[逍遙子筆記:在IM項目中有個(gè)接口讓用戶(hù)拉取自己的歷史消息,我們就需要在接口中增加一個(gè)參數讓用戶(hù)來(lái)確定本次要拉取多少條歷史消息,服務(wù)器端根據用戶(hù)傳入的限制量來(lái)確定返回消息的條數,而不是由服務(wù)器來(lái)在實(shí)現時(shí)就確定該接口一次調用只能返回幾條]

盡量減少對第三方開(kāi)發(fā)人員的隨意約束。[逍遙子筆記:不要在接口中添加默認的約束條件]

非常重要的一點(diǎn):讓第三方開(kāi)發(fā)人員自己指定排序過(guò)濾器/返回結果集的約束條件。這么做的最重要原因是:用戶(hù)能用盡量少的網(wǎng)絡(luò )消耗盡快獲取到結果;第二個(gè)重要原因是:用戶(hù)可能很懶,想讓服務(wù)端幫他們做好分頁(yè)和過(guò)濾;還有一個(gè)對客戶(hù)端不那么重要,但是對服務(wù)端很重要的原因:這么做會(huì )降低請求的資源負載。

過(guò)濾器通常用于過(guò)濾GET請求返回的資源集合,在GET請求中,可以通過(guò)URL傳遞過(guò)濾器信息。你可以放心把下面例子中列出的過(guò)濾器類(lèi)型應用到自己的API中:

 

  •   ?limit=10:限制返回給用戶(hù)的結果集的數量(通常用于分頁(yè));
  •   ?offset=10:給用戶(hù)返回一個(gè)結果集(通常用于分頁(yè));[逍遙子筆記:指定偏移量,從指定位置開(kāi)始返回結果集,與limit結合使用就可以達到分頁(yè)效果,第一次從開(kāi)始獲取指定數量的結果,后續都要從上次結果之后開(kāi)始返回]
  •   ?animal_type_id=1:返回符合條件的結果集(類(lèi)似于數據庫的WHERE查詢(xún)條件:WHERE animal_type_id=1);
  •   ?sortby=name&order=asc:將結果集按照指定屬性和指定排序方式進(jìn)行排序(類(lèi)似于數據的ORDER BY name ASC);

 

上述部分過(guò)濾器與前面介紹的某些URL端點(diǎn)功能重復,例如前面提到的URL:GET /zoo/ZID/animals在功能上就與使用過(guò)濾器的GET /animals?zoo_id=ZID重復。功能單一的端點(diǎn)對于第三方開(kāi)發(fā)人員來(lái)說(shuō)更容易使用,尤其是他們使用你提供的請求做一些復雜的開(kāi)發(fā)時(shí),更是如此。在A(yíng)PI文檔中明確寫(xiě)出這些功能重復的請求方式,將會(huì )消除第三方開(kāi)發(fā)人員對這些重復功能的困惑,否則他們就會(huì )懷疑這些重復功能之間是否有差異!

還有一點(diǎn),當需要對數據進(jìn)行過(guò)濾或者排序時(shí),你要給第三方開(kāi)發(fā)人員(Consumer)列出哪些屬性能用于過(guò)濾或排序,我們不希望把任何數據庫操作的錯誤返回給用戶(hù)。[逍遙子筆記:不要把服務(wù)內部的錯誤或者問(wèn)題暴露給第三方開(kāi)發(fā)人員]

狀態(tài)碼

充分利用適當的狀態(tài)碼對于設計REST 風(fēng)格的API來(lái)說(shuō)非常重要,因為HTTP狀態(tài)碼已有標準定義,并且各種網(wǎng)絡(luò )設備都能讀取并識別這些它們。例如,通過(guò)配置負載均衡器的參數來(lái)避免將請求發(fā)往出現50X錯誤的服務(wù)程序[逍遙子筆記:50X表示服務(wù)程序內部出錯]。這里將列出一些可供你選擇使用的HTTP狀態(tài)碼,它們可以成為你設計良好返回碼的出發(fā)點(diǎn):

 

  •   200 OK – [GET]

 

    客戶(hù)端向服務(wù)器請求數據時(shí),服務(wù)器找到這些數據并將之返回給客戶(hù)端(此行為冪等);[逍遙子筆記:GET操作只能獲取數據(即只讀),不應該對服務(wù)器的數據進(jìn)行任何形式的修改]

 

  •   201 CREATED – [POST/PUT/PATCH]

 

    客戶(hù)端向服務(wù)器發(fā)送數據,服務(wù)器為這些數據創(chuàng )建一個(gè)資源;

 

  •   204 NO CONTENT – [DELETE]

 

    客戶(hù)端請求服務(wù)器刪除一個(gè)資源時(shí),服務(wù)器將該資源刪除;[逍遙子筆記:返回碼204表示執行成功了,但是沒(méi)有數據。HTTP 的RFC2616中對于204返回碼的描述為:如果客戶(hù)端是個(gè)代理(例如瀏覽器),它不應該改變“觸發(fā)該請求的”頁(yè)面展示,該返回值主要用于輸入行為發(fā)生時(shí),雖然新的或更新過(guò)的元數據信息被應用于當前頁(yè)面,但代理(瀏覽器)不能改變當前的頁(yè)面展示,原文為:

If the client is a user agent, itSHOULD NOT change its document view from that which caused the request to besent. This response is primarily intended to allow input for actions to takeplace without causing a change to the user agent’s active document view,although any new or updated metainformation SHOULD be applied to the documentcurrently in the user agent’s active view.]

 

  •   400 INVALID REQUEST – [POST/PUT/PATCH]

 

    客戶(hù)端給服務(wù)器發(fā)送了一個(gè)無(wú)效的請求,服務(wù)器對此不作任何動(dòng)作(此行為冪等)。

 

  •   404 NOT FOUND – [*]

 

    客戶(hù)端請求了一個(gè)不存在的資源或資源集合,服務(wù)端對此不作任何動(dòng)作(此行為冪等)。

 

  •   500 INTERNAL SERVER ERROR – [*]

 

    服務(wù)器內部發(fā)生了錯誤,客戶(hù)端無(wú)法知道請求是否被執行成功了。

狀態(tài)碼范圍

1XX的返回碼預留給HTTP的底層使用,在你的整個(gè)職業(yè)生涯中都不會(huì )主動(dòng)發(fā)送這種返回碼;

2XX的返回碼表示請求按照預期執行并成功返回了信息。服務(wù)端要盡可能給用戶(hù)返回這種結果。

3XX的返回碼表示請求重定向,大多數API都不會(huì )經(jīng)常使用這種請求(),但是最新的超媒體API會(huì )充分使用這些功能。

4XX的返回碼主要表示由客戶(hù)端引起的錯誤,例如請求參數錯誤或者訪(fǎng)問(wèn)一個(gè)不存在的資源,這些必須為冪等操作,并且不能改變服務(wù)器的狀態(tài)[逍遙子筆記:其實(shí)服務(wù)器的狀態(tài)發(fā)生了改變就意味著(zhù)操作不是冪等了]。

5XX的返回碼主要表示由服務(wù)器引起的錯誤,通常情況下,這些錯誤都是開(kāi)發(fā)人員([逍遙子筆記:這里應該是服務(wù)器程序的開(kāi)發(fā)人員])接觸不到的底層函數拋出來(lái),然后傳遞給用戶(hù)([逍遙子筆記:這里應該是第三方開(kāi)發(fā)人員])的。用戶(hù)在收到5XX的返回碼時(shí),他們不知道服務(wù)器當前的工作狀態(tài)是否正常,因此,要盡量避免這種情況發(fā)生。

返回值文檔

當第三方開(kāi)發(fā)人員在發(fā)送HTTP請求時(shí),他們需要事先了解這些請求的返回值信息,下述列表就是一些REST風(fēng)格API以及它們對應的返回值信息:[逍遙子筆記:與前面的介紹URL的功能類(lèi)似,只是這里將最后面的URL描述換成返回值描述,這里依然采用三段式描述法:HTTP請求動(dòng)作+端點(diǎn)+端點(diǎn)對應的返回值描述信息]

 

  •   GET /collection:返回一個(gè)資源對象的列表;
  •   GET /collection/resource: 返回一個(gè)資源對象;
  •   POST /collection:返回新創(chuàng )建的資源對象
  •   PUT /collection/resource:返回一個(gè)完整的資源對象;
  •   PATCH /collection/resource:返回一個(gè)完整的資源對象;[逍遙子筆記:雖然請求中只帶了部分資源對象的內容,但是返回的內容卻是整個(gè)資源對象]
  •   DELETE /collection/resource:返回一個(gè)空文檔;

 

需要注意的是:當用戶(hù)創(chuàng )建一個(gè)資源時(shí),他們通常并不想知道新創(chuàng )建資源的ID(也不想知道其他屬性,例如修改或創(chuàng )建的時(shí)間戳)[逍遙子筆記:這一點(diǎn)略有疑惑,這種設計思路應該也是區分場(chǎng)合的,如果資源很復雜,本文介紹的這種思路或許可行,如果資源原本就很簡(jiǎn)單,例如我們以前設計的發(fā)送消息接口,就直接給用戶(hù)返回所發(fā)送消息的ID]。這些新增的屬性信息可通過(guò)后續請求獲得,當然也可以通過(guò)初始化POST請求來(lái)返回。

授權

多數情況下,服務(wù)器想確切知道每個(gè)請求的發(fā)起方是誰(shuí)?當然,部分API接口能放開(kāi)被用匿名訪(fǎng)問(wèn),但通常接口只能被授權的用戶(hù)訪(fǎng)問(wèn)。

OAuth2.0為此提供了一個(gè)很好的實(shí)現途徑。你能知道每個(gè)請求是由哪個(gè)客戶(hù)端發(fā)起?這些請求背后分別代表了哪些用戶(hù)?以及提供一種標準化的用戶(hù)訪(fǎng)問(wèn)或撤銷(xiāo)訪(fǎng)問(wèn)方式,所有這些都無(wú)需第三方用戶(hù)的登錄授信。

還有OAuth1.0和xAuth也能完成類(lèi)似功能。無(wú)論采用那種方法,一定要確保通用性以和良好的文檔設計,在文檔中對用戶(hù)常用語(yǔ)言/平臺的各種不同封裝庫進(jìn)行詳細說(shuō)明。[逍遙子筆記:這些服務(wù)以庫的方式供客戶(hù)端調用,例如SDK,因此在文檔中要對各種形式的封裝庫進(jìn)行詳細說(shuō)明]

我可以如實(shí)地告訴你,盡管OAuth1.0a雖然是最安全的選項,但是它非常難以部署。我遇到很多第三方開(kāi)發(fā)人員抱怨他們不得不實(shí)現自己的庫,因為OAuth1.0a沒(méi)有他們所使用語(yǔ)言對應的庫。我花費了大量的時(shí)間用于解決那些難以理解的“invalid signature”錯誤。因此,我建議你使用其他的替代方案。

內容類(lèi)型

目前,大多數REST風(fēng)格API接口都提供JSON格式的數據,你所能想起來(lái)的Facebook、Twitter、GitHub都是如此。XML方式已經(jīng)逐漸退出人們的視野(除了一些大公司內部還在使用之外),幸虧SOAP方式已經(jīng)消失,我們已經(jīng)看不到返回HTML格式數據的API接口了。

開(kāi)發(fā)者常用的開(kāi)發(fā)語(yǔ)言或框架都能輕易解析你返回的各種有效數據。如果你正在使用不同的序列化器構建一個(gè)通用的返回對象,你可以使用前面提到的任意數據格式(SOAP除外),不過(guò)在返回數據時(shí)需要注意處理請求首部的Accept字段。[逍遙子筆記:HTTP請求頭部的Accept可用于指定返回數據的格式]

一些API開(kāi)發(fā)人員建議針對不同返回內容的類(lèi)型,為URL(在端點(diǎn)之后)添加擴展字段,例如:.json,.xml,或者.html,但我不建議這么做,我建議使用HTTP請求首部的Accept字段(HTTP的RFC文檔中有對Accept的解釋?zhuān)?,并且覺(jué)得這才是合適的方法。

超媒體API

超媒體API可能代表REST風(fēng)格API的未來(lái)發(fā)展,它們在思想上更符合HTTP和HTML的設計初衷。[逍遙子筆記:根據REST作者Roy Thomas Fielding的描述,REST核心是面向資源的設計,超媒體服務(wù)所提供了各種多媒體資源的訪(fǎng)問(wèn),它在本質(zhì)上符合了以資源為中心的設計]

在使用非超媒體的REST風(fēng)格API時(shí),URL端點(diǎn)也是客戶(hù)端和服務(wù)器之間契約的一部分,這些端點(diǎn)必須事先告知客戶(hù)端,一旦改變它們,客戶(hù)端就無(wú)法按預期與服務(wù)器進(jìn)行交互,這其實(shí)也是一種約束。

現在,API的用戶(hù)不僅僅是能發(fā)起HTTP請求的用戶(hù)代理,人們更常用瀏覽器發(fā)起HTTP請求。然而,用戶(hù)不會(huì )被這些預先定義的、REST風(fēng)格API的URL端點(diǎn)所約束。是什么讓用戶(hù)變得如此特殊呢?現在的網(wǎng)頁(yè)能讓用戶(hù)先讀主題,然后點(diǎn)擊他們感興趣的主題所對應的鏈接,訪(fǎng)問(wèn)他們想訪(fǎng)問(wèn)的網(wǎng)站或者想閱讀的內容,此時(shí)URL發(fā)生變化的時(shí)候,用戶(hù)不受影響(除非用戶(hù)為某個(gè)網(wǎng)頁(yè)打了標簽,在他們訪(fǎng)問(wèn)這些打了標簽的網(wǎng)頁(yè)時(shí)會(huì )自動(dòng)跳轉到主頁(yè),用戶(hù)需要再從主頁(yè)中尋找他們所感興趣數據的新路徑)。[逍遙子筆記:我們的網(wǎng)站通常采用這種方式,尤其是各種門(mén)戶(hù)網(wǎng)站,例如網(wǎng)易:www.163.com,新浪:www.sina.com,打開(kāi)這些門(mén)戶(hù)網(wǎng)站,我們看不到一個(gè)URL,我們所看到的都是一個(gè)個(gè)的主題,每個(gè)主題對應一個(gè)超鏈接(URL),當這些主題對應的URL發(fā)生變化時(shí),只需要調整主題和超鏈接(URL)的映射關(guān)系即可,用戶(hù)實(shí)際上看不到這些URL的變化]

超媒體API概念和一個(gè)普通人的行為類(lèi)似。請求API的根目錄將會(huì )獲得一個(gè)URL列表,這些URL列表的每一項都可能對應了一個(gè)信息集,并且它以用戶(hù)能夠理解的方式來(lái)描述這些信息集合。無(wú)需為每個(gè)資源提供ID(除非特別邀請),因為一個(gè)URL就唯一標識了一個(gè)資源。

超媒體API用戶(hù)在訪(fǎng)問(wèn)連接并且收集信息時(shí),返回結果中將被放入最近更新的URL鏈接,因此URL無(wú)需事先與用戶(hù)約定。如果URL被緩存了,后續請求又返回了404[逍遙子筆記:404表示請求了一個(gè)不存在的資源],用戶(hù)只需簡(jiǎn)單地回到根目錄重新尋找內容即可。

當從集合中檢索一個(gè)資源列表時(shí),要給用戶(hù)返回這個(gè)資源列表的完整URL。當執行POST/PATCH/PUT請求時(shí),可用返回碼為3XX的響應來(lái)重定向到新的資源。

JSON即無(wú)法給我們提供需要的語(yǔ)義來(lái)指明哪些屬性是URL,也不能說(shuō)明URL怎樣與當前的文檔關(guān)聯(lián)起來(lái);可能正如你猜測的那樣,HTML可以提供這樣的信息。我們可以先通過(guò)API拿到數據,然后再進(jìn)行HTML處理。想想CSS陪伴我們走過(guò)的這些路,我們可能有一天會(huì )看到:在獲取同樣URL和內容的時(shí)候,無(wú)論通過(guò)API請求還是網(wǎng)站訪(fǎng)問(wèn),都采用同一種處理方式。[逍遙子筆記:JSON提供數據內容,并未提供數據展示功能]

文檔

老實(shí)說(shuō),如果沒(méi)有完全按照本文檔的指導,你的API也不一定會(huì )太差,然而,如果你沒(méi)有為API編寫(xiě)合適的文檔,沒(méi)有人會(huì )愿意用它,它將變?yōu)橐粋€(gè)極難使用的API。

確保你的文檔無(wú)需授權便可被開(kāi)發(fā)人員訪(fǎng)問(wèn)。

不要使用自動(dòng)文檔生成器,如果用了,就一定要仔細檢查和修改生成的文檔,確保它們能夠被用戶(hù)理解和使用。

文檔中所舉例子中的請求和響應包體要寫(xiě)全,不要截斷不重要的部分,而是用高亮方式展示重要的部分。

文檔中要寫(xiě)明各URL端點(diǎn)的預期返回碼和可能的出錯信息,以及出現這些錯誤信息的可能原因是什么?

如果時(shí)間充足,你還可以構建一個(gè)第三方開(kāi)發(fā)人員使用的API控制臺,以便他們可以立即對你的API進(jìn)行驗證。這個(gè)事情做起來(lái)不會(huì )像你想象的那么難,但是開(kāi)發(fā)人員(包括內部開(kāi)發(fā)人員和第三方開(kāi)發(fā)人員)卻可能因為這個(gè)功能而喜歡上使用你的API。

確保文檔能被打印,例如,CSS就是一種強大的文檔展示方式;在文檔打印的時(shí)候一定要隱藏文檔的工具欄,即便沒(méi)有人把你的文檔用打印機打印出來(lái),也會(huì )有很多開(kāi)發(fā)人員喜歡把它們輸出為PDF以便離線(xiàn)查看。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
RESTful API 設計最佳實(shí)踐
好 RESTful API 的設計原則
##RESTful API 最佳實(shí)踐
22條API設計的最佳實(shí)踐
RESTful API 設計指南
API 接口規范
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久