How to handle nested resources in Web API ("REST") when not found? - rest

Let say I have a resource Person and on a person I have a nested resource SomeResource. Which status code should be returned and why in the following scenarios?
/Person/1/SomeResource (SomeResource does not exist)
/Person/1/SomeResource (Person does not exist)
I think that 404 should be used in both scenarios but not everyone agrees and I would like to know why. You could argue that Person is the underlying resource and SomeResource is just a "property" on that resource and the request to SomeResource should therefor return nothing in the first scenario but 404 in the second scenario. I think that might be an option, but I still like 404 more. Another scenario that I don't like at all is to return 500 with an error description, that was an alternative I heard in the discussion as well but that forces the consumer to program against exception which I don't like. 500 for me means that something went wrong and you can't really do anything about it.
The problem is that the argument was that you don't know why you got a 404 if you got it, was it because of that the Person didn't exist or because of that the SomeResource didn't exist.
UPDATE 1:
Maybe I should break out SomeResource to a separate resource like
/SomeResource/1
which returns a response like {data: {the data}, person: {person data}}, and this only returns 404 if both are missing but if the data is missing a 200 is returned with empty data.
UPDATE 2:
I think I figured out which status code to use and it is 400 for when the person is not existing since I at that point considering it a request you should never have done, that is, a bad request. When SomeResource is missing I would go for 404 since the Person did exist but the nested resource was missing.

It may be helpful to remember that a given URI is intended to identify at single "resource". Semantically, a URI structure does not support the concept of "nested" resources. It seems you have two resources: Person & SomeResource in your scenario where SomeResource has a relation of some sort with Person. You could try a structure like this to represent this relationship:
GET /person/1
{
name: "Some Value",
someResource: {
"Href": "http://yourSite.com/someresource/123",
"Title": "Get some resource for this specific person"
},
// other key/value pairs as appropriate...
}
This way you are not overloading the 400 & 404 with application specific meanings. If the client has received a valid Person result, it would simply invoke the SomeResource href and would receive the appropriate 404 or not depending on SomeResource 123 existing. If the Person URI does not exists, invoking it would appropriately return 404 since it does not exist.

Related

Return 403 or 201 if a field is not writable

What is the best practice for a response if the user tries to write to a field he or she is not allowed?
Imagine the user wants to create a resource, for example a pizza: POST /pizza
The body:
{
"name": "Hawaii",
"base": "tomato sauce",
"firstMain": "ham",
"secondMain": "pineapple",
"cheese": true
}
Problem is, you can't put secondMain on a pizza (because its pineapple). What's better? Return a 403 error with the message that field secondMain is not writable or return a 201 with the created pizza but without the secondMain?
What's the best practice for this problem? Didn't found anything on Google.
Returning a 403 with a proper error response would work best. Saying 201 but creating something different then what they originally wanted would probably lead to a unhappy customer. I know I'd be annoyed if my pizza didn't come with pineapple and that's what I ordered.
Really guess it varies on a case by case basis depending on your expected result and what your client is expecting to happen. Just make sure to specify in your documentation that extra data sent up with requests that isn't writable will throw an error.
etc
403 response: {error: {"secondMain": "unknown field", "exampleField": "expected but missing"}}

REST API Error code after POSTing resource with invalid FK

