2012-03-15 88 views
2

我有一個服務需要.odt模板文件和一些文本值,並在輸出時生成.odt。我需要通過HTTP使這項服務可用,而我不知道什麼是使RESTful界面工作的最有效途徑。通過HTTP模擬過程調用的最佳/最RESTful方式是什麼?

我需要能夠提供的模板文件,並輸入值,服務器 - 並獲得所產生的.odt文件發回給我。我看到這是如何工作的選項有:

  1. PUT或POST模板到服務器,然後做一個GET請求,沿着我剛剛發佈模板的URI傳遞,再加上輸入值 - 將GET響應主體將擁有.odt
  2. 在單個GET請求中發送模板和參數 - 模板文件將進入GET請求主體。
  3. 像上面的(2)一樣,除了做整個事情作爲單個POST請求而不是GET。

(1)的問題是我不想將模板文件存儲在服務器上。這增加了複雜性,並且除了它是一種非常REST風格的方法之外,存儲該文件對我來說沒有用處。另外,一個請求會比2更好,所有其他事情都是平等的。

與(2)是把身體的GET請求接壤HTTP的濫用問題 - 這是我現在使用的軟件支持,但不一定是。

數字(3)似乎有誤導性,因爲這比'發佈'更自然地是'讀取'或'獲取'操作。我正在做的事情本質上就像一個函數調用 - 我需要在中傳遞大量的數據,而且我真的只是使用HTTP作爲在網絡上公開我的代碼的便捷方式。也許我想要做的事情本質上不是RESTful,並且沒有REST友好的解決方案?任何人都可以建議嗎?謝謝!

+0

剛剛發現了一個非常尖銳的問題,解決(但不回答)我的問題:http://stackoverflow.com/questions/9010724/rest-and-get-again-這似乎是我的問題的癥結所在 - 爲什麼我們是否應該能夠提供複雜/大型數據作爲GET請求的一部分? – 2012-03-15 20:13:12

回答

1

你在做什麼不是休息-FUL - 或者,至少,是很難在REST來表達,因爲你都在思考的操作第一,不是第一對象。

最REST-ful表達式是創建一個新的「OdtTemplate」資源(或獲取現有URI的資源),創建一個新的「SetOfValues」資源,然後創建一個與其綁定的「FillInTemplateWithValues」作業資源輸入到這兩個輸入中,並且可以讀取它們以確定作業的狀態,並獲取指向包含結果的最終「FilledInDocument」對象的指針。

REST是關於創建,讀取,更新和銷燬對象的全部內容。如果您不能將您的流程建模爲CRUD數據庫,則它不是REST。這意味着您需要將模板存儲在服務器上。

儘管實現RPC over HTTP模型,然後提交模板和值,然後同步獲取響應 - 或者您指定的其他非REST模式之一,您可能會更好......因爲這是正是你想要的。

+0

我不同意「REST全部關於CRUD」。雖然看起來在CRUD(創建,讀取,更新,刪除)中有四個REST方法(GET,PUT,POST,DELETE)和四個操作,但聲稱操作是並行的,這是一個邏輯上的跳躍。請參閱[REST APIs必須由超文本驅動](http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven)和[Crud對於休息不好](http:// soa .dzone.com /新聞/ CRUD壞休息)。 – 2012-08-11 22:26:07

0

如果在存儲模板沒有價值,然後選擇2是最平安,但你知道有讓您的GET主體上降落的可能性。

不過,如果我是這個系統的用戶,我會覺得很浪費必須每次我想和值來填充它上傳模板。相反,將模板存儲並允許具有不同值的不同請求填充生成的文檔似乎更合適。

5

哇,所以這個答案迅速升級...

在過去一年左右的時間我已經嘗試通過書籍,郵件列表等出於某種原因,我決定,以獲得更好地瞭解REST的選擇你的問題作爲我所學到的東西的測試。

對不起:P


讓我們把這個整個例子一步簡單。不用擔心用戶上傳文件,我們會假設用戶只是傳遞一個字符串。所以,實際上,除了要替換的字符參數(鍵/值列表)外,他們還要傳遞一個字符串。稍後我們將處理文件上傳部分。

這是一個RESTful的方式,它不需要任何東西存儲在服務器上。我將使用一些HTML(儘管破碎,我會忽略像HEAD這樣的東西)作爲我的媒體類型,只是因爲它是相當知名的。

樣本解決方案

首先,用戶需要訪問我們的REST服務。

GET/

<body> 
    <a rel="http://example.com/rels/arguments" href="/arguments"> 
     Start Building Arguments 
    </a> 
</body> 

這基本上爲用戶提供了一種方式來真正開始對我們的服務進行交互。現在他們只有一個選項:使用鏈接來構建一組新的參數(最終將用於字符串替換方案中的名稱/值對)。所以用戶去那個鏈接。

GET /參數

<body> 
    <a rel="self" href="/arguments"/> 
    <form rel="http://example.com/rels/arguments" method="get" action="/arguments?{key}={value}"> 
     <input id="key" name="key" type="text"/> 
     <input id="value" name="value" type="text"/> 
    </form> 
    <form rel="http://example.com/rels/processed_string" action="/processed_string/{input_string}"> 
     <input id="input_string" name="input_string" /> 
    </form> 
</body> 

這給我們帶來的 「論據」 資源的實例。請注意,這不是一個JSON或XML文檔,它只返回鍵/值對的普通數據;它是超媒體。它包含控件,引導用戶接下來可以做的事情(有時指的是允許用戶「跟隨他們的鼻子」)。這個特定的URL(「/ arguments」)表示鍵/值對的空列表。如果我願意的話,我可以命名爲「/ empty_arguments」:這是一個例子,爲什麼從URL的角度考慮REST是愚蠢的:它實際上並不重要。

在這個新的HTML,爲用戶提供了他們可以瀏覽到三種不同的資源:

  1. 他們可以使用到「自我」導航到他們目前在相同的資源。
  2. 他們可以使用第一種形式導航到一個新資源,該資源表示一個參數列表,並使用它們在表單中指定的其他名稱/值組對。
  3. 他們可以使用第二種形式提供他們希望最終替換的字符串。

注意:您可能會注意到,第二種形式有一個奇怪的 「行動」 網址:

/arguments?{key}={value}

在這裏,我被騙了:我使用URI Templates。這使我可以指定參數將如何放置到URL上,而不是使用僅使用<input-name>=<input-value>的默認HTML方案。很顯然,爲了這個工作,用戶不能使用瀏覽器(因爲瀏覽器沒有實現這個功能):他們需要使用理解HTML模板的軟件。當然,我使用HTML作爲示例,您的REST服務可以使用某種支持URI模板規範定義的URI模板的XML。

無論如何,假設用戶想要添加他們的參數。用戶使用第一種形式(例如,用「作者」填寫「鍵」輸入,用「John Doe」填寫「價值」輸入)。這導致...

GET /參數?作者約翰=%20Doe

<body> 
    <a rel="self" href="/arguments?Author=John%20Doe"/> 
    <form rel="http://example.com/rels/arguments" method="get" action="/arguments?Author=John%20Doe&{key}={value}"> 
     <input id="key" name="key" type="text"/> 
     <input id="value" name="value" type="text"/> 
    </form> 
    <form rel="http://example.com/rels/processed_string" action="/processed_string/{input_string}?Author=John%20Doe"> 
     <input id="input_string" name="input_string" /> 
    </form> 
</body> 

現在這是一個全新的資源。您可以使用單個鍵/值對將它描述爲參數列表(鍵/值對):「作者」/「John Doe」。 HTML與以前幾乎相同,只是有一些變化:

  1. 「自我」鏈接現在指向當前資源URL(從「/ arguments」更改爲「/ arguments?Author = John%20Doe」
  2. 第一種形式的「動作」屬性現在有較長的網址,但我們再次使用URI模板,使我們能夠建立一個更大的URI。
  3. 第二種形式

用戶現在希望要添加一個「Date」參數,所以他們再次提交第一個表單,這次用「Date」鍵和一個值「2003-01-02」 。

GET /參數?作者約翰=%20Doe &日期= 2003-01-02

<body> 
    <a rel="self" href="/arguments?Author=John%20Doe&Date=2003-01-02"/> 
    <form rel="http://example.com/rels/arguments" method="get" action="/arguments?Author=John%20Doe&Date=2003-01-02&{key}={value}"> 
     <input id="key" name="key" type="text"/> 
     <input id="value" name="value" type="text"/> 
    </form> 
    <form rel="http://example.com/rels/processed_string" action="/processed_string/{input_string}?Author=John%20Doe"> 
     <input id="input_string" name="input_string" /> 
    </form> 
</body> 

最後,用戶準備處理他們的字符串,所以他們使用的第二種形式,並填寫「 input_string「變量。這又一次使用URI模板,從而將用戶帶到下一個資源。比方說,該字符串如下:

{Author} wrote some books in {Date}

的結果將是:

GET/processed_string /%7BAuthor%7D +寫+有些+書籍+在+%7BDate%7D作者? = John%20Doe & Date = 2003-01-02

<body> 
    <a rel="self" href="/processed_string/%7BAuthor%7D+wrote+some+books+in+%7BDate%7D?Author=John%20Doe&Date=2003-01-02"> 
    <span class="results">John Doe wrote some books in 2003-01-02</span> 
</body> 

PHEW!這是很多工作!但它是(AFAIC)RESTful,並且它滿足了不需要在服務器端實際存儲ANYTHING(包括參數列表或最終想要處理的字符串)的要求。

重要的事情要注意

有一點是這裏重要的是,我不只是在談論的URL。實際上,大部分時間我都在談論HTML。 HTML是超媒體,這是REST中被遺忘的很大一部分。所有那些聲稱他們是「寧靜的」,他們說「在這個URL上使用這些參數進行GET並在這個URL上使用類似這樣的文檔進行POST」的API並沒有實踐REST。羅伊菲爾丁(字面上wrote the book on RESTmade this observation himself

另一件需要注意的事情是,設置參數有點痛苦。在初始GET /到達服務的根目錄(你可以認爲它是「菜單」)之後,你需要再做5個GET調用才能建立你的參數資源來創建四個關鍵字的參數資源/值配對。這可以通過不使用HTML來緩解。例如,我已經在我的例子中使用了URI模板,沒有理由說HTML對REST來說不夠好。使用支持類似於表單的超媒體格式(如XML的一些派生),但能夠指定值的「映射」,您可以一次完成此操作。例如,我們可以使用我們的API能夠理解的「映射」輸入類型是什麼,所以長擴展HTML媒體類型,以允許其他所謂的「映射」輸入型...

的客戶,他們會能夠通過一個GET構建他們的參數資源。

在這一點上,你可能甚至不需要「參數」資源。你可以只直接跳到包含映射和實際字符串「processed_string」資源...

什麼文件上傳?

好吧,所以最初你提到文件上傳,以及如何得到這個,而不需要存儲文件。那麼,基本上,我們可以使用我們現有的示例,但用文件替換最後一步。

在這裏,我們基本上做同樣的事情和以前一樣,除了我們正在上傳文件。需要注意的是,現在我們暗示用戶(通過表單上的「method」屬性)他們應該執行POST而不是GET。請注意,儘管處處聽到POST是非安全的(它可能導致服務器發生更改),但是非冪等操作,沒有任何說它必須是服務器上的更改狀態。

最後,服務器可以返回新文件(甚至更好的辦法是返回一些超媒體或LOCATION標頭,並帶有到新文件的鏈接,但這需要存儲)。

最終評論

這只是一個拿這個具體的例子。雖然我希望你已經獲得某種見解,但我會提醒你接受這個福音。我敢肯定,我曾經說過一些事情並不是真正的「休息」。我計劃發佈這個問題並回答REST-Discuss Mailing List,看看別人對此有何評論。

我希望通過這個來表達一件主要的事情,那就是最簡單的解決方案可能就是使用RPC。畢竟,你最初嘗試使RESTful試圖完成什麼?如果你試圖告訴人們你完成了「REST」,請記住,大量的API聲稱自己是「RESTful」,它們真的只是RPC被名詞而不是動詞所僞裝的URL所僞裝。

如果是因爲您已經聽說了REST的一些好處,以及如何通過使您的API RESTful隱含地獲得這些好處,那麼不幸的事實是,除了URL以外,REST還有更多其他優點,以及您是否對其進行GET或POST 。超媒體扮演着重要角色。

最後,有時您會遇到問題,這意味着您可能會做SEEM非RESTful的事情。也許你需要做一個POST而不是一個GET,因爲這個URI(它有一個理論上無限的存儲量,但有很多技術限制)會變得太長。那麼,你需要做POST。也許

更多資源:

相關問題