restful api 設(shè)計(jì)原則

目錄

  1. 定義(Definitions)
  2. 數(shù)據(jù)的設(shè)計(jì)與抽象化(Data Design and Abstraction)
  3. HTTP動(dòng)詞 (Verbs)
  4. 版本(Versioning)
  5. 分析 (Analytics)
  6. API根路徑 (API Root URL)
  7. 路徑 (Endpoint)
  8. 信息過濾 (Filtering)
  9. 狀態(tài)碼 (Status Codes)
  10. 文檔返回值 (Expected Return Documents)
  11. 身份認(rèn)證 (Authentication)
  12. 內(nèi)容形式 (Content Type)
  13. 超媒體 (Hypermedia APIs)
  14. 文檔 (Documentation)
  15. 其它:HTTP包文

引言

眾所周知腔寡,優(yōu)秀的API設(shè)計(jì)是相當(dāng)困難的膀斋!API建立起服務(wù)器和那些希望調(diào)用數(shù)據(jù)的客戶之間的聯(lián)系。打破了這個(gè)約定會(huì)導(dǎo)致開發(fā)者收到大量的報(bào)怨郵件氓辣,大量的客戶因此要修改他們不能繼續(xù)使用的APP欢际。當(dāng)然API文檔可以有效降低這些問題,但是大多數(shù)程序員都不愛寫文檔战得。

建立起API機(jī)制是提高你的服務(wù)的重要途徑之一控嗜。通過建立API,你的服務(wù)器/請(qǐng)求中心會(huì)變成其它請(qǐng)求服務(wù)的一個(gè)平臺(tái)蒜茴⌒亲Γ看看那些擁有大數(shù)據(jù)的公司:Facebook,Twitter粉私,谷歌顽腾,GitHub,亞馬遜毡鉴,Netfilx崔泵,無一不是因?yàn)樗麄冮_放了數(shù)據(jù)中心的API,使得他們變得很強(qiáng)大猪瞬。事實(shí)上憎瘸,這個(gè)產(chǎn)業(yè)生存的最重要的原因就是那些平臺(tái)所提供的消費(fèi)數(shù)據(jù)。

越早建立起你的API陈瘦,越多的人們會(huì)使用你的服務(wù)幌甘。

在你設(shè)計(jì)API時(shí),及時(shí)的更新文檔痊项,這些文檔的設(shè)計(jì)的目的是為了確保調(diào)用你API的客戶能更容易的理解锅风,這樣你可以大幅的減少收到關(guān)于困惑或是抱怨的郵件。我將會(huì)整理設(shè)計(jì)原則方面的篇章鞍泉,你可以根據(jù)你的需要讀其中的一段或幾段皱埠。

1. 定義 (Definitions)

以下是一些我會(huì)在這篇文章中用到的名詞:

  • 資源(Resource): 一個(gè)對(duì)象的記錄。如:一個(gè)動(dòng)物咖驮。
  • 集合(Collection): 很多對(duì)象的集合边器。如:很多動(dòng)物训枢。
  • HTTP: 互聯(lián)網(wǎng)交互的協(xié)議。
  • 客戶(Consumer): 通過電腦會(huì)做出HTTP請(qǐng)求的客戶忘巧。
  • 第三方開發(fā)人員(Third Party Developer): 需要獲取服務(wù)器數(shù)據(jù)的第三方開發(fā)人員恒界。
  • 服務(wù)器(Server): 一個(gè)可以處理客戶請(qǐng)求的HTTP的服務(wù)或應(yīng)用。
  • 路徑(Endpoint): 一個(gè)服務(wù)器API的路徑砚嘴,代表了一個(gè)資源或一個(gè)集合十酣。
2. 數(shù)據(jù)的設(shè)計(jì)與抽象化 (Data Design and Abstraction)

設(shè)計(jì)API比你想象的要簡(jiǎn)單。首先你需要考慮如何設(shè)計(jì)你的數(shù)據(jù)以及你的服務(wù)哭/請(qǐng)求中心將如何工作际长。如果你在開始寫程序的時(shí)候就應(yīng)該考慮API的設(shè)計(jì)耸采,這樣會(huì)使得一切變得簡(jiǎn)單起來。但是如果你想要在已經(jīng)完成的程序中添加API也颤,你可能需要提供更多的抽象化服務(wù)洋幻。

