摘要:返回值結(jié)構(gòu)在完成了上面的部署之后,接下來(lái)我們來(lái)看看返回結(jié)果應(yīng)該怎么樣來(lái)確定。因?yàn)榉祷刂抵?,我們常常要?duì)數(shù)據(jù)進(jìn)行區(qū)分分組,或者按照從屬關(guān)系打包,所以,我們?cè)俜祷貢r(shí),最好有包裹的思想,把數(shù)據(jù)存放在不同的包裹中進(jìn)行返回。
在項(xiàng)目中,需要為APP撰寫(xiě)API。剛開(kāi)始接觸的時(shí)候,并沒(méi)有考慮太多,就想提供URL,APP端通過(guò)該URL進(jìn)行查詢(xún)、創(chuàng)建、更新等操作即可。但再對(duì)相關(guān)規(guī)范進(jìn)行了解后,才發(fā)現(xiàn),API的設(shè)計(jì)并沒(méi)有那么簡(jiǎn)單,遠(yuǎn)遠(yuǎn)不是URL的問(wèn)題,而是一個(gè)通信協(xié)議的整體架構(gòu)。因此,我寫(xiě)這篇文章,用來(lái)記錄自己的一些心得,并不斷完善。并提供關(guān)于RESTful API的一些參考文獻(xiàn)。
1. 使用SSL(https)來(lái)提供URL首先,使用https可以在數(shù)據(jù)包被抓取時(shí)多一層加密。我們現(xiàn)在的APP使用環(huán)境大部分都是在路由器WIFI環(huán)境下,一旦路由器被入侵,那么黑客可以非常容易的抓取到用戶(hù)通過(guò)路由器傳輸?shù)臄?shù)據(jù),如果使用http未經(jīng)加密,那么黑客可以很輕松的獲取用戶(hù)的信息,甚至是賬戶(hù)信息。
其次,即使使用https,也要在API數(shù)據(jù)傳輸設(shè)計(jì)時(shí),正確的采用加密。例如直接將token信息放在URL中的做法,即使你使用了https,黑客抓不到你具體傳輸?shù)臄?shù)據(jù),但是可以抓到你請(qǐng)求的URL啊!(查了資料了,https用GET方式請(qǐng)求,也僅能抓到域名字符部分,不能抓到請(qǐng)求的數(shù)據(jù),但是URL可以在瀏覽器或特殊客戶(hù)端工具中直接看到。多謝下面的朋友指正錯(cuò)誤)因此,使用https進(jìn)行請(qǐng)求時(shí),要采用POST、PUT或者HEAD的方式傳輸必要的數(shù)據(jù)。
請(qǐng)求模式也可以說(shuō)是動(dòng)作、數(shù)據(jù)傳輸方式,通常我們?cè)趙eb中的form有GET、POST兩種,而在HTTP中,存在下發(fā)這幾種。
3. 在URI中體現(xiàn)資源,而非動(dòng)作GET (選擇):從服務(wù)器上獲取一個(gè)具體的資源或者一個(gè)資源列表。
POST (創(chuàng)建): 在服務(wù)器上創(chuàng)建一個(gè)新的資源。
PUT(更新):以整體的方式更新服務(wù)器上的一個(gè)資源。
PATCH (更新):只更新服務(wù)器上一個(gè)資源的一個(gè)屬性。
DELETE(刪除):刪除服務(wù)器上的一個(gè)資源。
HEAD : 獲取一個(gè)資源的元數(shù)據(jù),如數(shù)據(jù)的哈希值或最后的更新時(shí)間。
OPTIONS:獲取客戶(hù)端能對(duì)資源做什么操作的信息。
閱讀RESTful架構(gòu)的參考文獻(xiàn)之后,你會(huì)了解什么是資源的概念,以及REST的確切含義。再構(gòu)建API的URL的時(shí)候,URI中應(yīng)該僅包含資源(對(duì)象),而不要加入動(dòng)作。比如 /user/1/update ,其中update就是一個(gè)動(dòng)作,雖然我們希望通過(guò)這個(gè)URI來(lái)實(shí)現(xiàn)用戶(hù)ID為1的用戶(hù)進(jìn)行信息更新,但是按照RESTful的規(guī)范,作為動(dòng)作,應(yīng)該用上面的PUT來(lái)表示,所以請(qǐng)求更新用戶(hù)信息,應(yīng)該使用 PUT /user/1 來(lái)表示更新用戶(hù)ID為1的用戶(hù)信息。
如果去對(duì)應(yīng)上面的請(qǐng)求模式,GET表示顯示、列出、展示,POST表示提交、創(chuàng)建,PUT表示更新,DELETE表示刪除。
上面這段代碼中$url僅僅是提供到了user,而并沒(méi)有提供add,服務(wù)端通過(guò)識(shí)別POST請(qǐng)求來(lái)確定,這是一個(gè)創(chuàng)建用戶(hù)的操作。但是還有一些數(shù)據(jù)并沒(méi)有用以處理數(shù)據(jù),而是用以驗(yàn)證的,比如下文的鑒權(quán),可以將這些信息通過(guò)header進(jìn)行傳輸,下方詳細(xì)展示。
4. 版本API的開(kāi)發(fā)直接關(guān)系了APP是否可以正常使用,如果原本運(yùn)行正常的API,突然改動(dòng),那么之前使用這個(gè)API的APP可能無(wú)法正常運(yùn)行。APP是不可能強(qiáng)迫用戶(hù)主動(dòng)升級(jí)的,因此,通過(guò)API版本來(lái)解決這個(gè)問(wèn)題。也就是說(shuō),API的多個(gè)版本是同時(shí)運(yùn)行的,而且都要保證可以正常使用。
按照RESTful的規(guī)范,不同的版本也應(yīng)該用相同的API URL,通過(guò)header信息來(lái)判斷版本,再調(diào)用不同版本的程序進(jìn)行處理。但是這明顯會(huì)給開(kāi)發(fā)帶來(lái)巨大的成本。解決辦法有兩種:1.新版本兼容舊版本,所有舊版本的動(dòng)作、字段、操作,都在新版本中可以被實(shí)現(xiàn),但明顯這樣的維護(hù)成本很大;2.不同的版本,用不同的URL來(lái)提供服務(wù),比如再URL中通過(guò)v1、v2來(lái)區(qū)分版本號(hào),我則更喜歡采用子域名的方式,比如v2.api.xxx.com/user的方式。
5. HTTP響應(yīng)碼在用戶(hù)發(fā)出請(qǐng)求,服務(wù)端對(duì)請(qǐng)求進(jìn)行響應(yīng)時(shí),給予正確的HTTP響應(yīng)狀態(tài)碼,有利于讓客戶(hù)端正確區(qū)分遇到的情況。
200 OK - [GET]:服務(wù)器成功返回用戶(hù)請(qǐng)求的數(shù)據(jù),該操作是冪等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用戶(hù)新建或修改數(shù)據(jù)成功。
202 Accepted - [*]:表示一個(gè)請(qǐng)求已經(jīng)進(jìn)入后臺(tái)排隊(duì)(異步任務(wù))
204 NO CONTENT - [DELETE]:用戶(hù)刪除數(shù)據(jù)成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶(hù)發(fā)出的請(qǐng)求有錯(cuò)誤,服務(wù)器沒(méi)有進(jìn)行新建或修改數(shù)據(jù)的操作,該操作是冪等的。
401 Unauthorized - [*]:表示用戶(hù)沒(méi)有權(quán)限(令牌、用戶(hù)名、密碼錯(cuò)誤)。
403 Forbidden - [*] 表示用戶(hù)得到授權(quán)(與401錯(cuò)誤相對(duì)),但是訪(fǎng)問(wèn)是被禁止的。
404 NOT FOUND - [*]:用戶(hù)發(fā)出的請(qǐng)求針對(duì)的是不存在的記錄,服務(wù)器沒(méi)有進(jìn)行操作,該操作是冪等的。
406 Not Acceptable - [GET]:用戶(hù)請(qǐng)求的格式不可得(比如用戶(hù)請(qǐng)求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用戶(hù)請(qǐng)求的資源被永久刪除,且不會(huì)再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí),發(fā)生一個(gè)驗(yàn)證錯(cuò)誤。
500 INTERNAL SERVER ERROR - [*]:服務(wù)器發(fā)生錯(cuò)誤,用戶(hù)將無(wú)法判斷發(fā)出的請(qǐng)求是否成功。
在完成了上面的URL部署之后,接下來(lái)我們來(lái)看看返回結(jié)果應(yīng)該怎么樣來(lái)確定。我看到大部分文獻(xiàn)中指出,最好使用JSON進(jìn)行返回,而非xml。我認(rèn)為原因可能有兩點(diǎn):1. JSON可以很好的被很多程序支持,javascript的ajax可以直接將JSON轉(zhuǎn)換為對(duì)象。2. JSON的格式在容量上比xml小很多,可以減低寬帶占用,提高傳輸效率。
那么,返回值應(yīng)該怎么去部署呢?
首先,字段的合理返回,數(shù)據(jù)的包裹。因?yàn)榉祷刂抵?,我們常常要?duì)數(shù)據(jù)進(jìn)行區(qū)分分組,或者按照從屬關(guān)系打包,所以,我們?cè)俜祷貢r(shí),最好有包裹的思想,把數(shù)據(jù)存放在不同的包裹中進(jìn)行返回。
{ "error_code" : 0, "data" : { "user_id" : 1, "username" : "xiaomin" }, "server_time": 14939939 }
上面返回的JSON中,使用data來(lái)作為數(shù)據(jù)包,將所有數(shù)據(jù)統(tǒng)一以這個(gè)字段進(jìn)行包裹。除了data,也可以用list等其他形式的包裹,命名都是自己來(lái)根據(jù)自己的需要確定的。
{ "error_code" : 0, "list" : [ {"user_id":1,"username":"xiaoming"}, {"user_id":2,"username":"goudan"} ] "server_time": 14939939 }
總之,不要不分包,直接把所有數(shù)據(jù)和一些你想返回的全局?jǐn)?shù)據(jù)混在一起進(jìn)行返回。
其次,錯(cuò)誤碼。錯(cuò)誤碼的作用是方便查找錯(cuò)誤原因,通常情況下,我喜歡用error_code來(lái)表示,當(dāng)error_code=0時(shí),表示沒(méi)有發(fā)生錯(cuò)誤,當(dāng)error_code>0時(shí),發(fā)生了錯(cuò)誤,并且提供較為詳細(xì)的文檔,告訴客戶(hù)端對(duì)應(yīng)的error_code值所產(chǎn)生的錯(cuò)誤的原因和位置。
最后,空白壓縮和字符轉(zhuǎn)換。也就是返回的JSON結(jié)果不要換行和空格,用一行返回結(jié)果,使整個(gè)結(jié)果文本容量最小。同時(shí),中文等字符或結(jié)果中有引號(hào),都進(jìn)行字符轉(zhuǎn)換,防止結(jié)果無(wú)法被正確識(shí)別。
7. 鑒權(quán)其實(shí)也就是客戶(hù)端的權(quán)限控制。一般而言,我會(huì)采用給客戶(hù)端分發(fā)一個(gè)token來(lái)確定該客戶(hù)端的唯一身份。客戶(hù)端在請(qǐng)求時(shí),通過(guò)這個(gè)token,判斷發(fā)出請(qǐng)求的客戶(hù)端所對(duì)應(yīng)的用戶(hù),及其相關(guān)信息和權(quán)限。
前文已經(jīng)提到了,token信息不是用來(lái)進(jìn)行處理的數(shù)據(jù),雖然可以通過(guò)POST、PUT等進(jìn)行數(shù)據(jù)提交或傳輸,但是從RESTful規(guī)范來(lái)講,它不屬于操作數(shù)據(jù),在服務(wù)端進(jìn)行處理時(shí),僅是利用token進(jìn)行鑒權(quán)處理,所以,我的建議是通過(guò)header來(lái)發(fā)送token。
"xiaoming", "user_email" => "xx@sfa.com" ); // 添加apikey到header curl_setopt($ch, CURLOPT_HTTPHEADER , $header); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 執(zhí)行HTTP請(qǐng)求 curl_setopt($ch , CURLOPT_URL , $url); $res = curl_exec($ch); var_dump(json_decode($res)); ?>
上面的代碼中,通過(guò)將CURLOPT_CUSTOMREQUEST設(shè)置為PUT,就可以發(fā)出PUT請(qǐng)求,發(fā)出的PUT請(qǐng)求,仍然需要通過(guò)CURLOPT_POSTFIELDS來(lái)傳輸數(shù)據(jù)。服務(wù)端接受PUT請(qǐng)求時(shí),首先要對(duì)發(fā)出請(qǐng)求的客戶(hù)端進(jìn)行token驗(yàn)證,通過(guò)對(duì)token的處理,查找到擁有該token的實(shí)際用戶(hù),從而確定了將對(duì)哪一個(gè)用戶(hù)進(jìn)行信息更新操作。
國(guó)內(nèi)大部分API對(duì)PUT、DELETE請(qǐng)求進(jìn)行了閹割,更不用提HEAD、PACTH、OPTIONS請(qǐng)求。實(shí)際上,國(guó)內(nèi)大部分開(kāi)放API僅支持GET和POST兩種,部分API支持將app key信息通過(guò)header進(jìn)行發(fā)送。在面對(duì)這種情況下,我們不得不拋棄標(biāo)準(zhǔn)的RESTful規(guī)范,在url中加入get、add、update、delete等動(dòng)作詞匯,以補(bǔ)充由于請(qǐng)求支持不完善帶來(lái)的動(dòng)作區(qū)分問(wèn)題。如果僅支持GET和POST,那么所有需要保密的數(shù)據(jù),絕對(duì)不可以用GET來(lái)進(jìn)行請(qǐng)求,而必須用POST。
參考文獻(xiàn)《理解RESTful架構(gòu)》《RESTful API 設(shè)計(jì)指南》
《好RESTful API的設(shè)計(jì)原則》
《我所理解的RESTful Web API [設(shè)計(jì)篇]》
《https工作原理》
我的個(gè)人博客 www.tangshuang.net 偶爾寫(xiě)一些學(xué)習(xí)中的感想和經(jīng)驗(yàn),希望有相同興趣的朋友到博客來(lái)交流。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/21233.html
摘要:通常情況下,偽都是基于第一層次與第二層次設(shè)計(jì)的。為了解決這個(gè)版本不兼容問(wèn)題,在設(shè)計(jì)的一種實(shí)用的做法是使用版本號(hào)。例如,建議第三位版本號(hào)通常表示兼容升級(jí),只有不兼容時(shí)才需要變更服務(wù)版本。 原文地址:梁桂釗的博客 博客地址:blog.720ui.com 歡迎關(guān)注公眾號(hào):「服務(wù)端思維」。一群同頻者,一起成長(zhǎng),一起精進(jìn),打破認(rèn)知的局限性。 有一段時(shí)間沒(méi)怎么寫(xiě)文章了,今天提筆寫(xiě)一篇自己對(duì) API 設(shè)...
摘要:通常情況下,偽都是基于第一層次與第二層次設(shè)計(jì)的。為了解決這個(gè)版本不兼容問(wèn)題,在設(shè)計(jì)的一種實(shí)用的做法是使用版本號(hào)。例如,建議第三位版本號(hào)通常表示兼容升級(jí),只有不兼容時(shí)才需要變更服務(wù)版本。 原文地址:梁桂釗的博客博客地址:http://blog.720ui.com 歡迎關(guān)注公眾號(hào):「服務(wù)端思維」。一群同頻者,一起成長(zhǎng),一起精進(jìn),打破認(rèn)知的局限性。 有一段時(shí)間沒(méi)怎么寫(xiě)文章了,今天提筆寫(xiě)一篇...
摘要:因此,誤解幾乎是與之俱來(lái)的。這是完全錯(cuò)誤的。就像所強(qiáng)調(diào)的,對(duì)于一個(gè)被稱(chēng)作的來(lái)說(shuō),狀態(tài)轉(zhuǎn)移管理是一個(gè)必須要完成的需求。你可以將其稱(chēng)為或是,但是請(qǐng)不要把它叫做。 2000年的時(shí)候,Douglas Crockford聲明JavaScript是最被誤解的編程語(yǔ)言。這種誤解來(lái)源于不良的命名規(guī)范,錯(cuò)誤設(shè)計(jì),非標(biāo)準(zhǔn)模式等等。因此,誤解幾乎是與之俱來(lái)的。 我也在關(guān)于Restful架構(gòu)上發(fā)表了一個(gè)相似的...
摘要:狀態(tài)碼狀態(tài)碼范圍信息,請(qǐng)求收到,繼續(xù)處理。范圍的狀態(tài)碼是保留給服務(wù)器端錯(cuò)誤用的。當(dāng)收到響應(yīng)時(shí),客戶(hù)端不可能知道服務(wù)器的狀態(tài),所以這類(lèi)狀態(tài)碼是要盡可能的避免。服務(wù)器向用戶(hù)返回的狀態(tài)碼和提示信息,常見(jiàn)的有以下一些方括號(hào)中是該狀態(tài)碼對(duì)應(yīng)的動(dòng)詞。 這篇 文章主要是借鑒他人,但是自己很想總結(jié)出一套規(guī)范,以供向我這樣的新手使用,用來(lái)規(guī)范代碼,如果有什么好的提議,請(qǐng)不吝賜教,本篇文章長(zhǎng)期更新! 一、...
閱讀 2831·2021-09-28 09:45
閱讀 1507·2021-09-26 10:13
閱讀 897·2021-09-04 16:45
閱讀 3661·2021-08-18 10:21
閱讀 1084·2019-08-29 15:07
閱讀 2633·2019-08-29 14:10
閱讀 3147·2019-08-29 13:02
閱讀 2459·2019-08-29 12:31