restful理解

愈來愈多的人開始意識到,網站即軟件,並且是一種新型的軟件html

這種"互聯網軟件"採用客戶端/服務器模式,創建在分佈式體系上,經過互聯網通訊,具備高延時(high latency)、高併發等特色ajax

網站開發,徹底能夠採用軟件開發的模式。可是傳統上,軟件和網絡是兩個不一樣的領域,不多有交集;軟件開發主要針對單機環境,網絡則主要研究系統之間的通訊。互聯網的興起,使得這兩個領域開始融合,如今咱們必須考慮,如何開發在互聯網環境中使用的軟件。編程

RESTful架構,就是目前最流行的一種互聯網軟件架構。它結構清晰、符合標準、易於理解、擴展方便,因此正獲得愈來愈多網站的採用。json

可是,到底什麼是RESTful架構,並非一個容易說清楚的問題。下面,我就談談我理解的RESTful架構。api

1、起源緩存

REST這個詞,是Roy Thomas Fielding在他2000年的博士論文中提出的。安全

Fielding是一個很是重要的人,他是HTTP協議(1.0版和1.1版)的主要設計者、Apache服務器軟件的做者之一、Apache基金會的第一任主席。因此,他的這篇論文一經發表,就引發了關注,而且當即對互聯網開發產生了深遠的影響。服務器

他這樣介紹論文的寫做目的:restful

"本文研究計算機科學兩大前沿----軟件和網絡----的交叉點。長期以來,軟件研究主要關注軟件設計的分類、設計方法的演化,不多客觀地評估不一樣的設計選擇對系統行爲的影響。而相反地,網絡研究主要關注系統之間通訊行爲的細節、如何改進特定通訊機制的表現,經常忽視了一個事實,那就是改變應用程序的互動風格比改變互動協議,對總體表現有更大的影響。我這篇文章的寫做目的,就是想在符合架構原理的前提下,理解和評估以網絡爲基礎的應用軟件的架構設計,獲得一個功能強、性能好、適宜通訊的架構。"網絡

(This dissertation explores a junction on the frontiers of two research disciplines in computer science: software and networking. Software research has long been concerned with the categorization of software designs and the development of design methodologies, but has rarely been able to objectively evaluate the impact of various design choices on system behavior. Networking research, in contrast, is focused on the details of generic communication behavior between systems and improving the performance of particular communication techniques, often ignoring the fact that changing the interaction style of an application can have more impact on performance than the communication protocols used for that interaction. My work is motivated by the desire to understand and evaluate the architectural design of network-based application software through principled use of architectural constraints, thereby obtaining the functional, performance, and social properties desired of an architecture. )

2、名稱

Fielding將他對互聯網軟件的架構原則,定名爲REST,即Representational State Transfer的縮寫。我對這個詞組的翻譯是"表現層狀態轉化"。

若是一個架構符合REST原則,就稱它爲RESTful架構。

要理解RESTful架構,最好的方法就是去理解Representational State Transfer這個詞組究竟是什麼意思,它的每個詞表明瞭什麼涵義。若是你把這個名稱搞懂了,也就不難體會REST是一種什麼樣的設計。

3、資源(Resources)

REST的名稱"表現層狀態轉化"中,省略了主語。"表現層"其實指的是"資源"(Resources)的"表現層"。

所謂"資源",就是網絡上的一個實體,或者說是網絡上的一個具體信息。它能夠是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的實在。你能夠用一個URI(統一資源定位符)指向它,每種資源對應一個特定的URI。要獲取這個資源,訪問它的URI就能夠,所以URI就成了每個資源的地址或獨一無二的識別符。

所謂"上網",就是與互聯網上一系列的"資源"互動,調用它的URI。

4、表現層(Representation)

"資源"是一種信息實體,它能夠有多種外在表現形式。咱們把"資源"具體呈現出來的形式,叫作它的"表現層"(Representation)。

好比,文本能夠用txt格式表現,也能夠用HTML格式、XML格式、JSON格式表現,甚至能夠採用二進制格式;圖片能夠用JPG格式表現,也能夠用PNG格式表現。

URI只表明資源的實體,不表明它的形式。嚴格地說,有些網址最後的".html"後綴名是沒必要要的,由於這個後綴名錶示格式,屬於"表現層"範疇,而URI應該只表明"資源"的位置。它的具體表現形式,應該在HTTP請求的頭信息中用Accept和Content-Type字段指定,這兩個字段纔是對"表現層"的描述。

5、狀態轉化(State Transfer)

訪問一個網站,就表明了客戶端和服務器的一個互動過程。在這個過程當中,勢必涉及到數據和狀態的變化。

互聯網通訊協議HTTP協議,是一個無狀態協議。這意味着,全部的狀態都保存在服務器端。所以,若是客戶端想要操做服務器,必須經過某種手段,讓服務器端發生"狀態轉化"(State Transfer)。而這種轉化是創建在表現層之上的,因此就是"表現層狀態轉化"。