這里郁轻,我們臨時(shí)將一個(gè)集合(Collection)看做是一個(gè)數(shù)據(jù)庫表翅娶,資源(Resource)看作是數(shù)據(jù)表中的一條記錄。當(dāng)然這是一個(gè)特殊的例子好唯,事實(shí)上竭沫,你的API必須將你的數(shù)據(jù)和業(yè)務(wù)邏輯盡可能的剝離開來。這點(diǎn)是非常重要的骑篙,這樣可以消除第三方調(diào)用API的開發(fā)者的困惑蜕提,否則導(dǎo)致的結(jié)果就是他們不想使用你的API。

當(dāng)然靶端,有些重要的服務(wù)是不能通過API暴露給第三方用戶的谎势,一個(gè)簡(jiǎn)單的例子就是很多API不允許第三方使用者調(diào)用API來新增用戶。

3. HTTP動(dòng)詞 (Verbs)

毫無疑問杨名,你肯定知道GET和POST請(qǐng)求脏榆。它們是瀏覽器中最常用的請(qǐng)求類型。POST請(qǐng)求非常流行以致于都快成了日常用語台谍。很多對(duì)互聯(lián)網(wǎng)的原理一無所知的人們卻可能知道他們可以通過Facebook的友好請(qǐng)求须喂,‘POST‘一些信息上去。

有關(guān)于HTTP的動(dòng)作趁蕊,你需要掌握四個(gè)半坞生。其中的半個(gè)是因?yàn)椤甈ATCH‘ 和’PUT‘這個(gè)動(dòng)作很像。對(duì)于API開發(fā)者來說掷伙,其它四個(gè)HTTP動(dòng)作都是有兩兩聯(lián)系的是己。下面是具體的作動(dòng),以及解釋(在這里我假設(shè)大部分的讀者都懂得數(shù)據(jù)庫方面的知識(shí))任柜。

  • GET(select):從服務(wù)器中取出資源卒废。(一個(gè)或是多個(gè))
  • POST(create):在服務(wù)器上新增一個(gè)資源寒波。
  • PUT(update):在服務(wù)器上修改資源(需要提供整個(gè)資源信息)。
  • PATCH(update):在服務(wù)器上修改資源(只需要提供待修改的資源信息)升熊。
  • Delete(delete):從服務(wù)器上刪除資源俄烁。

以下是兩個(gè)比較少用到的HTTP動(dòng)作:
HEAD:從服務(wù)器上取回單個(gè)元數(shù)據(jù)的資源,例如數(shù)據(jù)的哈希值或數(shù)據(jù)的最后更新時(shí)間等级野。
OPTIONS:從服務(wù)器上取回客戶允許得到的資源信息页屠。

一個(gè)好的RESTful API會(huì)使用以上“四個(gè)半”動(dòng)作來供第三方使用者獲得或上傳數(shù)據(jù)。并且URL不會(huì)包含任何的ACTION或是其它的動(dòng)作蓖柔。

瀏覽器通常會(huì)緩存GET請(qǐng)求(大多數(shù)如此3狡蟆),例如一個(gè)被緩存了的GET請(qǐng)求(需要看緩存的HEADERS)要比POST請(qǐng)求快一些况鸣。一個(gè)HEAD請(qǐng)求一般是沒有回應(yīng)BODY的GET請(qǐng)求牢贸,當(dāng)然也能被緩存。

4. 版本(Versioning)

無論你建立的是怎樣的服務(wù)镐捧,在開始寫程序前做了大量的設(shè)計(jì)潜索,只要你的服務(wù)器代碼有變動(dòng),那么你的數(shù)據(jù)關(guān)系就可能發(fā)生變化懂酱,比如你的數(shù)據(jù)資源可能會(huì)新增或刪除一些屬性竹习。這是開發(fā)必不可少的工作,尤其是你的程序已經(jīng)上線并且被很多人所使用列牺。

請(qǐng)記住API是服務(wù)提供方和客戶之間的聯(lián)系整陌。如果你需要改變你的服務(wù)器API,這將會(huì)破壞兼容性問題瞎领。如果你要破壞原有的API泌辫,你的客戶將會(huì)痛恨你。如果你持續(xù)的修改你的API九默,你將會(huì)失去很多客戶震放。所以需要你確保你的應(yīng)用是逐步的更新,這樣才會(huì)使得調(diào)用你的API的客戶滿意荤西。你需要建立API的版本并且在有需要的時(shí)候介紹新的版本給客戶澜搅,并且保持老的版本可持續(xù)訪問。