I'm designing a REST API which has a Banner resource that's related to another two resources: Placeholder and Page.
While the relationship with Placeholder can be null, a Banner must be related to a Page. The business rules define that Pages are always created independently. Then, for new Banner resources, the page does always exist and the page's id can be passed as a parameter. The same applies for the Placeholder, although this could null.
So, I decided that a Banner resource can be also created independently (instead of a nested resource) as follows:
POST https://api.example.com/banners
{
"name": "banner's name",
"page": "PAGE_ID",
"placeholder": "PLACEHOLDER_ID",
... other parameters
}
What error code should be returned by the API when provided page or placeholder does not exist?
I'm returning a HTTP 404, but it feels odd. I thought about 409, but this doesn't look like a conflict.
PD: If I used a nested URL as POST /pages/<page_id>/banners, the 404 makes sense for a non existent page, but it still have the same problem for placeholder.
Assuming that you want to create a banner resource using POST /banners and that banner resource has
a required page attribute which value must be an existing PAGE_ID
an optional placeholder attribute which value must be an existing PLACEHOLDER_ID
and a name and other properties which I assume must also be controlled
Returning a 404 on post /banners is not a good idea
The consumer may provide from none to all invalid properties. Following your idea that would give something like that:
If only page is invalid you would return a 404
If only placeholder is invalid you would return a 404
If page and placeholder are both invalid you would have to return a 404 indicating that both value are invalid
If other properties are invalid, you would probably return a 400 Bad Request.
If page and/or placeholder and some other properties are invalid, which status return? a 404 or 400?
It's a bit complex and inconsistent and therefore not really usable for the API's consumer.
A 400 Bad Request is a better solution for post /banners
The best way to handle this use case is to consider all possible errors in the provided resources as a basic Client Error and therefore use 400 Bad Request status. The body of the response will contain a description of each error for each invalid property.
But there's a cleaner solution with POST /pages/page_id/placeholders/placeholder_id/banners
The POST /pages/<page_id>/banners is almost a good idea, you only need to push it further.
It seems that a banner goes into a placeholder which is in a page. If it's true you can do a POST /pages/<page_id>/placeholders/<placeholder_id>/banners to create a banner.
If page_id is invalid you return a 404 (indicating 'page not found')
If page_id is valid but placeholder_id is invalid you return a 404 (indicating 'place holder not found')
If page_id and placeholder_id are valid but property in the banner is invalid you return a 400 Bad Request (indicating which values are invalid)

Structuring a RESTful service to respond when no results found

I'm building a RESTful service with Symfony2.
It has a search function which returns a search entity, the entity has an array of results.
If the user performs an improper search there are a few different messages I may need to send them. Thus, My thought on how to structure the response is:
For a good search:
{
"message": "OK",
"search": <insert search object here>
}
and for a bad search:
{
"message: "Please double check your search in such and such fashion"
}
Essentially, always sending a "message" but not always sending a search entity, as one will not have been created if their search failed in certain ways.
Then, I will always return a 200 response, even when their search criteria were off. Or, if there were no results.
Does this jive with the thinking behind REST, or should I be changing the response to a 404 or something?
Thanks!
I think it depends on how you want to structure your RESTful service. When you say If the user performs an improper search to me that sounds like the user is using bad syntax in the search or doing something else wrong, as opposed to a properly formatted search that simply returns no results.
If that's the case I think most REST services return 400 - bad request, or some other error code in the 400 range.
Also, I think most REST services would return the search entity in the response body.

'Best' practice for restful POST response

So nothing new here I am just trying to get some clarification and cannot seem to find any in other posts.
I am creating a new resource restulfully, say:
/books (POST)
with a body:
{
title: 'The Lion, the Witch and the Wardrobe',
author: 'C. S. Lewis'
}
I know that I should return a 201 (Created) with a Location header of the new resource:
Location: /books/12345
The question I cannot seem to answer for myself is what should the server return in the body.
I have often done this type of response:
{
id: 12345,
title: 'The Lion, the Witch and the Wardrobe',
author: 'C. S. Lewis'
}
I have done this for a couple reasons:
I have written api for front end frameworks like angularjs. In my
particular case I am using angular resources and I often need just
the id for the resource to locate it. If I did not return the id in
the response body I would need to parse it out of the Location
header.
In a GET of all books I usually return the entire object not just
the id. In this sense my client code does not have to differentiate
where to get the id from (location header or body).
Now I know I am really in the grey area here, but most people are saying that returning the entire resource is 'bad' practice. But what if the server changes/adds information to the resource. It definitely adds the id, but might also add other things like a timestamp. In the case that I do not return the entire resource, is it really better to do a POST, return the id, then have the client perform a GET to get the new resource.
Returning the new object fits with the REST principle of "Uniform Interface - Manipulation of resources through representations." The complete object is the representation of the new state of the object that was created.
There is a really excellent reference for API design, here: Best Practices for Designing a Pragmatic RESTful API
It includes an answer to your question here: Updates & creation should return a resource representation
It says:
To prevent an API consumer from having to hit the API again for an
updated representation, have the API return the updated (or created)
representation as part of the response.
Seems nicely pragmatic to me and it fits in with that REST principle I mentioned above.
Returning the whole object on an update would not seem very relevant, but I can hardly see why returning the whole object when it is created would be a bad practice in a normal use case. This would be useful at least to get the ID easily and to get the timestamps when relevant.
This is actually the default behavior got when scaffolding with Rails.
I really do not see any advantage to returning only the ID and doing a GET request after, to get the data you could have got with your initial POST.
Anyway as long as your API is consistent I think that you should choose the pattern that fits your needs the best. There is not any correct way of how to build a REST API, imo.
After a post I like to return something like this:
Response
.created(URI("/obj/$id"))
.entity(TheNewObj())
.build()
Status 201 - CREATED
Header Location - the location of the new object
Entity - the new object

