2012-02-09 18 views
3

在RESTful服務中,不能一次檢索到的資源將進行分頁。例如:在REST中,如何在資源分頁時處理對findAll操作的GET請求?

GET /foo?page=1

的問題是,我應該怎麼處理GETALL要求,如:
GET /foo

以曝光率/ HATEOAS考慮,我看到幾個選項:

  1. 返回a 405不允許的方法幷包含第一頁的鏈接標頭: Link=<http://localhost:8080/rest/foo?page=0>; rel=」first「
  2. 回報400錯誤的請求,包括鏈路標題(同上)
  3. 回報303查看其它到第一分頁頁面
  4. 回報200 OK但只有真正迴歸第一頁(和包括下一個頁面的URI進入鏈接): Link=<http://localhost:8080/rest/foo?page=1>; rel=」next「
    • :我寧願不這樣做,已經學會了不管理默認情況下客戶端的任何內容,如果他們沒有明確要求。

這些當然只有幾個選項。我傾向於第一,但我不確定是否有一個我不知道的最佳做法。 任何反饋意見。 謝謝。

回答

2

讓我們從REST不像SOAP這樣的石頭協議這一事實入手,它只是一種構造服務的方式,類似於語言被描述爲面向對象的方式。

所有人都說,我建議如下處理。


將一個RESTful調用視爲一個函數聲明。

GET /foo 
foo() 

某些功能需要參數。

GET /foo?start=??&count=?? 
foo(start, count) 

有些語言支持默認參數,其他語言不支持;你可以自己決定你想如何處理參數。

使用默認參數,你可以假設函數定義爲

foo(start = 0, count = 10) 

使以GET /foo呼叫實際上相當於GET /foo?start=0&count=10,而到GET /foo?start=100通話將相當於GET /foo?start=100&count=10

如果希望默認參數,你可能會迫使該API的用戶明確設定startcount

foo(start, count) 

使以GET /foo的調用將返回一個400 Bad Request狀態代碼,但對GET /foo?start=0&count=10的調用將返回一個200 OK狀態代碼以及指定範圍內包含的內容。

在你有這兩種情況下,決定你將如何處理錯誤,如

GET /foo?start=-10&count=99999999 

如果參數有最大值和最小值,你需要決定是否正常化的參數,或者乾脆返回錯誤。前面的例子可能會返回一個400 Bad Request狀態代碼,但它也可以約束變成:

GET /foo?start=0&count=1000 

在它是由你來決定什麼是最有意義的在應用程序的情況下結束。

+0

從默認參數的POV中,我寧願不這樣做,只是因爲我沒有學會爲客戶隱式管理任何東西,除非他們明確要求它。從HTTP狀態代碼的POV中,您將介紹第四個選項 - 400錯誤請求 - 謝謝,這是一個有趣的選項。 – Eugen 2012-02-10 09:10:42

+0

@Eugen,默認參數是自由語言的典型代表,而嚴格的參數選擇是更保守的語言的典型代表。選擇哪個並不重要,保持一致更重要。就標題而言; REST REST的一部分是使用HTTP狀態代碼來處理基本通信。你仍然可以通過一個'400 Bad Request'傳遞一個消息體,其中可能包含* why爲什麼*這是一個錯誤的請求。如果一個客戶端請求'GET/foo/300'並且它不存在,你會發送一個'404 Not Found'狀態碼。 – zzzzBov 2012-02-10 13:59:06

+0

