What HTTP error code for failure to create a new resource because a parent entity is gone - api

Say i have an API exposing two related resources, Company which has many Employees.
Say I create a new Company: POST http://domain/api/company/ which returns something like http://domain/api/company/123.
If company/123 is removed from the system (say by a DELETE) then GET http://domain/api/company/123 could return HTTP response code 410 (Gone).
My question is this. If I now try to create an Employee under Company/123 by doing POST http://domain/api/employees/ (with companyId set to 123 in the request body) what HTTP response code should be sent back by the server due to the invalid request?
E.g. the request is correctly formated, but there is a logical error due to the fact that company 123 is gone.
Internal Server Error 500?

Not a 500, because there is no problem with the server.
I would suggest 409 Conflict.
From the RFC:
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required. Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.
It doesn't exactly match your case, but it is very close IMHO.
For example the server could tell you the parent resource does not exist for you to post to, and you can "resubmit" the employee to a different company. :)

I ran in the same situation here.
After evaluating the HTTP Status code options, it appears to me the best option is to return a 424 Failed Dependency
The 424 (Failed Dependency) status code means that the method could
not be performed on the resource because the requested action
depended on another action and that action failed. For example, if a
command in a PROPPATCH method fails, then, at minimum, the rest of
the commands will also fail with 424 (Failed Dependency).
From RFC

Related

HTTP code for an error in processing a request

