Restful風格

今天看到一個比較好的文章,記錄一下:html

Restful風格API中用put仍是post作新增操做有什麼區別?

1 HTTP協議詳解

HTTP協議一般承載於TCP協議之上,有時也承載於TLS或SSL協議層之上,這個時候,就成了咱們常說的HTTPS。以下圖所示:數據庫

            

 

默認HTTP的端口號爲80,HTTPS的端口號爲443。瀏覽器

HTTP協議永遠都是客戶端發起請求,服務器回送響應。見下圖:
     安全

這樣就限制了使用HTTP協議,沒法實如今客戶端沒有發起請求的時候,服務器將消息推送給客戶端。服務器

HTTP協議是一個無狀態的協議,同一個客戶端的此次請求和上次請求是沒有對應關係。網絡

一次HTTP操做稱爲一個事務,其工做過程可分爲四步:架構

1)首先客戶機與服務器須要創建鏈接。只要單擊某個超級連接,HTTP的工做開始。ide

2)創建鏈接後,客戶機發送一個請求給服務器,請求方式的格式爲:統一資源標識符(URL)、協議版本號,後邊是MIME信息包括請求修飾符、客戶機信息和可能的內容。post

3)服務器接到請求後,給予相應的響應信息,其格式爲一個狀態行,包括信息的協議版本號、一個成功或錯誤的代碼,後邊是MIME信息包括服務器信息、實體信息和可能的內容。性能

4)客戶端接收服務器所返回的信息經過瀏覽器顯示在用戶的顯示屏上,而後客戶機與服務器斷開鏈接。

若是在以上過程當中的某一步出現錯誤,那麼產生錯誤的信息將返回到客戶端,有顯示屏輸出。對於用戶來講,這些過程是由HTTP本身完成的,用戶只要用鼠標點擊,等待信息顯示就能夠了。

2  HTTP協議詳解之請求篇

  http請求由三部分組成,分別是:請求行、消息報頭、請求正文

請求行以一個方法符號開頭,以空格分開,後面跟着請求的URI和協議的版本,格式以下:Method Request-URIHTTP-Version CRLF  
其中 Method表示請求方法;Request-URI是一個統一資源標識符;HTTP-Version表示請求的HTTP協議版本;CRLF表示回車和換行(除了做爲結尾的CRLF外,不容許出現單獨的CR或LF字符)。

請求方法(全部方法全爲大寫)有多種,各個方法的解釋以下:
GET     請求獲取Request-URI所標識的資源
POST    在Request-URI所標識的資源後附加新的數據
HEAD    請求獲取由Request-URI所標識的資源的響應消息報頭
PUT     請求服務器存儲一個資源,並用Request-URI做爲其標識
DELETE  請求服務器刪除Request-URI所標識的資源
TRACE   請求服務器回送收到的請求信息,主要用於測試或診斷
CONNECT 保留未來使用
OPTIONS 請求查詢服務器的性能,或者查詢與資源相關的選項和需求
應用舉例:
GET方法:在瀏覽器的地址欄中輸入網址的方式訪問網頁時,瀏覽器採用GET方法向服務器獲取資源,eg:GET /form.html HTTP/1.1 (CRLF)

POST方法要求被請求服務器接受附在請求後面的數據,經常使用於提交表單。

HEAD方法與GET方法幾乎是同樣的,對於HEAD請求的迴應部分來講,它的HTTP頭部中包含的信息與經過GET請求所獲得的信息是相同的。利用這個方法,沒必要傳輸整個資源內容,就能夠獲得Request-URI所標識的資源的信息。該方法經常使用於測試超連接的有效性,是否能夠訪問,以及最近是否更新。

3  HTTP協議詳解之響應篇

在接收和解釋請求消息後,服務器返回一個HTTP響應消息。

HTTP響應也是由三個部分組成,分別是:狀態行、消息報頭、響應正文
一、狀態行格式以下:

HTTP-VersionStatus-Code Reason-Phrase CRLF
其中,HTTP-Version表示服務器HTTP協議的版本;Status-Code表示服務器發回的響應狀態代碼;Reason-Phrase表示狀態代碼的文本描述。
狀態代碼有三位數字組成,第一個數字定義了響應的類別,且有五種可能取值:
1xx:指示信息--表示請求已接收,繼續處理
2xx:成功--表示請求已被成功接收、理解、接受
3xx:重定向--要完成請求必須進行更進一步的操做
4xx:客戶端錯誤--請求有語法錯誤或請求沒法實現
5xx:服務器端錯誤--服務器未能實現合法的請求
二、常見狀態代碼、狀態描述、說明:

請求收到,繼續處理
100——客戶必須繼續發出請求
101——客戶要求服務器根據請求轉換HTTP協議版本
操做成功收到,分析、接受
200——交易成功
201——提示知道新文件的URL
202——接受和處理、但處理未完成
203——返回信息不肯定或不完整
204——請求收到,但返回信息爲空
205——服務器完成了請求,用戶代理必須復位當前已經瀏覽過的文件
206——服務器已經完成了部分用戶的GET請求
完成此請求必須進一步處理
300——請求的資源可在多處獲得
301——刪除請求數據
302——在其餘地址發現了請求數據
303——建議客戶訪問其餘URL或訪問方式
304——客戶端已經執行了GET,但文件未變化
305——請求的資源必須從服務器指定的地址獲得
306——前一版本HTTP中使用的代碼,現行版本中再也不使用
307——申明請求的資源臨時性刪除
請求包含一個錯誤語法或不能完成
400——錯誤請求,如語法錯誤
401——未受權
HTTP 401.1 - 未受權:登陸失敗
   HTTP 401.2 - 未受權:服務器配置問題致使登陸失敗
   HTTP 401.3 - ACL 禁止訪問資源
   HTTP 401.4 - 未受權:受權被篩選器拒絕
HTTP 401.5 - 未受權:ISAPI 或 CGI 受權失敗
402——保留有效ChargeTo頭響應
403——禁止訪問
HTTP 403.1 禁止訪問:禁止可執行訪問
   HTTP 403.2 - 禁止訪問:禁止讀訪問
   HTTP 403.3 - 禁止訪問:禁止寫訪問
   HTTP 403.4 - 禁止訪問:要求 SSL
   HTTP 403.5 - 禁止訪問:要求 SSL128
   HTTP 403.6 - 禁止訪問:IP 地址被拒絕
   HTTP 403.7 - 禁止訪問:要求客戶證書
   HTTP 403.8 - 禁止訪問:禁止站點訪問
   HTTP 403.9 - 禁止訪問:鏈接的用戶過多
   HTTP 403.10 - 禁止訪問:配置無效
   HTTP 403.11 - 禁止訪問:密碼更改
   HTTP 403.12 - 禁止訪問:映射器拒絕訪問
   HTTP 403.13 - 禁止訪問:客戶證書已被吊銷
   HTTP 403.15 - 禁止訪問:客戶訪問許可過多
   HTTP 403.16 - 禁止訪問:客戶證書不可信或者無效
HTTP 403.17 - 禁止訪問:客戶證書已經到期或者還沒有生效
404——沒有發現文件、查詢或URl
405——用戶在Request-Line字段定義的方法不容許
406——根據用戶發送的Accept拖,請求資源不可訪問
407——相似401,用戶必須首先在代理服務器上獲得受權
408——客戶端沒有在用戶指定的餓時間內完成請求
409——對當前資源狀態,請求不能完成
410——服務器上再也不有此資源且無進一步的參考地址
411——服務器拒絕用戶定義的Content-Length屬性請求
412——一個或多個請求頭字段在當前請求中錯誤
413——請求的資源大於服務器容許的大小
414——請求的資源URL長於服務器容許的長度
415——請求資源不支持請求項目格式
416——請求中包含Range請求頭字段,在當前請求資源範圍內沒有range指示值,請求也不包含If-Range請求頭字段
417——服務器不知足請求Expect頭字段指定的指望值,若是是代理服務器,多是下一級服務器不能知足請求長。
服務器執行一個徹底有效請求失敗
   HTTP 500 - 內部服務器錯誤
   HTTP 500.100 - 內部服務器錯誤 -ASP 錯誤
   HTTP 500-11 服務器關閉
   HTTP 500-12 應用程序從新啓動
   HTTP 500-13 - 服務器太忙
   HTTP 500-14 - 應用程序無效
   HTTP 500-15 - 不容許請求 global.asa
   Error 501 - 未實現
        HTTP 502 - 網關錯誤
   HTTP 500.100 - 內部服務器錯誤 -ASP 錯誤
   HTTP 500-11 服務器關閉
   HTTP 500-12 應用程序從新啓動
   HTTP 500-13 - 服務器太忙
   HTTP 500-14 - 應用程序無效
   HTTP 500-15 - 不容許請求 global.asa
   Error 501 - 未實現
        HTTP 502 - 網關錯誤

4 API設計的基本要求

  一個被廣泛認可和遵照:RESTful設計原則。它被Roy Felding提出(在他的」基於網絡的軟件架構「論文中第五章)。而REST的核心原則是將你的API拆分爲邏輯上的資源。這些資源經過http被操做(GET ,POST,PUT,DELETE)。
    顯然從API用戶的角度來看,」資源「應該是個名詞。即便你的內部數據模型和資源已經有了很好的對應,API設計的時候你仍然不須要把它們一對一的都暴露出來。這裏的關鍵是隱藏內部資源,暴露必需的外部資源。
    一旦定義好了要暴露的資源,你能夠定義資源上容許的操做,以及這些操做和你的API的對應關係:

·       GET /tickets # 獲取ticket列表

·       GET /tickets/12 # 查看某個具體的ticket

·       POST /tickets # 新建一個ticket

·       PUT /tickets/12 # 更新ticket 12.