另外一個(gè)建議是如果你的API只是簡(jiǎn)單的新增一些特性邪锌,例如在你的資源中新增一些屬性(這些屬性不是必填項(xiàng)勉躺,資源沒有這些屬性也能照常運(yùn)行),或者你新增一些新的路徑(Endpoints)觅丰,這個(gè)時(shí)候你不必更新你的API版本號(hào)饵溅,因?yàn)槟闼龅倪@些改變并不會(huì)打破現(xiàn)有的兼容性。當(dāng)然你需要更新你的API文檔妇萄。

過段時(shí)間后蜕企,你可以不建議使用你的API的舊版本咬荷。不過不建議使用并不意味著關(guān)閉它或降低那個(gè)版本的質(zhì)量,而只是告訴客戶舊版本將會(huì)在未來的某一天不能使用轻掩,需要他們盡快更新到最新的版本幸乒。

好的RESTful API會(huì)在URL上顯示版本號(hào)。最常見的解決辦法就是把版本號(hào)放在請(qǐng)求的頭部中唇牧。但經(jīng)過我跟很多不同的開發(fā)人員的討論罕扎,得出的結(jié)論是將版本號(hào)放在HTTP頭信息中不如放在URL上來的方便和直觀。例:將API的版本號(hào)放入U(xiǎn)RL: https://api.example.com/v1/

5. 分析 (Analytics)

優(yōu)秀的程序會(huì)經(jīng)常追蹤客戶調(diào)用你的API的版本/路徑丐重。這個(gè)可以在你的數(shù)據(jù)庫中用整數(shù)型字段統(tǒng)計(jì)下腔召,當(dāng)每次請(qǐng)求過來的時(shí)候,就增加一次扮惦。這樣做有很多優(yōu)點(diǎn)臀蛛,最常見的好處是我們就可以知道哪個(gè)API請(qǐng)求是最高效的。

為了創(chuàng)建第三方開發(fā)人員喜歡的API崖蜜,最重要的事情是當(dāng)你不贊成使用舊的API版本時(shí)浊仆,你需要聯(lián)系那些還在使用舊版本的開發(fā)人員。這可能是你升級(jí)并徹底放棄一個(gè)API舊版本最好的方法纳猪。

通知第三方開發(fā)人員可以是自動(dòng)的氧卧,例如當(dāng)超過10桃笙,000的不贊成使用的請(qǐng)求被調(diào)用時(shí)氏堤,就可以自動(dòng)發(fā)郵件給那些開發(fā)人員。

6. API根路徑 (API Root URL)

你的API根路徑(域名)的設(shè)計(jì)非常重要搏明。當(dāng)一個(gè)開發(fā)人員(可看作是作古派風(fēng)格的開發(fā)者)在一個(gè)很老的程序上使用你的API的新的特性時(shí)鼠锈,他們可能不知道你服務(wù)器,也許他們可能只是知道一系列的后綴請(qǐng)求的URL星著。所以盡量簡(jiǎn)化你的API根路徑购笆,因?yàn)橐粋€(gè)復(fù)雜的URL會(huì)使得一些開發(fā)人員放棄你的API。

以下是兩個(gè)常見的根路徑URL:

如果你的應(yīng)用很大或是你預(yù)期你的應(yīng)用會(huì)很大虚循,那么把你的API放到單獨(dú)的子域里是個(gè)很不錯(cuò)的選擇同欠,這樣可以使得你的API更加的靈活容易維護(hù)。例如:https://api.example.com/v1/*

如果你覺得你的API不是很復(fù)雜横缔,或者是你只想要個(gè)小應(yīng)用程序(比如你希望你的網(wǎng)站和API放在同一個(gè)框架下)铺遂,那么就把你的API放在根域名的URL后面。例如:https://example.org/api/v1/*

有個(gè)可以存放API路徑列表的頁面是個(gè)很好的主意茎刚。比如點(diǎn)擊GitHub的API的根路徑就可以得到一個(gè)路徑列表襟锐。就我個(gè)人而言,我是非常喜歡這種點(diǎn)擊根路徑就得到所有API URL或者得到API的開發(fā)文檔的形式膛锭,這樣有助于開發(fā)者的開發(fā)粮坞。

另外蚊荣,作為好的RESTful API, API與用戶的通信協(xié)議,總是使用HTTPs協(xié)議莫杈。

7. 路徑 (Endpoint)

路徑就是你API的URL互例,它指出了資源的詳情或是一堆資源的集合。

舉例說明:
如果你想要建立一個(gè)虛構(gòu)的API來代表不同的動(dòng)物園筝闹,每個(gè)動(dòng)物園包含很多動(dòng)物(每個(gè)動(dòng)物只屬于一個(gè)動(dòng)物園)敲霍,員工(可以在多個(gè)動(dòng)物園里工作)照顧每個(gè)動(dòng)物,那么你建的路徑如下:

關(guān)于每個(gè)路徑的作用丁存,你需要列舉出一些HTTP動(dòng)作的路徑肩杈。以下列舉了一些可行的動(dòng)作來代表一個(gè)可以運(yùn)作的API,值得注意的是我已經(jīng)把每個(gè)HTTP動(dòng)作放到了路徑前解寝,并寫上了一些注釋扩然。

  • GET /zoos: 列出所有的動(dòng)物園(返回ID和名稱,沒有其它更詳細(xì)的資料聋伦。)
  • POST /zoos: 新建一個(gè)動(dòng)物園
  • GET /zoos/ZID: 根據(jù)ZID取出一整個(gè)動(dòng)物園的對(duì)象
  • PUT /zoos/ZID: 更新一個(gè)動(dòng)物園(傳入全部屬性以及ZID)
  • PATCH /zoos/ZID: 更新一個(gè)動(dòng)物園(傳入要更新的屬性以及ZID)
  • DELETE /zoos/ZID: 刪除一個(gè)動(dòng)物園
  • GET /zoos/ZID/animals: 根據(jù)ZID取出動(dòng)物的列表(返回動(dòng)物的ID和名稱)
  • GET /animals: 列舉出所有的動(dòng)物夫偶。(返回動(dòng)物ID和名稱)
  • POST /animals: 新建一個(gè)動(dòng)物。
  • GET /animals/AID: 根據(jù)動(dòng)物的ID取出相應(yīng)的動(dòng)物的對(duì)象觉增。
  • PUT /animals/AID: 新增一個(gè)動(dòng)物(傳入全部屬性以及AID)
  • PATCH /animals/AID: 新增一個(gè)動(dòng)物(傳入要更新的屬性以及AID)
  • GET /animal_types: 根據(jù)傳入的動(dòng)物園類型獲取動(dòng)物園的列表(返回動(dòng)物園ID和名稱)
  • GET /animal_types/ATID: 根據(jù)傳入的動(dòng)物園類型ID獲取一個(gè)動(dòng)物園的信息
  • GET /employees: 獲取所有的員工列表
  • GET /employees/EID: 根據(jù)員工的ID獲取員工信息
  • GET /zoos/ZID/employees: 獲取在指定動(dòng)物園里工作的員工列表(返回員工ID和姓名)
  • POST /employees: 新增一個(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)物類型ID嘹履。在你的文檔中標(biāo)明是簡(jiǎn)寫意思一個(gè)很好的習(xí)慣腻扇。