Let's say we have an HTTP request made by the client. The endpoint exists and is accessible by the client (this rules out 401, 403, 404 and 405). The request payload is valid (this rules out 400). The server is alive and well, and is able to handle the request and return a response (this rules out 5xx).
The error arises within the processing of the request. Examples of such errors may include:
Business validation error.
Querying for an entity in a database that does not exist. Assume that the database lookup is only one part of the request processing pipeline (e.g. not the client request itself).
The server that handles the original client request makes an internal HTTP request that fails. In this case, the handling server is alive and well, while the internal HTTP request may return a 5xx. Assume that the internal HTTP request is only one part of the request processing pipeline (e.g. not the client request itself).
What is the appropriate HTTP code to assign for these responses?
I've seen API docs use 402 (Stripe) and 422 (PayPal), though I haven't come across anything definitive.
Thoughts from the community welcome! Thanks.
What is the appropriate HTTP code to assign for these responses?
Two important ideas
First - your API is a facade, designed to make it look your service/business logic/etc is just another HTTP compliant document store (aka the "uniform interface" constraint). For the purposes of designing your responses, the specific nature of your resources and the implementation details are not significant.
Second - the important point of a status code is how that status code will be understood by general purpose components (think browsers, web caches, reverse proxies, spiders...). We're trying to help these components broadly categorize the nature of the response. (This is one reason why there are relatively few codes in the 5xx class; there just isn't much that a general purpose component can do differently if the servers handling of the request fails).
And here's the thing: if the general purpose handling of two status codes isn't significantly different. 403 Forbidden and 409 Conflict have different semantics associated with them, but the differences in the standardized handling of those codes, if any, are pretty subtle.
You should make an effort to get 4xx vs 5xx right. It's often less important to precisely identify which 4xx code to use.
Business validation error
Common choices here would be 409 Conflict (your request is not consistent with my copy of the data), or 403 Forbidden (I understood your request, but I'm not going to fulfill it).
If the problem is the data within the request itself (ie: somebody submitted the wrong form) you are more likely to see a 422 Unprocessable Entity (yes, I accept application/json, but not this application/json).
Querying for an entity in a database that does not exist.
The implementation details don't matter; can you trace the problem back to the HTTP request?
If the problem traces back to the URI (we parse the target uri for some information, and use that information to lookup information in our data store), then 404 Not Found is often a good choice. If the problem traces back to the body of the request (we expected some option in the form to match an entry in our enumerated list, but it doesn't), then 409 Conflict is reasonable.
If the server's data is flat out issing, then you are probably looking at a 500 Internal Server Error.
The server that handles the original client request makes an internal HTTP request that fails.
A failure of the server to connect to some other HTTP server is purely an implementation detail, like not being able to connect to a database or a file system.
Unless that failure is a consequence of information in the request, you are going to end up with the 500 Internal Server Error.
This may be where the use of custom defined error response codes may come in, As long as you respect the already defined response codes. For example you could define 600 as your response code and in your API Docs specify what these custom codes mean in detail. For more information of all existing codes I would reference Iana: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
Now if your goal is to stay within existing http response boundaries I would recommend something along the lines of:
Unprocessable failure: Status 422
Authorization failure: Status 403
Unable to process could mean many things such as the aforementioned business validation error.
Business validation error.
This could be 400, 422, 403, 409 depending on what business validation means.
Querying for an entity in a database that does not exist. Assume that the database lookup is only one part of the request processing pipeline (e.g. not the client request itself).
Sounds like 400, 409 or 422.
The server that handles the original client request makes an internal HTTP request that fails. In this case, the handling server is alive and well, while the internal HTTP request may return a 5xx. Assume that the internal HTTP request is only one part of the request processing pipeline (e.g. not the client request itself).
The client doesn't know/care about internal http requests. The point is that it's failed, and it's a bug/system failure so this is a 5xx error.
The most important thing to remember when choosing a HTTP status code is:
Make sure you have the general class correct, so 4xx and 5xx depending on this is a client/server error.
If you need something more specific, ask yourself why. Is your client going to be able to make a better decision if it received a 400 or 409? If not, maybe it's not that important.
I wrote a ton about error codes here, and would suggest you read a bunch of the 4xx entries.
Also a great blog post from one of the authors of the HTTP standards, which goes more into the idea that finding the perfect status code for a case is not that important.

Microservices HttpStatus Codes

this is a question related to good practices in signalling the communication between various APIs in a Microservice architecture.
I am facing the following 'events':
one Microservice is DOWN (physically)
one Microservice is calling another one using a wrong URL
one Microservice is calling another one using a correct URL but wrong arguments (query params for example, or POST body fails validation)
one Microservice is asking another one for a resource and that particular resource cannot be found in DB (lets say a findById type)
I need to find a better way to signal these by using HTTP Status codes and various payloads explaining in detail what's going on.
For example:
for case 1, I could use NOT_FOUND (404) with a payload: API_DOWN
for case 2, I could use BAD_REQUEST (400)
for case 3, I could also use BAD_REQUEST (400) with a validation payload message
for case 4, I could also use NOT_FOUND (404) with a RESOURCE_NOT_FOUND message
everything else could be INTERNAL_SERVER_ERROR if caused by a uncaught exception.
200 OK for good stuff
Any thoughts? I am not 100% happy with my interim solution. Want to make it better. I understand the fact there are 2 animals here: one is client-server signalling and second one is related to data (payloads missing etc)
one Microservice is DOWN (physically) - I could use NOT_FOUND (404) with a payload: API_DOWN
In this instance you will have no control over what response code the consumer receives. Depending on how the service is hosted and managed, you may receive any of 500 Server error, 502 Bad gateway, 503 Unavailable, or 504 Timeout. However, what you will get depends on your infrastructure and stack set up.
one Microservice is calling another one using a wrong URL - I could use BAD_REQUEST (400)
This is semantically identical to the above case. There is very little difference between trying to call a service which is unavailable, and trying to call one which doesn't exist.
one Microservice is calling another one using a correct URL but wrong
arguments (query params for example, or POST body fails validation) - I could also use BAD_REQUEST (400) with a validation payload message
There are a couple of variants of this. One is calling PUT on a resource which only supported PATCH, for example. In this instance there is a status code for this, it's 405 Method not allowed. Again, you're usually not in control here - most service frameworks will automatically return this status code to consumers if you do not define a requested operation against a given resource.
Another variant (as in your example) is incorrect query parameters. Again most frameworks will automatically return 400 Bad request (or 422 Unprocessable) in this instance. If the query parameter is provided but is invalid in some other way, then 400 Bad request is appropriate.
Note: it is not generally appropriate to return a 400 Bad request for an "invalid" path parameter.
one Microservice is asking another one for a resource and that
particular resource cannot be found in DB (lets say a findById type) - I could also use NOT_FOUND (404) with a RESOURCE_NOT_FOUND message
Yes, 404 Not found is the correct status code.
everything else could be INTERNAL_SERVER_ERROR if caused by a uncaught
exception.
Not necessarily. One status code I use often is 409 Conflict for those instances where the input is OK but has caused some kind of problem (like duplicate entities).
200 OK for good stuff
200 is fine in many situations. However, consider 201 Created if something has been added, 202 Accepted if the call had no effect (like if you try to create a resource but the resource was already there), or 204 No Content if you want to explicitly call out that no return type should be expected.
Just a small addition what #tom-redfern already said.
There's a nice map i like. Looks like a plan for an underground.
HTTP Status Map by Restlet
On the bottom right side of the image you have nice summary.
Code 100: Informational
Code 200: Success
Code 300: Redirectional
Code 400: Client Error
Code 500: Server Error
You can hover the status codes and get a nice and short explanation to it. Maybe this helps you for your implementation.
For example we got multiple times the same request nearly at the same time. This lead to duplicate entries in our elasticsearch. We added a servlet filter which catches duplicates and returns a 409 CONFLICT status code.
Description for 409 is in example:
Indicates that the request could not be processed because of conflict
in the request, such as an edit conflict in the case of multiple
updates.

Idempotence of HTTP PUT and DELETE

So the HTTP spec says that HTTP PUT and DELETE should be idempotent. Meaning, multiple PUT requests to the same URL with the same body should not result in additional side-effects on the server. Same goes with multiple HTTP DELETEs, if 2 or more DELETE requests are sent to the same URL, the second (or third, etc) requests should not return an error indicating that the resource has already been deleted.
However, what about PUT requests to a URI after a DELETE has been processed? Should it return 404?
For example, consider the following requests are executed in this order:
POST /api/items - creates an item resource, returns HTTP 201 and URI /api/items/6
PUT /api/items/6 - updates the data associated with item #6
PUT /api/items/6 - has no side effects as long as request body is same as previous PUT
DELETE /api/items/6 - deletes item #6 and returns HTTP 202
DELETE /api/items/6 - has no side effects, and also returns HTTP 202
GET /api/items/6 - this will now return a 404
PUT /api/items/6 - WHAT SHOULD HAPPEN HERE? 404? 409? something else?
So, should PUT be consistent with get and return a 404, or like #CodeCaster suggests, would a 409 be more appropriate?
RFC 2616, section 9.6, PUT:
The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations.
In contrast, the URI in a PUT request identifies the entity enclosed
with the request -- the user agent knows what URI is intended and the
server MUST NOT attempt to apply the request to some other resource.
And:
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.
So to define 'appropriate' is to look at the 400-series, indicating there's a client error. First I'll eliminate the irrelevant ones:
400 Bad Request: The request could not be understood by the server due to malformed
syntax.
401 Unauthorized: The request requires user authentication.
402 Payment Required: This code is reserved for future use.
406 Not Acceptable: The resource identified by the request [...] not acceptable
according to the accept headers sent in the request.
407 Proxy Authentication Required: This code [...] indicates that the
client must first authenticate itself with the proxy.
408 Request Timeout: The client did not produce a request within the time that the server was prepared to wait.
411 Length Required: The server refuses to accept the request without a defined Content-
Length.
So, which ones may we use?
403 Forbidden
The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated.
This description actually fits pretty well, altough it is usually used in a permissions-related context (as in: YOU may not ...).
404 Not Found
The server has not found anything matching the Request-URI. No
indication is given of whether the condition is temporary or
permanent. The 410 (Gone) status code SHOULD be used if the server
knows, through some internally configurable mechanism, that an old
resource is permanently unavailable and has no forwarding address.
This status code is commonly used when the server does not wish to
reveal exactly why the request has been refused, or when no other
response is applicable.
This one too, especially the last line.
405 Method Not Allowed
The method specified in the Request-Line is not allowed for the
resource identified by the Request-URI. The response MUST include an
Allow header containing a list of valid methods for the requested
resource.
There are no valid methods we can respond with, since we don't want any method to be executed on this resource at the moment, so we cannot return a 405.
409 Conflict
Conflicts are most likely to occur in response to a PUT request. For
example, if versioning were being used and the entity being PUT
included changes to a resource which conflict with those made by an
earlier (third-party) request, the server might use the 409 response
to indicate that it can't complete the request. In this case, the
response entity would likely contain a list of the differences
between the two versions in a format defined by the response
Content-Type.
But that assumes there already is a resource at the URI (how can there be a conflict with nothing?).
410 Gone
The requested resource is no longer available at the server and no
forwarding address is known. This condition is expected to be
considered permanent. Clients with link editing capabilities SHOULD
delete references to the Request-URI after user approval. If the
server does not know, or has no facility to determine, whether or not
the condition is permanent, the status code 404 (Not Found) SHOULD be
used instead.
This one also makes sense.
I've edited this post a few times now, it was accepted when it claimed "use 410 or 404", but now I think 403 might also be applicable, since the RFC doesn't state a 403 has to be permissions-related (but it seems to be implemented that way by popular web servers). I think I have eliminated all other 400-codes, but feel free to comment (before you downvote).
Your question has an unstated, assumed premise, that the resource must exist for a PUT to succeed. This is not a valid assumption.
The relevant portion of the spec (RFC2616) says:
the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource.
The spec does not say, "An object at the referenced URI must already exist in order for a PUT to that URI to succeed."
The easy example is a web store implemented via REST. GET returns a representation of the object at the given path, while DELETE removes the item at the given path. Those are easy. But the POST and PUT are not much more difficult to understand. POST can do anything, but one use of POST creates an object in a container that the client specifies, and lets the server return the URI of the newly created object within that container. PUT is more limited; it gives the server the representation for an object at a given URI. The object may already exist, or it may not. PUT is not a synonym for REPLACE.
In my opinion 409 or 410 is wrong for a PUT, unless the container itself - the thing you are trying to put into, does not exist.
therefore:
POST /container
==> returns 200 with `Location:/container/resource-12345`
PUT /container/resource-98928
==> returns 201 CREATED or 200 OK
PUT /this-container-does-not-exist/resource-22828282
--> returns 400
Of course it is up to you, whether you'd like your server to allow these PUT semantics. But there's nothing in the spec that says you must not allow clients to provide the URI of the resource that he is PUTting.

Choose appropriate HTTP status codes in controversial situations or introduce subcodes?

I am developing iOS application running against a remote server, having another developer behind it. The project and an API draft we are writing are in initial phase.
The problem we are faced with is that we are not satisfied with existing amount of conventional status codes described by HTTP/REST specifications: there are cases where we are uncertain about what code to pick up.
Examples to provide minimal context:
Server-side validation errors. Fx. Client-side validations are ok, but server API has recently been changed slightly, so a server should return something indicating that it is exactly the validation problem.
An attempt to register user that already exists. SO topics do not provide any precise point on that.
A user is registered, and tries to log in without having the password confirmation procedure accomplished.
Two obvious approaches we see here:
Use fx 400 error for the cases when an appropriate conventional status code could not be found. This will lead us to parsing error text messages from JSON responses. Obviously, this approach will introduce superfluous complication in a client-side code.
Create our own sub-codes system and rely on it in our code. This one involves too much artificial conventions, which will lead us towards becoming too opinionated and arbitrary.
Feeling that the number of such cases is going to grow, we are thinking about an introduction of custom sub-codes in JSON responses our server should give (i.e. choose the second approach).
What I'm asking here:
What are the recommended approaches, strategies, even glues or hacks for these kinds of situations?
What are pros-cons of moving away from strictly following REST/HTTP conventions for status codes?
Thanks!
For validation problems, I use 422 Unprocessable Entity (WebDAV; RFC 4918)
The request was well-formed but was unable to be followed due to semantic errors. This is because the request did not fail because of malformed syntax, but because of semantics.
Then in order to communicate you just need to decide on your errors format, so for situation 1 if there is a required field you might return a 422 with the following.
{
"field": ["required"]
}
I would treat number two as a validation problem, since really it is a validation problem on username, so a 422 with the following.
{
"username": ["conflict"]
}
Number three I would treat as a 403 Forbidden because passing an authorization header will not help and will be forbidden until they do something other than pass credentials.
You could do something like oauth2 does and return a human readable description, a constant that people can code against that further clarifies the error and a uri for more information.
{
"error": "unfinished_registration",
"error_description": "Must finish the user registration process",
"error_uri": "http://yourdocumentation.com"
}
Note: you will find that people disagree on what http codes map to what situation and if 422 should be used since is part of the WebDAV extensions, and that is fine, the most important thing you can do is document what the codes mean and be consistent rather than being perfect with what they mean.
There's no such thing as "sub-codes" in HTTP (Microsoft IIS is clearly violating the spec, and should be flogged).
If there's an appropriate status code, use it; don't say "this status code means that in my application" because that's losing the value of generic status codes; you might as well design your own protocol.
After that, if you need to refine the semantics of the status code, use headers and/or the body.
For the use cases you have described, you could use these error codes:
1) 400 Bad Request
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
2) 409 Conflict
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough
information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.
Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.
3) 401 Not Authorized
The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication" [43].
For any other use case that you have, it varies. I would probably go with number 2 if there is truly no standard way of encoding specific errors.

What is the proper HTTP response code for request without mandatory fields

Consider simple case where user is deleting a post. This is simple HTTP DELETE/POST request with one mandatory field, post_id.
What should server do if post_id is not provided?
Apparently, user should never encounter this behaviour, so let's be puristic.
My first take would be 400 bad request, but spec says
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
and I'd say missing field is OK from syntax/http POV, it's application domain-specific semantic requirement.
200 OK with explanations is bad, 500 feels weird as this is request problem.
Thoughs?
400 is the correct response.
400 is not restricted to a malformed syntax from an HTTP point of view. Missing a mandatory argument is an error in the syntax defined by the application and thus a "Bad Request"
EDIT
At first it seems strange that there is no separate return code for this, but the return codes are designed to differentiate in what actions the client should take. A 400 error code means that the client should change the POST data or query string to the format defined by the application. Hence it is appropriate for this case.
In a REST scenario, the resource to be deleted should be identified by the URL, so the ID of the resource should be a part of that URL in order to properly identify it. Once that assumption is correct, then the URL either is identifying a different resource fr deletion, or it isn't (which would give a 404)
In the general case of a missing parameter, however, I often use a 403 Forbidden error. The reasoning is that the request was understood, but I'm not going to do as asked (because things are wrong). The response entity explains what is wrong, so if the response is an HTML page, the error messages are in the page. If it's a JSON or XML response, the error information is in there.
From rfc2616:
10.4.4 403 Forbidden
The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated.
If the request method was not HEAD and the server wishes to make
public why the request has not been fulfilled, it SHOULD describe the
reason for the refusal in the entity. If the server does not wish to
make this information available to the client, the status code 404
(Not Found) can be used instead.