Best practice for partial updates in a RESTful service

I am writing a RESTful service for a customer management system and I am trying to find the best practice for updating records partially. For example, I want the caller to be able to read the full record with a GET request. But for updating it only certain operations on the record are allowed, like change the status from ENABLED to DISABLED. (I have more complex scenarios than this)
I don't want the caller to submit the entire record with just the updated field for security reasons (it also feels like overkill).
Is there a recommended way of constructing the URIs? When reading the REST books RPC style calls seem to be frowned upon.
If the following call returns the full customer record for the customer with the id 123
GET /customer/123
<customer>
{lots of attributes}
<status>ENABLED</status>
{even more attributes}
</customer>
how should I update the status?
POST /customer/123/status
<status>DISABLED</status>
POST /customer/123/changeStatus
DISABLED
...
Update: To augment the question. How does one incorporate 'business logic calls' into a REST api? Is there an agreed way of doing this? Not all of the methods are CRUD by nature. Some are more complex, like 'sendEmailToCustomer(123)', 'mergeCustomers(123, 456)', 'countCustomers()'
POST /customer/123?cmd=sendEmail
POST /cmd/sendEmail?customerId=123
GET /customer/count
You basically have two options:
Use PATCH (but note that you have to define your own media type that specifies what will happen exactly)
Use POST to a sub resource and return 303 See Other with the Location header pointing to the main resource. The intention of the 303 is to tell the client: "I have performed your POST and the effect was that some other resource was updated. See Location header for which resource that was." POST/303 is intended for iterative additions to a resources to build up the state of some main resource and it is a perfect fit for partial updates.
You should use POST for partial updates.
To update fields for customer 123, make a POST to /customer/123.
If you want to update just the status, you could also PUT to /customer/123/status.
Generally, GET requests should not have any side effects, and PUT is for writing/replacing the entire resource.
This follows directly from HTTP, as seen here: http://en.wikipedia.org/wiki/HTTP_PUT#Request_methods
You should use PATCH for partial updates - either using json-patch documents (see https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-patch-08 or http://www.mnot.net/blog/2012/09/05/patch) or the XML patch framework (see https://www.rfc-editor.org/rfc/rfc5261). In my opinion though, json-patch is the best fit for your kind of business data.
PATCH with JSON/XML patch documents has very strait forward semantics for partial updates. If you start using POST, with modified copies of the original document, for partial updates you soon run into problems where you want missing values (or, rather, null values) to represent either "ignore this property" or "set this property to the empty value" - and that leads down a rabbit hole of hacked solutions that in the end will result in your own kind of patch format.
You can find a more in-depth answer here: http://soabits.blogspot.dk/2013/01/http-put-patch-or-post-partial-updates.html.
I am running into a similar problem. PUT on a sub-resource seems to work when you want to update only a single field. However, sometimes you want to update a bunch of things: Think of a web form representing the resource with option to change some entries. The user's submission of form should not result in a multiple PUTs.
Here are two solution that I can think of:
do a PUT with the entire resource. On the server-side, define the semantics that a PUT with the entire resource ignores all the values that haven't changed.
do a PUT with a partial resource. On the server-side, define the semantics of this to be a merge.
2 is just a bandwidth-optimization of 1. Sometimes 1 is the only option if the resource defines some fields are required fields (think proto buffers).
The problem with both these approaches is how to clear a field. You will have to define a special null value (especially for proto buffers since null values are not defined for proto buffers) that will cause clearing of the field.
Comments?
RFC 7396: JSON Merge Patch (published four years after the question was posted) describes the best practices for a PATCH in terms of the format and processing rules.
In a nutshell, you submit an HTTP PATCH to a target resource with the application/merge-patch+json MIME media type and a body representing only the parts that you want to be changed/added/removed and then follow the below processing rules.
Rules:
If the provided merge patch contains members that do not appear within the target, those members are added.
If the target does contain the member, the value is replaced.
Null values in the merge patch are given special meaning to indicate the removal of existing values in the target.
Example test cases that illustrate the rules above (as seen in the appendix of that RFC):
ORIGINAL PATCH RESULT
--------------------------------------------
{"a":"b"} {"a":"c"} {"a":"c"}
{"a":"b"} {"b":"c"} {"a":"b",
"b":"c"}
{"a":"b"} {"a":null} {}
{"a":"b", {"a":null} {"b":"c"}
"b":"c"}
{"a":["b"]} {"a":"c"} {"a":"c"}
{"a":"c"} {"a":["b"]} {"a":["b"]}
{"a": { {"a": { {"a": {
"b": "c"} "b": "d", "b": "d"
} "c": null} }
} }
{"a": [ {"a": [1]} {"a": [1]}
{"b":"c"}
]
}
["a","b"] ["c","d"] ["c","d"]
{"a":"b"} ["c"] ["c"]
{"a":"foo"} null null
{"a":"foo"} "bar" "bar"
{"e":null} {"a":1} {"e":null,
"a":1}
[1,2] {"a":"b", {"a":"b"}
"c":null}
{} {"a": {"a":
{"bb": {"bb":
{"ccc": {}}}
null}}}
For modifying the status I think a RESTful approach is to use a logical sub-resource which describes the status of the resources. This IMO is pretty useful and clean when you have a reduced set of statuses. It makes your API more expressive without forcing the existing operations for your customer resource.
Example:
POST /customer/active <-- Providing entity in the body a new customer
{
... // attributes here except status
}
The POST service should return the newly created customer with the id:
{
id:123,
... // the other fields here
}
The GET for the created resource would use the resource location:
GET /customer/123/active
A GET /customer/123/inactive should return 404
For the PUT operation, without providing a Json entity it will just update the status
PUT /customer/123/inactive <-- Deactivating an existing customer
Providing an entity will allow you to update the contents of the customer and update the status at the same time.
PUT /customer/123/inactive
{
... // entity fields here except id and status
}
You are creating a conceptual sub-resource for your customer resource. It is also consistent with Roy Fielding's definition of a resource: "...A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time..." In this case the conceptual mapping is active-customer to customer with status=ACTIVE.
Read operation:
GET /customer/123/active
GET /customer/123/inactive
If you make those calls one right after the other one of them must return status 404, the successful output may not include the status as it is implicit. Of course you can still use GET /customer/123?status=ACTIVE|INACTIVE to query the customer resource directly.
The DELETE operation is interesting as the semantics can be confusing. But you have the option of not publishing that operation for this conceptual resource, or use it in accordance with your business logic.
DELETE /customer/123/active
That one can take your customer to a DELETED/DISABLED status or to the opposite status (ACTIVE/INACTIVE).
Things to add to your augmented question. I think you can often perfectly design more complicated business actions. But you have to give away the method/procedure style of thinking and think more in resources and verbs.
mail sendings
POST /customers/123/mails
payload:
{from: x#x.com, subject: "foo", to: y#y.com}
The implementation of this resource + POST would then send out the mail. if necessary you could then offer something like /customer/123/outbox and then offer resource links to /customer/mails/{mailId}.
customer count
You could handle it like a search resource (including search metadata with paging and num-found info, which gives you the count of customers).
GET /customers
response payload:
{numFound: 1234, paging: {self:..., next:..., previous:...} customer: { ...} ....}
Use PUT for updating incomplete/partial resource.
You can accept jObject as parameter and parse its value to update the resource.
Below is the Java function which you can use as a reference :
public IHttpActionResult Put(int id, JObject partialObject) {
Dictionary < string, string > dictionaryObject = new Dictionary < string, string > ();
foreach(JProperty property in json.Properties()) {
dictionaryObject.Add(property.Name.ToString(), property.Value.ToString());
}
int id = Convert.ToInt32(dictionaryObject["id"]);
DateTime startTime = Convert.ToDateTime(orderInsert["AppointmentDateTime"]);
Boolean isGroup = Convert.ToBoolean(dictionaryObject["IsGroup"]);
//Call function to update resource
update(id, startTime, isGroup);
return Ok(appointmentModelList);
}
Check out http://www.odata.org/
It defines the MERGE method, so in your case it would be something like this:
MERGE /customer/123
<customer>
<status>DISABLED</status>
</customer>
Only the status property is updated and the other values are preserved.
Regarding your Update.
The concept of CRUD I believe has caused some confusion regarding API design. CRUD is a general low level concept for basic operations to perform on data, and HTTP verbs are just request methods (created 21 years ago) that may or may not map to a CRUD operation. In fact, try to find the presence of the CRUD acronym in the HTTP 1.0/1.1 specification.
A very well explained guide that applies a pragmatic convention can be found in the Google cloud platform API documentation. It describes the concepts behind the creation of a resource based API, one that emphasizes a big amount of resources over operations, and includes the use cases that you are describing. Although is a just a convention design for their product, I think it makes a lot of sense.
The base concept here (and one that produces a lot of confusion) is the mapping between "methods" and HTTP verbs. One thing is to define what "operations" (methods) your API will do over which types of resources (for example, get a list of customers, or send an email), and another are the HTTP verbs. There must be a definition of both, the methods and the verbs that you plan to use and a mapping between them.
It also says that, when an operation does not map exactly with a standard method (List, Get, Create, Update, Delete in this case), one may use "Custom methods", like BatchGet, which retrieves several objects based on several object id input, or SendEmail.
It doesn't matter. In terms of REST, you can't do a GET, because it's not cacheable, but it doesn't matter if you use POST or PATCH or PUT or whatever, and it doesn't matter what the URL looks like. If you're doing REST, what matters is that when you get a representation of your resource from the server, that representation is able give the client state transition options.
If your GET response had state transitions, the client just needs to know how to read them, and the server can change them if needed. Here an update is done using POST, but if it was changed to PATCH, or if the URL changes, the client still knows how to make an update:
{
"customer" :
{
},
"operations":
[
"update" :
{
"method": "POST",
"href": "https://server/customer/123/"
}]
}
You could go as far as to list required/optional parameters for the client to give back to you. It depends on the application.
As far as business operations, that might be a different resource linked to from the customer resource. If you want to send an email to the customer, maybe that service is it's own resource that you can POST to, so you might include the following operation in the customer resource:
"email":
{
"method": "POST",
"href": "http://server/emailservice/send?customer=1234"
}
Some good videos, and example of the presenter's REST architecture are these. Stormpath only uses GET/POST/DELETE, which is fine since REST has nothing to do with what operations you use or how URLs should look (except GETs should be cacheable):
https://www.youtube.com/watch?v=pspy1H6A3FM,
https://www.youtube.com/watch?v=5WXYw4J4QOU,
http://docs.stormpath.com/rest/quickstart/