我簡(jiǎn)化了以上這些常用的API URL前綴。這個(gè)形式有利于開發(fā)時(shí)的交流砾嫉,當(dāng)然在你正式的API文檔中幼苛,你需要補(bǔ)齊全部URL的路徑。(例如:GET http://api.example.com/v1/animal_type/ATID).

值得注意的是關(guān)于員工和動(dòng)物園的數(shù)據(jù)間焕刮,可以有很多不同的展示及聯(lián)系舶沿,下面我會(huì)列舉一個(gè)URL,來說明下它們之間特殊的相互影響配并。比如當(dāng)我們想解雇一個(gè)員工時(shí)括荡,我們沒有一個(gè)HTTP動(dòng)作叫‘FIRE’,但是我們可以通過HTTP動(dòng)作‘DELETE’來表示員工的解雇荐绝,這樣也達(dá)到了相同的目的一汽。

8. 信息過濾 (Filtering)

當(dāng)一個(gè)客戶發(fā)來獲取一個(gè)對(duì)象的列表請(qǐng)求時(shí),服務(wù)器所給他的每一個(gè)對(duì)象是否與請(qǐng)求的標(biāo)準(zhǔn)相匹配是非常重要的。如果這個(gè)列表的記錄數(shù)量很多召夹。那么很重要的一點(diǎn)就是服務(wù)器不能將它們都返回給用戶岩喷。不然這么龐大的數(shù)據(jù)量會(huì)使得第三方開發(fā)人員很難去分析獲得的數(shù)據(jù)。如果他們請(qǐng)求的是一個(gè)確定的集合监憎,然后迭代得到結(jié)果纱意,那么他們就不會(huì)想要再看到另外多出來的那100條數(shù)據(jù)。否則他們就要花額外的工作量去分析那多出來的數(shù)據(jù)鲸阔。問題是他們的程序去要去做一些限制呢偷霉?還是任由這樣的事情發(fā)生而不去管呢?

最好的辦法是API提供一些參數(shù)褐筛,讓第三方開發(fā)人員傳參去限制类少。

通過傳參的模式,服務(wù)器可以為客戶提供一些對(duì)結(jié)果集的排序等功能渔扎。當(dāng)然最重要的是限定參數(shù)的辦法使得網(wǎng)絡(luò)負(fù)擔(dān)變小了硫狞,同時(shí)客戶也能準(zhǔn)確的得到他們想要的數(shù)據(jù)。此外晃痴,客戶也可能是比較懶惰的残吩,如果客戶端能為他們提供過濾或是分頁的數(shù)據(jù),那何樂而不為呢倘核?

信息過濾最常見是存在于HTTP動(dòng)作的GET中泣侮,既然他們是GET請(qǐng)求,那么過濾參數(shù)就必須寫在URL里紧唱。下面是一些你可以參考的關(guān)于過濾參數(shù)的例子:

  • ?limit=10: 指定返回記錄的數(shù)量 (有分頁)
  • ?offset=10: 返回記錄的開始位置 (有分頁)
  • ?animal_type_id=1: 指定篩選條件活尊。(例如WHERE animal_type_id = 1)
  • ?sortby=name&order=asc: 指定返回結(jié)果按照哪個(gè)屬性排序,以及排序順序琼蚯。 (例如ORDER BY name ASC)

對(duì)于API的路徑和URL的參數(shù)允許存在冗余(即重復(fù))酬凳。比如我之前的例子 GET/zoo/ZID/animals和GET /animals?zoo_id=ZID的含義就是相同的。有些專用的路徑會(huì)方便客戶的調(diào)用遭庶,特別是那些你預(yù)計(jì)他們會(huì)經(jīng)常使用的路徑稠屠。在你的API文檔中峦睡,需要寫清楚哪些是冗余的,這樣可以消除第三方開發(fā)人員的疑惑权埠。

另外還要提一下榨了,當(dāng)參數(shù)可以指定按照某一屬性進(jìn)行排序時(shí),你需要指出哪些屬性是可以排序的攘蔽,即需要整理出可以進(jìn)行排序的屬性的白名單龙屉,因?yàn)槲覀儾恍枰l(fā)送錯(cuò)誤的數(shù)據(jù)給客戶。

9. 狀態(tài)碼 (Status Codes)

作為一個(gè)RESTful的API,你需要正確使用HTTP的響應(yīng)碼转捕。他們是一套標(biāo)準(zhǔn)作岖,許多網(wǎng)絡(luò)技術(shù)、設(shè)備都能讀懂五芝。例如負(fù)載均衡(load balancers)就能分辯出這些狀態(tài)碼并且避免了當(dāng)錯(cuò)誤為50開頭時(shí)發(fā)送給瀏覽器的很多回應(yīng)痘儡。HTTP有很多很狀態(tài)碼,查看全部請(qǐng)點(diǎn)擊這里枢步,下面我簡(jiǎn)單列了一些重要的狀態(tài)碼:

  • 200 OK - [GET]:服務(wù)器成功返回用戶請(qǐng)求的數(shù)據(jù)沉删,該操作是冪等的(Idempotent)。
  • 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數(shù)據(jù)成功醉途。
  • 204 NO CONTENT - [DELETE]:用戶刪除數(shù)據(jù)成功矾瑰。
  • 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發(fā)出的請(qǐng)求有錯(cuò)誤,服務(wù)器沒有進(jìn)行新建或修改數(shù)據(jù)的操作隘擎,該操作是冪等的脯倚。
  • 404 NOT FOUND -
    :用戶發(fā)出的請(qǐng)求針對(duì)的是不存在的記錄,服務(wù)器沒有進(jìn)行操作嵌屎,該操作是冪等的推正。
  • 500 INTERNAL SERVER ERROR - [*]:服務(wù)器發(fā)生錯(cuò)誤宝惰,用戶將無法判斷發(fā)出的請(qǐng)求是否成功。

