Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REST resource representation with links, compatible with PUT and GET [closed]

Tags:

rest

api

I have been asked to design and implement a RESTful API, and have been researching best practices, but so far have only a woolly concept about resource representations. Most of the available examples I found seem to focus heavily on API clients that walk connected structures using a series of GETs.

I have looked at:

http://www.restapitutorial.com/media/RESTful_Best_Practices-v1_1.pdf

http://www.youtube.com/watch?v=HW9wWZHWhnI

amongst other online resources (I am limited to 2 links sorry cannot list them all). They are all great, but don't really address my design question.

Most of the best practice documents suggest two things that to me look slightly in conflict:

1) REST service should represent data relationships as links between resources

2) A "PUT" request from a client should be a full representation, identical in form to the representation seen on the server.

The trouble from my point of view is that the links, and perhaps quite a few other properties in a typical resource, are read-only, so cannot be updated. The server apparanetly shoudl expect them as-is, and return an error if it thinks the client is trying to update them. In fact, when I look at a typical resource represented in JSON, the majority of it is data that logically cannot/should not be replaced. E.g.

{
 "link": { "rel":"self", "href":"http://example/project/12345" },
 "team": {
    "link": { "rel":"self", "href":"http://example/project/12345/team" },
    "title": "The project team"
  },
  "title": "The Big Project"
}

Here at best only the two title texts would be writable to a client on this resource (team membership might be alterable via the team link).

So should I be requiring that a PUT includes all the "link" elements exactly as-is, which are purely logical and read-only (note in the example, the team cannot be re-linked, as the resource defines it as the team for the project - in this case that could be changed, but for many resource types with stricter containership, this doesn't apply)?

Are there standard patterns or anti-patterns for representing resources in REST with many links? I'm not being asked for a specific REST variant, such as HATEOAS though my inclination is to aim at theoretical "correctness" where possible. In other words, if "official" REST would be to expect clients to PUT the whole resource, links and all, then that is probably what I will do.

Some examples of real world complex non-leaf REST resources that support GET and PUT, and thus have to work with this issue, would be really appreciated. When I search I get lots of opinion, and many examples showing how nicely GET works . . . but so far I have not seen a well-documented example showing a PUT to anything but a trivial leaf resource (i.e. one that does not contain any links, except perhaps a self reference).

like image 545
Neil Slater Avatar asked Oct 06 '22 06:10

Neil Slater


2 Answers

Basically, a GET request will return a resource serialised into a defined format, and metadata about that resource (which together constitute a representation of the resource). When you PUT a representation back, it does not need to contain the metadata, nor does it need to be in the same format as the original (or any subsequent) GET request. The server will then update the resource based on the representation you provided.

An example from HTML is the <head> and <body> elements, which provide metadata about the resource, and the resource representation; and the text/html and application/x-www-form-urlencoded content types, which transfer resource representations in two different formats, the former with metadata, the latter without. When you GET the resource after POSTing to it, you don't expect to receive application/x-www-form-urlencoded-formatted data!

I am not sure what you mean by "REST variant". There is only one REST. If you are referring to other HTTP-based APIs, please don't call them REST. For further details on API styles, see Classification of HTTP-based APIs.

Lastly, you ask for examples of non-leaf PUT requests. I am not sure exactly what you mean by non-leaf, as I can think of two types:

  1. Collections
  2. Sub-resources

Collections Lets say you have a car catalogue, available at /cars. If you decided you wanted to erase all your cars, you could either do DELETE /cars/1, DELETE /cars/2 ... etc. or you might choose PUT /cars with an empty body or an array with no contents. The latter would obviously be a lot more efficient.

Sub-resources Continuing this theme, lets say that there is a car, /cars/1 which is represented thus:

{
  "model":"Model-T",
  "mfgr":"Ford",
  "colour":"black"
}

Now, you may wish to allow these fields to be accessed by URLs such as /cars/1/mfgr which would return Ford or perhaps {"mfgr":"Ford"}. Now the URL /cars/1 represents a non-leaf resource. However there is still no problem in PUTting a new representation to the URL. This would therefore update the sub-resource URLs' values too.

Lastly, you may want to take a look at the HAL format for transmitting hypertext via JSON.

like image 186
Nicholas Shanks Avatar answered Oct 13 '22 10:10

Nicholas Shanks


You should put a "complete" representation as your media type defines it. If you're designing your own media type, your specification should define which parts are intended to be mutable and which are intended to be immutable. The Shoji Catalog Protocol, for example, defines a "body" member that is intended to contain the mutable data:

In general, when a body member is present, processors SHOULD expect the values present within the body to be potentially mutable (via an HTTP PUT or POST, for example) and SHOULD expect any values outside the body member to be immutable; that is, (potentially) writable on insert but not on update. Servers are free, of course to allow or disallow mutability of any part of the resource. But the presence of a "body" member carries with it strong hints regarding the mutability of data both within and without that member.

This isn't a standard (although it's so obviously useful to me that I'd like it to become one (wink)). Note that servers are free to do whatever they wish with the representation a client sends; the strongest requirement for any HTTP server is that it attempt to perform the intention of the client (if able and allowed). How and to what extent it does that is really a concern for your particular application, which is why you're not finding much in any specs about it.

In practice, I haven't found it useful for the server to validate the links or other immutable parts of a representation; they're simply ignored. That can lead to clients deciding they can omit such. Again, in practice I haven't found that to be a problem.

like image 37
fumanchu Avatar answered Oct 13 '22 11:10

fumanchu