客戶端用到的手段,只能是HTTP協議。具體來講,就是HTTP協議裏面,四個表示操做方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操做:GET用來獲取資源,POST用來新建資源(也能夠用於更新資源),PUT用來更新資源,DELETE用來刪除資源。

6、綜述

綜合上面的解釋,咱們總結一下什麼是RESTful架構:

  (1)每個URI表明一種資源;

  (2)客戶端和服務器之間,傳遞這種資源的某種表現層

  (3)客戶端經過四個HTTP動詞,對服務器端資源進行操做,實現"表現層狀態轉化"。

7、誤區

RESTful架構有一些典型的設計誤區。

最多見的一種設計錯誤,就是URI包含動詞。由於"資源"表示一種實體,因此應該是名詞,URI不該該有動詞,動詞應該放在HTTP協議中

舉例來講,某個URI是/posts/show/1,其中show是動詞,這個URI就設計錯了,正確的寫法應該是/posts/1,而後用GET方法表示show。

若是某些動做是HTTP動詞表示不了的,你就應該把動做作成一種資源。好比網上匯款,從帳戶1向帳戶2匯款500元,錯誤的URI是:

  POST /accounts/1/transfer/500/to/2

正確的寫法是把動詞transfer改爲名詞transaction,資源不能是動詞,可是能夠是一種服務:

  POST /transaction HTTP/1.1
  Host: 127.0.0.1
  
  from=1&to=2&amount=500.00

另外一個設計誤區,就是在URI中加入版本號:

  http://www.example.com/app/1.0/foo

  http://www.example.com/app/1.1/foo

  http://www.example.com/app/2.0/foo

由於不一樣的版本,能夠理解成同一種資源的不一樣表現形式,因此應該採用同一個URI。版本號能夠在HTTP請求頭信息的Accept字段中進行區分(參見Versioning REST Services):

  Accept: vnd.example-com.foo+json; version=1.0

  Accept: vnd.example-com.foo+json; version=1.1

  Accept: vnd.example-com.foo+json; version=2.0

(完)

 

轉自:http://www.ruanyifeng.com/blog/2011/09/restful.html

一篇文章:

Literate Programming - Nobody Understands REST or HTTP


這篇文章頗有意思,挖掘了REST深層,特別重點指出REST的URL是名詞。

好比銀行轉賬,從賬戶1轉到賬戶2轉去500元,那麼REST URL通常人寫成:
POST /accounts/1/transfer/500.00/to/2

其實錯誤的,由於REST中R表明Resource資源,資源是名詞,你並非在轉錢,而是在建立一個轉賬交易資源。應該是:

POST 資源名詞



這個概念頗有意思,咱們知道DDD也是一個名詞建模,在DDD,轉賬交易咱們是使用一個服務來實現,固然這裏的服務能夠當作是一個資源。

曾經有一篇文章認爲WEB天生是面向函數的,這裏的「POST」能夠當作是一個方法函數,而「資源名詞」當作方法的參數。

未來是否有一種技術思想,將DDD REST以及面向函數三者完美捆綁一塊兒,經過URL表明領域模型類圖的結構關係,好比/forum/thread,表明Forum類的子類Thread,領域模型被顯式地用URL表達出來,用戶訪問形式和咱們分析設計的模型合二爲一,大道至簡。

遐想太多,回到這篇文章,做者認爲這個轉賬應該是建立一個轉賬交易資源,改成:

POST /transactions


而後加入參數 from=1&to=2&amount=500.00

在面向函數FP中,函數也能夠當作是一個對象,對象也就是資源,在REST這裏好像獲得了統一。

接着做者思路,當建立了交易資源後,服務器REST端將返回:


HTTP/1.1 201 OK
Date: Sun, 3 Jul 2011 23:59:59 GMT
Content-Type: application/json
Content-Length: 12345
Location: http://foo.com/transactions/1

{
"transaction":{"id":1,"uri":"/transactions/1"}}



返回的URL是http://foo.com/transactions/1,也就是告訴你已經成功建立了transactions這個交易,下一步你能夠訪問其中的/transactions/1

當REST客戶端再次訪問:
GET /transactions/1 HTTP/1.1

返回結果是:
HTTP/1.1 blah blah blah

{"id":1,"status":"in-progress"}

表示正在處理當中,咱們能夠繼續訪問這個URL,直至其完成或失敗。這就是名詞思路。

有人可能認爲這個名詞思路和WEB的天生函數FP有違背,實際上,REST的POST/GET等四個動做已經代表是函數,那麼URL無疑表明業務名詞,固然,是否是能夠將URL又表明業務方法或函數呢?其實,這裏transactions交易被看成資源,而交易顯然是業務方法或函數。

 

http動詞

 

對於資源的具體操做類型,由HTTP動詞表示。

