Restful Design - Parent collection object in response when POSTing a resource - rest

Let's say we have a collection resource called shelf (of book resources) and we would like to POST a new book:
[POST] /shelves/{shelf-id}/books [request body -- a book]
I know that the response should be either empty with a reference to the newly created resource (201) or include the created resource (200).
Let's say the clients that are creating book resources, will need to show summary of the shelf the new book is added to. One solution should be making clients to first do a POST (let's call it Req#1 -- to create the new book), and then a GET (Req#2) on the shelf resource to get the summary.
What if we care a lot about efficiency and want to return the result of Req#2 implicitly when getting Req#1 on the server and save one request on the client side? Is it OK based on REST principles to return the parent collection resource information in the response when a resource is added to the collection?
Any alternative design?

It's 'OK' for REST design to return different resource states, but HTTP doesn't have a standard way to do this. If you uses the HAL format for you REST api, it does have a way to do embedding, so I suppose you could embed different resources to the response of a POST request.
Note that there's no standard I know of that suggests that the following statement is true: I know that the response should be either empty with a reference to the newly created resource (201) or include the created resource (200).
Anyway, what are you trying to solve? Is it really that expensive to do an extra HTTP request? Where do you base that concern on? What's expensive about it? Is it the latency of having to do an extra roundtrip?
If that's the case, you could consider using HTTP/2 push to push a new version of your parent resource. It's probably the most standards compliant way. If your server and client support this well, then this also means you can use this as a great standard mechanism to push things to clients because they might soon request it.

I know that the response should be either empty with a reference to the newly created resource (201) or include the created resource (200).
This isn't true. According to the spec:
The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field. The response SHOULD include an entity containing a list of resource characteristics and location(s) from which the user or user agent can choose the one most appropriate. The entity format is specified by the media type given in the Content-Type header field. The origin server MUST create the resource before returning the 201 status code.
In summary, use a 201 status response with information about the new resource. Please don't mix information about other resources with it. That is not RESTful, and apart from pedantry, it probably will make a messy API for very little benefit.

Related

ASP.NET Core Web API - PUT vs PATCH

