0

I have a resource which is essentially a simple CRUD document which has a small twist in that it can be "switched" into a "synchronized" state where-in instead of using it's own current values it now returns the values of a "parent" document that it is now synchronized with.

I am trying to find a RESTful way to modeling this. The resource has a property which indicates this state Synchronzied = true/false and a ParentId property to indicate which resource it is synced with.

One option is to just allow this to be changed during the PUT updates but that feels somehow incorrect as this isn't a part of the document but in some respect is metadata about the document. I've also considered a POST /document/{id}/synchronized request where the requested state is passed as an argument.

Neither feels quite right though. The first feel a bit awkward because it feels as if I'm parsing the submitted data for just one value, the rest are essentially discarded if we are synchronizing. In the second case it feels wrong to be creating a nested resource just for one property.

Chris Nicola
  • 14,384
  • 6
  • 47
  • 61
  • If I understand correctly, it seems that "switching" the state is not in line with REST in that it isn't the same resource anymore. However, if the resource isn't transformed into a new resource and you want to be able to access both formats, I'd definitely go with content type negotiation since you're simply representing the resource differently and not creating a new one. – Brenden Nov 25 '13 at 20:00

3 Answers3

1

You might consider, in response to a GET on a synchronized resource, returning 302/303 with a Location header set to the parent resource. But then allow a PUT on that same synchronized URI to replace the redirect with the transferred entity, which would then be returned in subsequent GET responses. If you wished to allow clients to switch an entity back to a synchronized state, you could do so by POSTing to the child URI a request body that contains the URI of the desired parent. You may even find serendipitous use cases by allowing the client to POST any URI, not just the id of a small set of known parents.

GET /child
    200 OK
    {foo: bar}

POST /child
{parent: /some/other}
    200 OK

GET /child
    302/303
    Location: /some/other

PUT /child
{foo: baz}
    201 Created

GET /child
    200 OK
    {foo: baz}
fumanchu
  • 14,419
  • 6
  • 31
  • 36
1

One solution here is to have two different resource types – full documents and slave documents – distinguished by MIME type. For example, you could have application/vnd.mysite.document for the full document and application/vnd.mysite.documentlink+json when you’re just linking to another document.

To make a slave document:

PUT /document/1234
Content-Type: application/vnd.mysite.documentlink+json

{"parent": "/document/1"}

To make a full document:

PUT /document/1234
Content-Type: application/vnd.mysite.document

Hello, I am a document full of stuff.

Then you can respond to GET requests by returning the document or a 303 (See Other) redirect to the parent.

dhwthompson
  • 2,501
  • 1
  • 15
  • 11
  • Yes this is very similar to the direction I'm thinking of going soon. It will require a fair bit of refactoring though but I think this is the ideal approach. Though I think I will avoid custom mimetypes and just stick with plain JSON for now. – Chris Nicola Dec 30 '11 at 21:27
0

You've looked at most of the common options, however consider using the HTTP PATCH method. I have used it successfully via AJAX on both Firefox and Chrome. The PATCH method specifies a set of changes to be applied to a document, rather than replacement of the entire document (via PUT).

(If you want to only retrieve part of a document, consider specifying a Range header with GET. You will need to define something other than a byte range to deal with XML or JSON documents -- see details on range units.)

Obviously, both of these solutions assume a willing client and server -- if you can't support the API on both ends of the request, you won't have much success with either.

Community
  • 1
  • 1
toddsundsted
  • 6,225
  • 2
  • 21
  • 13