經常使用的HTTP動詞有下面五個(括號裏是對應的SQL命令)。

  • GET(SELECT):從服務器取出資源(一項或多項)。
  • POST(CREATE):在服務器新建一個資源。
  • PUT(UPDATE):在服務器更新資源(客戶端提供改變後的完整資源)。
  • PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)。
  • DELETE(DELETE):從服務器刪除資源。

還有兩個不經常使用的HTTP動詞。

  • HEAD:獲取資源的元數據。
  • OPTIONS:獲取信息,關於資源的哪些屬性是客戶端能夠改變的。

下面是一些例子。

  • GET /zoos:列出全部動物園
  • POST /zoos:新建一個動物園
  • GET /zoos/ID:獲取某個指定動物園的信息
  • PUT /zoos/ID:更新某個指定動物園的信息(提供該動物園的所有信息)
  • PATCH /zoos/ID:更新某個指定動物園的信息(提供該動物園的部分信息)
  • DELETE /zoos/ID:刪除某個動物園
  • GET /zoos/ID/animals:列出某個指定動物園的全部動物
  • DELETE /zoos/ID/animals/ID:刪除某個指定動物園的指定動物

post和put區別

put也能夠用來表示新建資源,這時和post有什麼區別呢?

常會混淆HTTP的POST/PUT方法,由於這兩個方法彷佛均可以用來建立或更新一個資源。

區別是細微但清楚的:

POST方法用來建立一個子資源,如 /api/users,會在users下面建立一個user,如users/1

POST方法不是冪等的,屢次執行,將致使多條相同的用戶被建立(users/1,users/2 ...而這些用戶除了自增加id外有着相同的數據,除非你的系統實現了額外的數據惟一性檢查)

 

PUT方法用來建立一個URI已知的資源(這是和post的區別,post uri中id未知,而put時uri是徹底肯定的),或對已知資源進行徹底替換,好比users/1,

所以PUT方法通常會用來更新一個已知資源,除非在建立前,你徹底知道本身要建立的對象的URI

 (在編程中.一個冪等操做的特色是其任意屢次執行所產生的影響均與一次執行的影響相同。冪等函數,或冪等方法,是指可使用相同參數重複執行,並能得到相同結果的函數。這函數不會影響系統狀態,也不用擔憂重複執行會對系統形成改變。例如,「getUsername()和setTrue()」函數就是一個冪等函數.更復雜的操做冪等保證是利用惟一交易號(流水號)實現.)

下面是RFC的描述:

The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI.
The URI in a POST request identifies the resource that will handle the enclosed entity.
That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations.
In contrast, the URI in a PUT request identifies the entity enclosed with the request --
the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource.

--

另外例子:

HTTP POST vs HTTP PUT

建立:

在不知道資源標識符時你應該使用POST來建立資源。使用POST建立資源時,返回「201 Created"狀態和新建資源的位置是很好的實踐,由於新建資源的位置在提交時是未知的。這可使客戶端稍後訪問新建立的資源若是須要的話。

HTTP/1.1 POST /accounts
{

}
響應:

201 Created
Location: https://api.stormpath.com/accounts/abcdef1234
當你容許客戶端指定新建資源的資源標識符時要使用PUT。但要記住,由於PUT是冪等的,你必需要發送全部可能的值

HTTP/1.1 PUT /accounts/abcdef1234

{
「givenName」: 「John」,
「surname」: 「Smith」,
「status」: 「enabled」
}

你可以使用POST更新所有或一部分值。

HTTP/1.1 POST /accounts/abcdef1234
{
「status」: 「disabled」
}
Response 200 OK
若是你想用PUT更新某一資源,則必需要更新資源的所有屬性。你必需要在PUT請求中發送全部屬性值以保證冪等性

HTTP/1.1 PUT /accounts/abcdef1234
{ //FULL RESOURCE UPDATE
「givenName」: 「J」,
「surname」: 「Smith」,
「status」: 「Enabled」
}
也可使用POST發送全部值,這樣服務端狀態與處理PUT請求的結果是同樣的——這不是HTTP規範所必需的。注意冪等性與HTTP緩存服務器的緩存有較強的關聯,而且POST請求一般是非緩存的。若是你對緩存的反作用感冒的話,你可使用POST來執行所有或部分更新。

POST是目前唯一的狀態不統一的方法。HTTP規範對它的定義也很寬泛,而且大致上將它定義爲了一個「服務端處理指令」。這就意味着在POST請求中作任何處理都是「安全」的。
最後咱們要注意HTTP規範中尚未完成的另外一個稱爲PATCH的方法。PATCH意爲用於執行部分更新時的POST的替代品。然而,由於POST已經能夠處理部分更新,HTTP協會彷佛沒有急着批准和完成PATCH的必要了。但若是批准了,PATCH將會加入POST做爲另外一個狀態不統一的HTTP方法。

轉:http://www.oschina.net/translate/put-or-post

 

 

http://www.ruanyifeng.com/blog/2014/05/restful_api.html

相關文章
相關標籤/搜索