I've been learning how to build an ASP.NET Core Web API using the official documentation. However, under the PUT section it says:
According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.
I know that POST is used to create a new resource and PUT is used to update a particular resource. But I cannot understand what is meant by "entire updated entity, not just the changes".
I cannot understand what is meant by "entire updated entity, not just the changes".
You should review the HTTP specification, which describes the semantics of PUT.
A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.
Representation here refers to the bytes that would appear as the payload of the GET request. For a web page, we're talking about the HTML. For a resouce that responds with application/json, we're talking about the entire json document.
In other words, if you want to create/edit a json document, and save it on the web server, then you use HTTP PUT, and the payload of the request should be the entire JSON document.
For cases where the JSON document is very big (much bigger than the HTTP headers) and the changes you are making are small, then you might instead choose to send the changes in a patch request, where the payload of the request is a patch document (probably JSON Patch or JSON Merge Patch
Now, here's the magic trick -- everybody on the web understands HTTP requests the same way. PUT always means PUT, PATCH always means PATCH. So you can use PUT and PATCH to make changes to things on the web that aren't really documents, but might instead be something else (like an entity).
That's pretty much the point of an HTTP API - it's a facade that (when seen from the outside) makes our service look like just another web server.
The fact that your resource is really rows in a database instead of a document on a file system is an implementation detail that is hidden behind the Web API.
Supposed you have a json Data like below
{
"Id":123,
"FirstName":"John",
"MiddleName":"Random",
"LastName":"Doe"
}
Suppose, you want to change middle name here. you want to remove it. You can use both put and patch to do so.
PUT
Here you've to send the whole new entity (the changed state of the json model) in your request. Though you're only changing the Middle name part, the full json data is being sent in the request payload
PUT /user?id=123
{
"Id":123,
"FirstName":"John",
"MiddleName":"", //Only this is being changed.
"LastName":"Doe"
}
PATCH
In this case, you can only send the diff between the old model and the new model, and that will be it. So, here, in this case, only the changes are being sent, not the whole updated entity
PATCH /user?id=123
{
"MiddleName":"", //Only this is being changed.
}
Using PATCH can be handy when you want to edit only a few properties of a huge object.

Am I deviating from REST pattern, if I allow my user to change resource identifier of the resource during PUT calls?

In my case I shall allow the user to update the resource using a code in the url (ex:apidomain/{code}) and can also change the code by passing it inside the model.
Am I deviating from REST pattern, if I allow my user to change resource identifier of the resource during PUT calls?
HTTP PUT means "put the body of my request here", where the URL at which you make the request is where to put the entity. If you PUT a resource somewhere, you should be able to GET it again.
If the content of the request means that the resource will not be found at the URL you just PUT it at, you've broken one of the HTTP constraints.
I can think of a couple of options to handle this scenario which would all fit within HTTP's constraints:
Make it so that the URL of the resource is immutable. The "real" ID of any resource in a RESTful system is its URL. If you want to have an ID which is mutable, make it a surrogate key supported by an immutable identifier which is used to build the URL, or just make the URL the primary key.
Remove the ID of the entity from its representation (so there can be no confusion around identifiers) and perform a PUT of the resource to its new URL. The PUT should contain enough information to recognise the resource already exists at a previous location and to internally perform a "relocate" by changing the relevant ID.
DELETE the first resource and PUT the resource with its new ID in its new location. You might be able to track some history between the two internally, if required.
However you decide to perform a "relocation" of a resource, you should make it so anybody attempting to GET the old resource should receive a 301 Moved Permanently response, which should include the new location of the resource.

Should I use a POST request on /resources/ or PUT request on /resources/id/ to create a new object?

What's the RESTful way to create an object?
Should I use POST on the /resources/ URI and return the URI to the newly created resource in the response or should I use PUT on the /resources/id/ URI?
A GET request for /resources/id/ would surely return a 404 but should PUT return a 404 as well?
Should both methods be used to create a new object?
Generally, you will use either or both depending on whether or not you want the client (and therefore the user) to define the URI or not. If the client POSTs to resources/ then the server gets to determine the URI for the resource. If the client PUTs to resources/{id}/ then the client is determining the URI for the resource.
One exception is if creation involves links, states, and other items that are not then properly considered part of the resource--you generally cannot PUT these extra "constructor args" if you will, since they are not part of the resource state. Instead, you must POST in that case.
Even if you use POST for creation, you still might then want to expose PUT for updates. It depends on the resource.
If you don't allow a PUT to create then yes, you should return 404 in that situation.

How to edit a resource?

Pardon the simple question, but it seems most searches try to tell me which methods are designed for what actions. Eg, create & edit is PUT, create from plural (articles) is POST, and so on. (If you disagree with this, i was just using it as an example. :)
With that said, how do you initiate a resource edit? To create a resource, with a known url you preform a GET on an non-existing URL. Eg, GET:mysite/resource_one. This then returns a form, and the form submits a PUT to the same address and bam, the resource is created.
Now how do you edit that same resource? With 4 Methods, designed for CRUD, i am having issues because i can only seem to think of one way. To go to a new resource. Eg, GET:mysite/resource_one/edit. This then presents a form with existing data, you edit it, and then the data is submitted to GET:mysite/resource_one. This seems odd to me in a system that seems to be designed to allow full CRUD to be preformed on a resource, without leaving said resource.
So.. what is the proper method? I mean, if GET:mysite/resource_one/edit is right, then why not GET:mysite/resource_one/delete, GET:mysite/resource_two/create, and so on..
Replies much appreciated!
The URL always represents the resource, not the action. Thus, while mysite/resource_one/edit might be a proper URL to a page that initiates editing a resource, it's not a part of the REST API itself, it's part of the web app that uses that REST API to manipulate that resource. Moreover, in that example mysite/resource_one would be a confusing representation of the resource.
To create a new resource, you use POST on the parent resource, with the body of the request containing the data for the new resource. The response contains the URL for the newly created resource.
To update an existing resource, you use PUT on the resource URL, with the body of the request containing either full or partial update of the resource data.

How do you implement resource "edit" forms in a RESTful way?

We are trying to implement a REST API for an application we have now. We want to expose read/write capabilities for various resources using the REST API. How do we implement the "form" part of this? I get how to expose "read" of our data by creating RESTful URLs that essentially function as method calls and return the data:
GET /restapi/myobject?param=object-id-maybe
...and an XML document representing some data structure is returned. Fine.
But, normally, in a web application, an "edit" would involve two requests: one to load the current version of the resources and populate the form with that data, and one to post the modified data back.
But I don't get how you would do the same thing with HTTP methods that REST is sort of mapped to. It's a PUT, right? Can someone explain this?
(Additional consideration: The UI would be primarily done with AJAX)
--
Update: That definitely helps. But, I am still a bit confused about the server side? Obviously, I am not simply dealing with files here. On the server, the code that answers the requests should be filtering the request method to determine what to do with it? Is that the "switch" between reads and writes?
There are many different alternatives you can use. A good solution is provided at the microformats wiki and has also been referenced by the RESTful JSON crew. As close as you can get to a standard, really.
Operate on a Record
GET /people/1
return the first record
DELETE /people/1
destroy the first record
POST /people/1?_method=DELETE
alias for DELETE, to compensate for browser limitations
GET /people/1/edit
return a form to edit the first record
PUT /people/1
submit fields for updating the first record
POST /people/1?_method=PUT
alias for PUT, to compensate for browser limitations
I think you need to separate data services from web UI. When providing data services, a RESTful system is entirely appropriate, including the use of verbs that browsers can't support (like PUT and DELETE).
When describing a UI, I think most people confuse "RESTful" with "nice, predictable URLs". I wouldn't be all that worried about a purely RESTful URL syntax when you're describing web UI.
If you're submitting the data via plain HTML, you're restricted to doing a POST based form. The URI that the POST request is sent to should not be the URI for the resource being modified. You should either POST to a collection resource that ADDs a newly created resource each time (with the URI for the new resource in the Location header and a 202 status code) or POST to an updater resource that updates a resource with a supplied URI in the request's content (or custom header).
If you're using an XmlHttpRequest object, you can set the method to PUT and submit the data to the resource's URI. This can also work with empty forms if the server supplies a valid URI for the yet-nonexistent resource. The first PUT would create the resource (returning 202). Subsequent PUTs will either do nothing if it's the same data or modify the existing resource (in either case a 200 is returned unless an error occurs).
The load should just be a normal GET request, and the saving of new data should be a POST to the URL which currently has the data...
For example, load the current data from http://www.example.com/record/matt-s-example and then, change the data, and POST back to the same URL with the new data.
A PUT request could be used when creating a new record (i.e. PUT the data at a URL which doesn't currently exist), but in practice just POSTing is probably a better approach to get started with.