@Eugen,你可能會發現我對[這個問題]的答案(http://stackoverflow.com/questions/4573305/rest-api-why-use-put-delete-post-get)有用。此外,[HTTP狀態代碼](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)很重要。 – zzzzBov 2012-02-10 14:01:12

2

從RESTful的角度來看,我認爲完全可以同時處理兩個表示。考慮一個有幾個版本你想下載的軟件,最新的是3.8。所以如果你想獲得最新版本,你可以用GET /software/version/latest.zipGET /software/version/3.8.zip來解決它,直到有更新的版本。所以兩個不同的鏈接指向相同的資源。

我喜歡想象分頁幾乎相同。在第一頁上總是有最新的文章。因此,如果沒有提供page參數,則可以簡單地暗示它是1.

具有rel屬性的方法的方向稍有不同。這是Google創建的,旨在更好地處理重複內容的問題,主要用於區分「主要」頁面和分頁頁面。以下是如何使用它:

//first page: 
<link rel="next" href="http://www.foo.com/foo?page=2" /> 

//second page: 
<link rel="prev" href="http://www.foo.com/foo?page=1" /> 
<link rel="next" href="http://www.foo.com/foo?page=3" /> 

//third and last page: 
<link rel="prev" href="http://www.foo.com/foo?page=2" /> 

因此,從搜索引擎優化的角度這是一個好主意(以及由谷歌推薦)使用這些元素。它們也完全符合REST的資源導向思想和資源的超媒體表示。我想303 See Other是正確的選擇。它旨在用於這種目的,並且是規範化資源的好方法。你可以通過許多URI來使它們可用,但是對於一個表示有一個「真實的」URI(例如具有不同版本的軟件)。

根據該規範,響應應該是這個樣子:

303 See Other 
Location: http:www.foo.com/foo?page=1 

<a href="http:www.foo.com/foo?page=1">http:www.foo.com/foo?page=1</a> 

所以你提供一個位置,頭部與「真實」表示,身體應該包含一個超文本文件鏈接到新URI。請注意,根據規範客戶端預計發送GET請求的位置的值,但它不必須


//編輯爲回答您的評論(是的,這是非常糟糕的做法,要求的東西沒有:-)證明它 - 我的壞!):

谷歌提出的rel="next"rel="prev"屬性於2011年9月在Official Webmaster Central Blog。它們可以用於(或在某些情況下,而不是)rel="canonical" tag

在這些環節,你可以找到它們之間的差異來解釋:

  • rel="next"rel="prev"​​是「表示在分頁序列組件網址之間的關係」
  • rel="canonical"「讓你公開指定您的URL的首選版本「

因此,它們之間存在細微的差異。因此,您可以將問題分解爲一個規範問題:有幾個URL指向相同的資源(/foofoo?page=1,但是您有一個首選版本的URL(foo?page=1)。因此,現在有幾種REST風格的選項:

  • 如果查詢沒有給出page -parameter,使用默認值(例如1)加工時,我想在這個特定的情況下,它是確定以使用,即使你指出一個默認值作爲不好的做法
  • 迴應303 See Other位置-header(如上所述)提供首選URL。我認爲3xx -response是處理重複/規範內容的最佳(也是最可能RESTfully預期的)方式。
  • 如果您想強制客戶提供page參數(如zzzzBov在他的回答中所解釋的),請回復400 Bad Request。請注意,這個響應沒有像一個位置頭(如假設你的問題),所以解釋請求失敗的原因和/或正確的URL(如有)必須去的實體主體響應。此外,請注意,根據規範,此響應通常在客戶端提交錯誤/格式錯誤的表示(!!URL!)以及PUTPOST請求時使用。所以請記住,這也可能對客戶有點模糊。

就個人而言,我不認爲你的建議作出迴應與405 Method Not Allowed是一個好主意。根據規範,您需要必須提供允許 -header列出允許的方法。但是這個資源可以允許哪些方法?我只能想到POST。但是,如果你不希望客戶端POST它要麼,你也可以用403 Forbidden迴應與解釋爲什麼它是被禁止的,或404 Not Found如果你不想知道爲什麼它是被禁止的。所以它也可能有點模糊(在我看來)。

使用link -elements與提到rel -attributes正如你在你的問題建議在本質上不是「REST風格」,因爲它只是這是在資源的表示入駐超媒體。但是你的問題(據我瞭解)是你想要決定如何迴應一個特定的請求和要表達的服務。但它仍然不是完全沒有意義的:

您可以考慮整個SEO問題,因爲使用rel="next/prev/canonical"的副作用,但請記住,他們還創造連通(具有鏈接的質量),這是一REST的特性(見Roy Fielding's dissertation)。

如果您想深入瞭解RESTful Web Services(完全值得),我推薦閱讀Leonard Richardson和Sam Ruby的書RESTful Web Services

+0

感謝您的回覆。有一點需要注意的是,我並沒有意識到這是谷歌推動這些特定雷納斯的標準化 - 你有任何鏈接來支持這一點?另外,我沒有考慮與SEO有關的任何事情,只是在RESTful Web服務中的良好做法。再次感謝你的反饋。 – Eugen 2012-02-10 09:07:05

+0

@Eugen我已經更新了我的答案,我希望現在更清楚;) – Quasdunk 2012-02-10 10:52:48

0

在某些情況下,不會隱式管理客戶端可導致覆蓋複雜的界面事情,例子是當消費者不是技術或者是不打算在建立在接口之上,例如在網頁中。在這種情況下,即使是200也是合適的。

在其他情況下,我會同意隱含的管理將是一個糟糕的主意,因爲在那裏消費者會希望能夠正確地預測和其中可能需要一個簡單的規範的響應。在這種情況下405,400和303.

這是一個背景問題。

相關問題