狀態(tài)碼邊界:

1XX狀態(tài)碼是HTTP比較低等級(jí)的狀態(tài)碼尊残,在HTTP/1.0協(xié)議中沒有定議任何1XX狀態(tài)碼寝衫,所以最好不要向客戶發(fā)送任何1XX的狀態(tài)碼慰毅。
2XX狀態(tài)碼說明了客戶端接收了正確的消息。這種狀態(tài)碼是極好的东臀,所以確保你的服務(wù)器發(fā)送的都是這類的狀態(tài)碼宰掉。
3XX狀態(tài)碼用來重定向孟害。很多API通常不會(huì)使用這些請(qǐng)求(SEO優(yōu)化人員會(huì)使用它們)纹坐。值得一提的是耘子,新出來的Hypermedia API還是會(huì)使用3XX的狀態(tài)碼的谷誓。
4XX狀態(tài)碼表示客戶端的請(qǐng)求錯(cuò)誤。比如客戶端提供了錯(cuò)誤的參數(shù)或請(qǐng)求要獲取的不存在的對(duì)象糙臼。對(duì)于客戶端和服務(wù)器端來說這些請(qǐng)求是等冪的变逃。
5XX狀態(tài)碼一般是服務(wù)器在處理請(qǐng)求過程中的異常。一般來說這些錯(cuò)誤被低等級(jí)的方法所拋出凰棉,當(dāng)然也不排除開發(fā)人員手動(dòng)發(fā)送撒犀,來確保某個(gè)客戶得到某種回應(yīng)。當(dāng)服務(wù)器發(fā)送了5XX狀態(tài)碼,這個(gè)客戶可能都不會(huì)收到任何回應(yīng)杆煞,所以這些錯(cuò)誤也是不可避免的决乎。

  1. 文檔返回值 (Expected Return Documents)

當(dāng)使用不同的HTTP動(dòng)作來獲取資源時(shí)蚌斩,一個(gè)用戶需要獲取一些有排序的數(shù)據(jù)送膳,以下列舉了典型的RESTful APIs:

  • GET /collection: 返回一個(gè)資源集合叠聋。
  • GET /collection/resource: 返回單個(gè)資源對(duì)象。
  • POST /collection: 返回最新創(chuàng)建的資源對(duì)象棉饶。
  • PUT /collection/resource: 返回更新完畢的資源對(duì)象袜啃。
  • PATCH /collection/resource: 返回更新完畢的資源對(duì)象囊骤。
  • DELETE /collection/resource: 返回一個(gè)空的文檔。

當(dāng)客戶新增一個(gè)資源時(shí)滑蚯,他們通常不知道新增的資源的ID(或最新更新的時(shí)間等屬性),這些額外的屬性需要通過POST同時(shí)返回給客戶涉馅。

11. 身份認(rèn)證 (Authentication)

大多數(shù)情況下服務(wù)器會(huì)對(duì)請(qǐng)求方的身份進(jìn)行驗(yàn)證滑绒。當(dāng)然有些API提供了可以被普通用戶調(diào)用的路徑,但多數(shù)的API都需要認(rèn)證的過程纵势。

OAuth2.0提供了一個(gè)很好的解決方案钦铁。在每次請(qǐng)求時(shí),服務(wù)器需要知道哪個(gè)第三方程序發(fā)來想要獲取系統(tǒng)的某個(gè)用戶信息的請(qǐng)求躏仇,這時(shí)候,就需要用戶授權(quán)給那個(gè)第三方程序怀喉,允許它獲得用戶的信息躲履。

除此之外,還有OAuth 1.0 和 xAuth篷帅。無論你用的是哪種認(rèn)證技術(shù),你都需要確保你所使用的是常見技術(shù)箭昵,然后編輯好文 檔和供不同平臺(tái)使用的類庫掉房。

就我的經(jīng)驗(yàn)來看,關(guān)于以安全著稱的OAuth1.0a诅病,對(duì)它對(duì)接接口是非常痛苦的事贤笆。我最近驚奇的發(fā)現(xiàn)由于它沒有提供很多語言的類型,很多的第三方開發(fā)人員都開始擁有了自己的類庫。我曾經(jīng)為了它用了好幾個(gè)小時(shí)來調(diào)試一個(gè)叫“無效簽名”的錯(cuò)誤奇瘦,這真是太糟糕了棘催。

