簡體   English   中英

我應該在我寧靜的api中加入連接詞嗎?

[英]should I put connecting words in my restful api or not?

假設我有一個控制器,它有三個參數:

class Dog {
    function tell (dogId, commandId, rewardId) {
         // blah
    }
}

我訪問的網址可能是:

 mysite.com/dog/tell/1/2/3

在這種情況下,您必須記住參數按dogId映射到dogIdcommandIdrewardId 另一種方式可能是:

mysite.com/dog/tell/1/command/2/reward/3

或者為了更清晰(但可能更多的jiggery-pokery與您的框架):

mysite.com/tell/dog/1/command/2/reward/3

哪個更好? 哪個更常見? 乍一看似乎更清晰更好。 但是,您仍然需要記住參數的順序,現在您還必須記住關鍵字。 (“它是'狗/命令/獎勵'還是'命令/狗/獎勵'或'狗/到/為'或......?”

思考? 參考文獻? :)

您似乎沒有在此處創建RESTful API。 REST API使用URI來表示資源,而不是操作( tell我看起來像是一個操作)。 資源操作由所有資源共有的接口定義。 我假設您正在使用HTTP設計REST API,因此您的公共接口由HTTP動詞GET,POST,PUT,DELETE等定義。

因此,不要根據操作tell來定義我們的服務,讓我們從思考資源開始:狗。 作為一個客戶,讓我們假設我正在尋找羅孚狗。 我與您的服務的第一次互動可能是以下請求:

GET mysite.com/dogs?q=Rover

在對此請求的響應中,我們假設我獲得了一個代表Rover狗的資源的URL: mysite.com/dogs/3759

現在,讓我們找出羅孚狗的狀態:

GET mysite.com/dogs/3739

在回應中,我看到羅孚狗還活着,醒着站起來(即響應告訴我羅孚的狀態 )。 響應還包括我可用於導致此資源狀態轉換的表單(即響應告訴我如何使Rover更改狀態)。

現在,下一步是告訴羅孚做點什么。 我們希望羅孚的狀態從站立轉變為坐着(假設我們不能簡單地更新流浪者狀態從站立到坐着,我們只能發出一個羅孚可以選擇遵循的命令 - 就像一只真正的狗!)。 讓我們向Rover發布一個sit命令:

POST mysite.com/dogs/3739
<command name="sit"/>

我們可以將命令視為一種資源 - 它有一個'名稱'(坐)發行者(我),一只狗(流浪者),也可以跟隨或取消跟隨(取決於狗的心情)。 現在,在我對此POST的回復中,我得到以下信息

Status  : 201 (Created)
Location: mysite.com/dogs/3739/commands/1299

狀態告訴我Rover已收到此數據,並且已導致創建新資源(我們的命令)。 如果我們想獲得此命令的狀態,我們可以通過對Location頭中給出的URL發出請求來查看它。 讓我們這樣做,找出我們新創建的命令:

GET mysite.com/dogs/3739/commands/1299

現在響應將告訴我該命令的狀態。 讓我們假設我們很幸運:已經遵循了命令(為此資源返回的表示包括一些信息,如followed=true )。 響應還包括一個返回資源的鏈接,該資源代表Rover(發出命令的狗)。

最后,當我們請求代表Rover的資源的狀態時:

GET mysite.com/dogs/3739

我們從回應中看到國家轉型已經發生,我們現在被告知羅孚是“坐着”。 響應還可能包括對Rover迄今為止以此URI鏈接形式發布的命令列表的引用:

mysite.com/dogs/3739/commands/

這是IMO更接近RESTful模型。 你在這里選擇的域名可能會讓我更難以解釋和理解。 “命令”資源令人困惑,聽起來非常冗余,但“命令”這個詞實際上只是因為我們談論的是寵物。 實際上,“命令”只是您發送給狗的消息。 當我們將“命令”一詞替換為“消息”這個詞時,更容易看出消息是一種肯定具有狀態的資源。

所以簡而言之(tl; dr):

  • 給資源提供URI,而不是操作
  • 通過發送數據創建/更新資源(導致狀態轉換)(不是'調用操作')
  • 如果可以,通過對客戶端的每個響應,幫助他們使用鏈接和表單進行下一次狀態轉換(這些允許客戶端更新自己的狀態,並更新應用程序狀態)。

有關更多閱讀,這里描述了RESTful交互的一個很好的例子:

http://www.infoq.com/articles/webber-rest-workflow

這個咖啡店的例子在Jim Webber和Ian Robinson的書“REST in Practice”中得到了完善和擴展。

當然,重新閱讀菲爾丁也是值得的(我認為第5.2節最相關):

http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

很難在一篇文章中解釋(對不起長度!)但我希望這會有所幫助。

就個人而言,我更喜歡擁有像mysite.com/dog/1/tell這樣的網址,並通過POST傳遞命令= 2和獎勵= 3。 狗ID可能也在數據中。 幾個原因:

  1. 具有后果的操作不應該通過GET完成,但是在URL中擁有整個請求會使GET非常誘人。
  2. REST僅表示請求應包含執行操作所需的所有內容,而不是URL應該包含的內容。 考慮到#1,我甚至會說將所有內容都填充到可獲取的URL中是一個壞主意。
  3. 使它更加通用; 在URL上發布HTML表單就足以測試它。
  4. 正如其他人所提到的,URL旨在形成分層命名空間。 當你把params放在URL中時,你會打破這種情況,因為(1)在'command'和'reward'之間沒有明確的父/子關系,並且(2)如果沒有params是可選的,它會使很多無效的網址。 命名params使它更糟糕,因為現在相同的“資源”有6個不同且功能相同的URL ......如果你的框架實際上支持這樣做的話。

對於一個網站,我會說連接詞是有用的,對於api,我說不是真的,好的文檔是api所需要的。

mysite.com/tell/dog/1/command/2/reward/3

看起來非常像

mysite.com/tell?dog=1&command=2&reward=3

在第二種情況下,訂單絕對不重要。 最有可能的是,它在第​​一種情況下也不重要。 如果我是你,我會接受任何組合,因為它顯然不是層次結構,因為URL是預期的。 而且,你不能指望mysite.com/tell/dog/1做一些有用的事情。

由於狗id,命令id和獎勵id只能一起使用,我也說明了這個事實,也是如此:

mysite.com/tell/dog-a-command-rewarding-by/1/2/3

甚至

mysite.com/tell/dog-a-command-rewarding-by/1-2-3

因為你不能指望mysite.com/tell/dog-a-command-rewarding-by/1做一些有用的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM