2012-03-07 38 views
2

我正在構建一個API,並且正在努力處理髮布和更新資源的最佳方法。目前,用戶將使用XML將數據發佈到產品資源。我使用xsd文件驗證這個XML。這很好,但意味着用戶想要更新一個字段必須發佈與產品有關的所有字段。這是預期的還是我應該以其他方式做這個?構建RESTful API - 處理POST請求和驗證

我有另一個資源,將需要「狀態」或「派遣」更新,但只會更新一個或另一個,並永遠不會在同一時間。因此,我是否會以與產品資源相同的方式構建該產品,並且要求即使只更新一個產品領域,或者將這些產品作爲兩個單獨的資源進行更新,也要求他們總是發佈兩個領域?

回答

2

您可以另一種方式處理更新。第一個問題是您的客戶如何知道如何更新資源?如果他們正在帶外收到這些信息,那麼您不會執行REST。通過在帶內包含更新信息,它可以更明確地進行更新,從而爲您提供更大的自由度和靈活性。例如,product資源可以按照如下

<product href="/products/123" 
    name="iPad 64GB + 4G" 
    price="829.00"> 
    <description>It's cool, ya</description> 
    <update href="/products/123" method="PUT"> 
     <name type="xs:string" cardinality="optional"/> 
     <price type="xs:decimal" cardinality="optional"/> 
     <description type="xs:string" cardinality="optional"/> 
    </update> 
    ... you could have a delete form here as well ... 
</person> 

同時表示,該products集合可以表示爲

<people href="/products"> 
    ... the first set of items in the collection and pagination links could go here ... 
    <create href="/product" method="POST"> 
     <name type="xs:string" cardinality="required"/> 
     <price type="xs:decimal" cardinality="required"/> 
     <description type="xs:string" cardinality="required"/> 
    </create> 
</people> 

通知的參數的基數是如何更新和創造之間的不同。

在更換整個資源狀態PUT方面,認爲它是這樣的:當我更新product只有指定pricenamedescription默認其現有的值,然後將整個資源進行更新。我們唯一需要做的就是在我們的媒體類型中明確地定義這個邏輯。

從你描述一下,您目前擁有的東西,可能沿着

<product href="/products/123" 
    name="iPad 64GB + 4G" 
    price="829.00"> 
    <description>It's cool, ya</description> 
    <update href="/products/123" method="PUT"> 
     <product type="my:product" cardinality="required"/> 
    </update> 
    ... you could have a delete form here as well ... 
</person> 


<people href="/products"> 
    ... the first set of items in the collection and pagination links could go here ... 
    <create href="/product" method="POST"> 
     <product type="my:product" cardinality="required"/> 
    </create> 
</people> 

行這不是壞的每說,它只是更新樣,吸吮表示,是因爲你」我必須包括所有的領域。你是對的,覺得這是錯誤的,並質疑它。

此外,我強烈建議您不要使用XSD來驗證請求。除非XSD的設計非常謹慎,否則它會在您的客戶端和您的API之間創建一個緊密的耦合,這會迫使您同時或按特定順序(例如,服務器,然後客戶端)更新它們。改爲看看Schematron。現在

,在order,將有一張statusdispatch細節,認爲order資源作爲一個小狀態機的方面。它可能看起來像這樣:

Start ----> Received ----> Processed -------> Dispatched ------> End 
       |    |        ^
       |    V         | 
       ----------> Cancelled ------------------------------ 

因此,創建訂單時,會自動將其狀態設置爲接收狀態。從那裏它可以被處理或取消,並且可以從處理中被派遣或取消。這個想法是通過資源中提供的形式和鏈接來表示過渡。在此基礎上,這裏是我們如何能夠代表order,對於各種狀態

接收(從客戶的角度來看):

<order href="/orders/123" status="received"> 
    ... order details go here ... 
    <cancel href="/orders/123" method="delete"/> 
</order> 

收到(從員工的角度來看):

<order href="/orders/123" status="received"> 
    ... order details go here ... 
    <process href="/orders/123" method="put"> 
     ... whatever details need to be submitted at the same time ... 
    </process> 
</order> 

加工(從客戶的角度)

<order href="/orders/123" status="processed"> 
    ... order details go here ... 
    <cancel href="/orders/123" method="delete"/> 
</order> 

處理(從員工的角度來看):

<order href="/orders/123" status="processed"> 
    ... order details go here ... 
    <dispatch href="/orders/123" method="POST"> 
     <company type="xs:string" cardinality="required"/> 
     <con-note type="xs:string" cardinality="required"/> 
     <tracking type="xs:anyURI" cardinality="optional"/> 
     ... whatever details need to be submitted at the same time ... 
    </dispatch> 
</order> 

調度(從客戶和員工的角度)

<order href="/orders/123" status="dispatched"> 
    ... order details go here ... 
    <shipping-details href="/order/123/shipping"> 
</order> 

取消(從客戶和員工的角度)

<order href="/orders/123" status="cancelled"> 
    ... order details go here ... 
</order> 

的不同狀態基於那裏的權限將轉換呈現給不同的用戶。員工無法取消訂單,同樣,客戶也無法處理或派送訂單。根據訂單的當前狀態,只顯示允許的狀態轉換。

+0

這和我剛開始的時候完全不一樣,我不得不重新思考一下。非常感謝您的幫助和示例。 – LeeTee 2012-03-08 11:54:31

1

通過POST,您可以靈活定義您爲給定資源定義的狀態。 POST可以是一種全面的方法。如果您使用PUT方法,那麼您將需要替換整個資源狀態,因爲HTTP規範將此定義爲正確的行爲。實際上,您可以爲狀態創建單獨的資源並使用它們自己的GET/POST/PUT/DELETE行爲分配來表示您描述的用例。

+0

所以我做得正確呢? – LeeTee 2012-03-07 14:54:08

+0

是的,我會去兩個單獨的資源路由,因爲它更適合這些字段的實際使用。 – 2012-03-07 14:57:12