12. 內(nèi)容形式 (Content Type)

關(guān)于服務(wù)器返回的數(shù)據(jù)格式,應(yīng)該盡量使用JSON格式耳标。包括Facebook, Twitter, GitHub都是使用了這種格式醇坝。其它的格式還有XML、SOAP次坡。但是XML格式容易引起很多糾紛(特別是大型交互環(huán)境)呼猪。SOAP在當(dāng)今幾乎沒人用了。

開發(fā)人員使用流行的語言我框架可以對(duì)數(shù)據(jù)進(jìn)行有效的轉(zhuǎn)換宋距。如果服務(wù)器想提供一個(gè)很普通的回應(yīng)對(duì)象,那么它可以很容易的提供上述的數(shù)據(jù)格式(不包括SOAP)。值得注意的是,你需要正確使用響應(yīng)文檔中的頭部?jī)?nèi)容荡灾。

一些API創(chuàng)建者在響應(yīng)內(nèi)容中提供了響應(yīng)格式的參數(shù)皆警,包括json\xml\html。雖然本人很少這樣干系洛,但仍然覺得這是個(gè)不錯(cuò)的形式。

13. 超媒體 (Hypermedia APIs)

Hypermedia APIs是RESTful API設(shè)計(jì)的發(fā)展趨勢(shì),即在返回結(jié)果中提供鏈接扑媚。這樣可以使用戶在不查API文 檔的前提下葵萎,也可能知道下一步應(yīng)該要做什么票从。

當(dāng)使用一個(gè)不是Hypermedia的RESTful API時(shí),路徑是服務(wù)器和客戶之間的聯(lián)系狭瞎。但這些路徑必須是被客戶知道的,一旦服務(wù)器改變了這些路徑的作用襟己,那么客戶將不能跟服務(wù)器進(jìn)行通信仿吞,這就是傳統(tǒng)RESTful API的一大限制。

對(duì)于現(xiàn)在來說董饰,API客戶不再是發(fā)起HTTP的唯一請(qǐng)求方谴供,用著瀏覽器的人們都是發(fā)起HTTP的請(qǐng)求方桂肌。但是這些人并不會(huì)局限于使用預(yù)先定定好的RESTful API崎场。這是為什么呢?因?yàn)樗麄冏x的是真正的內(nèi)容闲先,他們點(diǎn)擊一些想要讀的標(biāo)題惕医,然后一個(gè)網(wǎng)頁就會(huì)打開來了抬伺,他們就可以知道他們真正想要的內(nèi)容。如果一個(gè)URL改變了灾梦,網(wǎng)友們是不會(huì)受影響的(除非他們定閱了一個(gè)頁面峡钓,而不是在首頁是新打開一個(gè)標(biāo)題去閱讀)

Hypermedia API的概念跟現(xiàn)實(shí)人類的世界很像。請(qǐng)求API的根目錄得到可以請(qǐng)求每個(gè)集合信息以及描述這些集合的用途的URL列表若河。另外能岩,提供給每個(gè)資原的ID不是必須的,因?yàn)閁RL里已經(jīng)提供萧福。

當(dāng)一個(gè)用戶使用Hypemedia風(fēng)格的API的鏈接來收集信息時(shí)拉鹃,響應(yīng)里一般都會(huì)包含最新的URL,這些URL沒必要提前寫在文檔里。如果一個(gè)URL被緩存了膏燕,那么可能就會(huì)返回404錯(cuò)誤钥屈,客戶可以很容易的回到根目錄來找到正確的URL。

當(dāng)要獲取一個(gè)資源列表的集合煌寇,可以在響應(yīng)的資源里放上一個(gè)關(guān)于URL的屬性焕蹄。當(dāng)需要調(diào)用POST/PATCH/PUT,服務(wù)器回應(yīng)的時(shí)候可以直接用3XX的響應(yīng)碼來做重定向阀溶。

14. 文檔 (Documentation)

說實(shí)話腻脏,如果你不是100%確定你的標(biāo)準(zhǔn),那么你的API也不是最糟糕的银锻。但如果你的API沒有文 檔永品,這將會(huì)是很糟糕的API,那么沒有人將會(huì)使用你的API击纬。

所以撰寫API文檔是十分有必要的鼎姐。