·       DELETE /tickets/12 #刪除ticekt 12

    能夠看出使用REST的好處在於能夠充分利用http的強大實現對資源的CURD功能。而這裏你只須要一個endpoint:/tickets,再沒有其餘什麼命名規則和url規則了,cool!
    可是有的endpoint,須要使用複數使得你的URL更加規整。這讓API使用者更加容易理解,對開發者來講也更容易實現。
如何處理關聯?關於如何處理資源之間的管理REST原則也有相關的描述:

·       GET /tickets/12/messages- Retrieves list of messages forticket #12

·       GET /tickets/12/messages/5- Retrieves message #5 forticket #12

·       POST /tickets/12/messages- Creates a new message inticket #12

·       PUT /tickets/12/messages/5- Updates message #5 for ticket#12

·       PATCH /tickets/12/messages/5- Partially updates message#5 for ticket #12

·       DELETE /tickets/12/messages/5- Deletes message #5 forticket #12

    其中,若是這種關聯和資源獨立,那麼咱們能夠在資源的輸出表示中保存相應資源的endpoint。而後API的使用者就能夠經過點擊連接找到相關的資源。若是關聯和資源聯繫緊密。資源的輸出表示就應該直接保存相應資源信息。(例如這裏若是message資源是獨立存在的,那麼上面 GET/tickets/12/messages就會返回相應message的連接;相反的若是message不獨立存在,他和ticket依附存在,則上面的API調用返回直接返回message信息)

5 get和post區別

    經常使用的請求方式是GET和POST.

GET方式:是以實體的方式獲得由請求URI所指定資源的信息,若是請求URI只是一個數據產生過程,那麼最終要在響應實體中返回的是處理過程的結果所指向的資源,而不是處理過程的描述。

POST方式:用來向目的服務器發出請求,要求它接受被附在請求後的實體,並把它看成請求隊列中請求URI所指定資源的附加新子項,Post被設計成用統一的方法實現下列功能:

1)對現有資源的解釋;

2)向電子公告欄、新聞組、郵件列表或相似討論組發信息;

3)提交數據塊;

4)經過附加操做來擴展數據庫 。

從上面描述能夠看出,Get是向服務器發索取數據的一種請求;而Post是向服務器提交數據的一種請求,要提交的數據位於信息頭後面的實體中。

GET與POST方法有如下區別:

1)   在客戶端,Get方式在經過URL提交數據,數據在URL中能夠看到;POST方式,數據放置在HTMLHEADER內提交。

2)  GET方式提交的數據最多隻能有1024字節,而POST則沒有此限制。

3)   安全性問題。正如在(1)中提到,使用 Get 的時候,參數會顯示在地址欄上,而 Post 不會。因此,若是這些數據是中文數據並且是非敏感數據,那麼使用 get;若是用戶輸入的數據不是中文字符並且包含敏感數據,那麼仍是使用 post爲好。

4)   安全的和冪等的。所謂安全的意味着該操做用於獲取信息而非修改信息。冪等的意味着對同一 URL 的多個請求應該返回一樣的結果。完整的定義並不像看起來那樣嚴格。換句話說,GET 請求通常不該產生反作用。從根本上講,其目標是當用戶打開一個連接時,她能夠確信從自身的角度來看沒有改變資源。好比,新聞站點的頭版不斷更新。雖然第二次請求會返回不一樣的一批新聞,該操做仍然被認爲是安全的和冪等的,由於它老是返回當前的新聞。反之亦然。POST 請求就不那麼輕鬆了。POST 表示可能改變服務器上的資源的請求。仍然以新聞站點爲例,讀者對文章的註解應該經過 POST 請求實現,由於在註解提交以後站點已經不一樣了(比方說文章下面出現一條註解)。

6 put和post區別

  有的觀點認爲,應該用POST來建立一個資源,用PUT來更新一個資源;有的觀點認爲,應該用PUT來建立一個資源,用POST來更新一個資源;還有的觀點認爲能夠用PUT和POST中任何一個來作建立或者更新一個資源。這些觀點都只看到了風格,爭論起來也只是爭論哪一種風格更好,其實,用PUT仍是POST,不是看這是建立仍是更新資源的動做,這不是風格的問題,而是語義的問題。  舉一個簡單的例子,假若有一個博客系統提供一個Web API,模式是這樣http://superblogging/blogs/{blog-name},很簡單,將{blog-name}替換爲咱們的blog名字,往這個URI發送一個HTTP PUT或者POST請求,HTTP的body部分就是博文,這是一個很簡單的REST API例子。咱們應該用PUT方法仍是POST方法?取決於這個REST服務的行爲是不是idempotent的,假如咱們發送兩個http://superblogging/blogs/post/Sample請求,服務器端是什麼樣的行爲?若是產生了兩個博客帖子,那就說明這個服務不是idempotent的,由於屢次使用產生了反作用了嘛;若是後一個請求把第一個請求覆蓋掉了,那這個服務就是idempotent的。前一種狀況,應該使用POST方法,後一種狀況,應該使用PUT方法。

相關文章
相關標籤/搜索