目錄
- 定義(Definitions)
- 數(shù)據(jù)的設(shè)計(jì)與抽象化(Data Design and Abstraction)
- HTTP動(dòng)詞 (Verbs)
- 版本(Versioning)
- 分析 (Analytics)
- API根路徑 (API Root URL)
- 路徑 (Endpoint)
- 信息過濾 (Filtering)
- 狀態(tài)碼 (Status Codes)
- 文檔返回值 (Expected Return Documents)
- 身份認(rèn)證 (Authentication)
- 內(nèi)容形式 (Content Type)
- 超媒體 (Hypermedia APIs)
- 文檔 (Documentation)
- 其它: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)物,那么你建的路徑如下:
- https://api.example.com/v1/zoos
- https://api.example.com/v1/animals
- https://api.example.com/v1/animal_types
- https://api.example.com/v1/employees
關(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ò)誤也是不可避免的决乎。
- 文檔返回值 (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!