不要使用自動(dòng)生成的文檔,但如果你真的這么做了更振,那一定要保證你檢查和校驗(yàn)過這個(gè)文檔炕桨。
不要縮減請(qǐng)求和響應(yīng)的內(nèi)容,最好就全部展求肯腕。在你的文檔中有些重點(diǎn)的要加粗献宫。

在文檔中,要加上每個(gè)路徑的響應(yīng)的內(nèi)容和可能出現(xiàn)的信息錯(cuò)誤实撒,并盡可能的寫上在什么情況下可能導(dǎo)致這些錯(cuò)誤姊途。

如果你有時(shí)間的話,就建立一個(gè)開發(fā)者API的終端機(jī)知态,這樣開發(fā)者就可以更方便 的體驗(yàn)?zāi)愕腁PI捷兰。這對(duì)你來說其實(shí)并不困難,并且所有的開發(fā)者(你公司內(nèi)部的或第三方開發(fā)者)都會(huì)很喜歡這種形式负敏。

必須得確保你的文檔可以被打印贡茅。CSS是個(gè)很強(qiáng)大的技術(shù)。當(dāng)要打印的時(shí)候不必要隱藏你的側(cè)邊欄原在,因?yàn)楹芏嚅_發(fā)者都喜歡離線復(fù)印去閱讀API的文檔友扰。

15. 其它:HTTP包文

既然我們所做的所有事都是基于HTTP,那么我們接下來要討論下HTTP包文庶柿。如果一個(gè)從事這個(gè)工作的人不知道HTTP包文村怪,那是很糟糕的事情。當(dāng)一個(gè)客戶發(fā)送給服務(wù)器發(fā)送請(qǐng)求浮庐,會(huì)提供一個(gè)包含鍵/值(Key/Value)的集合甚负,叫頭部(Header)柬焕,再過幾行就是請(qǐng)求的內(nèi)容(Body)了。頭部和內(nèi)容是放在同一個(gè)包里進(jìn)行發(fā)送的梭域。

服務(wù)器的響應(yīng)格式也是一對(duì)對(duì)的鍵/值(Key/Value)形式斑举,HTTP是一個(gè)請(qǐng)求/響應(yīng)的協(xié)議,它不支持服務(wù)器無緣無故的主動(dòng)推送給客戶端病涨,除非你使用另一個(gè)叫Websockets的協(xié)議富玷。
當(dāng)設(shè)計(jì)API時(shí),一般需要用一些工具來幫助你看HTTP的包既穆。比如Wireshark,當(dāng)然你也可以用一些框架/WEB的服務(wù)自帶的工具來確保
轉(zhuǎn)載(http://angelbill3.iteye.com/blog/2108785
原文(https://codeplanet.io/principles-good-restful-api-design/
關(guān)注一波赎懦!喜歡一波!本人是前端小白幻工,這是我的個(gè)人博客鄧鵬的博客励两, 使用的技術(shù) vue全家桶 + koa2 + mysql + php + nginx!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末囊颅,一起剝皮案震驚了整個(gè)濱河市当悔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌踢代,老刑警劉巖盲憎,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異胳挎,居然都是意外死亡焙畔,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門串远,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人儿惫,你說我怎么就攤上這事澡罚。” “怎么了肾请?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵留搔,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我铛铁,道長(zhǎng)隔显,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任饵逐,我火速辦了婚禮括眠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘倍权。我一直安慰自己掷豺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著当船,像睡著了一般题画。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上德频,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天苍息,我揣著相機(jī)與錄音,去河邊找鬼壹置。 笑死竞思,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蒸绩。 我是一名探鬼主播衙四,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼患亿!你這毒婦竟也來了传蹈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤步藕,失蹤者是張志新(化名)和其女友劉穎惦界,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咙冗,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沾歪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雾消。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灾搏。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖立润,靈堂內(nèi)的尸體忽然破棺而出狂窑,到底是詐尸還是另有隱情,我是刑警寧澤桑腮,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布泉哈,位于F島的核電站,受9級(jí)特大地震影響破讨,放射性物質(zhì)發(fā)生泄漏丛晦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一提陶、第九天 我趴在偏房一處隱蔽的房頂上張望烫沙。 院中可真熱鬧,春花似錦搁骑、人聲如沸斧吐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽煤率。三九已至仰冠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蝶糯,已是汗流浹背洋只。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昼捍,地道東北人识虚。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像妒茬,于是被迫代替她去往敵國和親担锤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容