Handling CRUD on child objects with RESTful

If given the following xml request sent to a RESTful API endpoint called /catalog via a PUT (Intent to update catalog).

If the user provides additional <book> s that don't exist at that point in the catalog in the request should the endpoint "Create" them? or should they be ignored and a different endpoint perhaps /books be used to create them.

<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
   <book id="bk103">
      <author>Corets, Eva</author>
      <title>Maeve Ascendant</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-11-17</publish_date>
      <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
   </book>
   <book id="bk104">
      <author>Corets, Eva</author>
      <title>Oberon's Legacy</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2001-03-10</publish_date>
      <description>In post-apocalypse England, the mysterious 
      agent known only as Oberon helps to create a new life 
      for the inhabitants of London. Sequel to Maeve 
      Ascendant.</description>
   </book>
   <book id="bk105">
      <author>Corets, Eva</author>
      <title>The Sundered Grail</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2001-09-10</publish_date>
      <description>The two daughters of Maeve, half-sisters, 
      battle one another for control of England. Sequel to 
      Oberon's Legacy.</description>
   </book>
   <book id="bk106">
      <author>Randall, Cynthia</author>
      <title>Lover Birds</title>
      <genre>Romance</genre>
      <price>4.95</price>
      <publish_date>2000-09-02</publish_date>
      <description>When Carla meets Paul at an ornithology 
      conference, tempers fly as feathers get ruffled.</description>
   </book>
   <book id="bk107">
      <author>Thurman, Paula</author>
      <title>Splish Splash</title>
      <genre>Romance</genre>
      <price>4.95</price>
      <publish_date>2000-11-02</publish_date>
      <description>A deep sea diver finds true love twenty 
      thousand leagues beneath the sea.</description>
   </book>
   <book id="bk108">
      <author>Knorr, Stefan</author>
      <title>Creepy Crawlies</title>
      <genre>Horror</genre>
      <price>4.95</price>
      <publish_date>2000-12-06</publish_date>
      <description>An anthology of horror stories about roaches,
      centipedes, scorpions  and other insects.</description>
   </book>
   <book id="bk109">
      <author>Kress, Peter</author>
      <title>Paradox Lost</title>
      <genre>Science Fiction</genre>
      <price>6.95</price>
      <publish_date>2000-11-02</publish_date>
      <description>After an inadvertant trip through a Heisenberg
      Uncertainty Device, James Salway discovers the problems 
      of being quantum.</description>
   </book>
   <book id="bk110">
      <author>O'Brien, Tim</author>
      <title>Microsoft .NET: The Programming Bible</title>
      <genre>Computer</genre>
      <price>36.95</price>
      <publish_date>2000-12-09</publish_date>
      <description>Microsoft's .NET initiative is explored in 
      detail in this deep programmer's reference.</description>
   </book>
   <book id="bk111">
      <author>O'Brien, Tim</author>
      <title>MSXML3: A Comprehensive Guide</title>
      <genre>Computer</genre>
      <price>36.95</price>
      <publish_date>2000-12-01</publish_date>
      <description>The Microsoft MSXML3 parser is covered in 
      detail, with attention to XML DOM interfaces, XSLT processing, 
      SAX and more.</description>
   </book>
   <book id="bk112">
      <author>Galos, Mike</author>
      <title>Visual Studio 7: A Comprehensive Guide</title>
      <genre>Computer</genre>
      <price>49.95</price>
      <publish_date>2001-04-16</publish_date>
      <description>Microsoft Visual Studio 7 is explored in depth,
      looking at how Visual Basic, Visual C++, C#, and ASP+ are 
      integrated into a comprehensive development 
      environment.</description>
   </book>
</catalog>

I am finding a lot on SO that talks about PUT vs POST and best practices for doing CRUD operations on a root object but I've spent the night trying to find information around how child objects should be handled.

According to http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html it isn't clear to me if this applies to child objects?

9.6 PUT

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST NOT ignore any Content-* (eg Content-Range) headers that it does not understand or implement and MUST return a 501 (Not Implemented) response in such cases.

From my understanding of REST, books are resources and should be handled through their own endpoint and an update to the catalog should only be used to add existing books to a catalog, not create them.

So in this scenario a book that does not exist would be ignored/not added to the catalog until a create request is submitted to create the book.

This would mean the user would send a POST /book to create the book, followed by a PUT to /catalog with the book in the request to add it to the catalog.


You're right. You have two different resources here. One is named Books and the other is named Catalogs. You must design two different URIs to address each one. So in this scenario, I'd create two different resources to handle this problem. The first resource would be named as /catalogs and you must build it to receive only the book ID (one or more) that someone wants to associate with this catalog. You'll have:

Endpoint -> https://yourapi.com/catalogs

POST to https://yourapi.com/catalogs --> creates a new catalog.
PUT to https://yourapi.com/catalogs/1 --> updates the catalog with ID = 1.
PUT to https://yourapi.com/catalogs/2 where id 2 doesn't exist --> creates a new catalog with id=2

You have to send the XML below to the endpoint pointed above.

<?xml version="1.0"?>
<catalog>
    <book id="bk101"/>
    <book id="bk102"/>
    <book id="bk103"/>
    <book id="bk104"/>
<catalog>

The second resource should be /books and you must use it to create, delete, update and list books. Once you've created a book, then you can associate it with a catalog. You shouldn't use the resource Catalogs to create a Book that way. To my mind, it doesn't make sense.


What you are trying to do is a bulk/batch update. Afaik. we don't have consensus how to do that. There are many issues here:

  • PUT should be used by updating the whole resource. Since the resource is /catalog (so every single book in your storage) here, you have to give a representation of the whole catalog. You should consider PATCH instead, which can be used for partial update.
  • PUT is idempotent. So if you send a PUT twice it should not have any side effect. That's why you can use PUT for creation only if the users give the id of the new resources. (Otherwise you would create the new resource twice.) PATCH is not idempotent, so 2:0 to PATCH.
  • You can find a description about PATCH here: PATCH Method for HTTP.

    With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version. The PATCH method affects the resource identified by the Request-URI, and it also MAY have side effects on other resources; ie, new resources may be created, or existing ones modified, by the application of a PATCH.

    So PATCH /catalog and your XML would be okay. You can decide whether you allow your users to give the id of the new resources, or you can generate it on server side.

    Ofc. you have alternatives, for example you can send a book collection with POST /catalog , so multiple book resources will be created. You can use PUT /catalog/?id="bk112,bk113,..." to update a specific collection of books. Another alternative to create everything one by one, as you already mentioned.

    Be aware that we are talking about hyperlinks ( METHOD /resource-id?query <data /> + link metadata: eg link relation ). So you should consider to add links to your resource representations you return by a GET and probably use a hypermedia format as well eg HAL+XML or ATOM+XML.

    链接地址: http://www.djcxy.com/p/41350.html

    上一篇: 使用哪种HTTP方法:PUT或DELETE?

    下一篇: 使用RESTful处理子对象上的CRUD