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