Should POST request return 404 if reference to other entity fails? - rest

I'm building an API which operates on a noun Foo. When a caller creates an instance of Foo with a POST request, they are required to provide an ID to a second noun, Bar. If the ID they provided is of the right type but there is no Bar with that ID, is 404 the right response?

I think it depends on whether the ID is in the URL or not. The URL is the address for a resource, if the ID is in the URL and no item with this ID exists, or you don't provide it at all, then the URL is invalid, so no resource could be found, so that's a 404.
However, if the ID is not in the URL but in the data from the POST request, and the URL is a valid address to a resource, then a 400 Bad Request should be returned.

I would suggest using HTTP 400 (Bad Request).
See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1. One could interpret 400 as a generic indication that the client did not form the request correctly.
One could also make a case for returning a 500 response. If the client believes that the Bar reference is valid, then the server's failure to process this request could be viewed as exceptional. This could happen for example if the reference is valid, but the a different client deletes it. In this scenario, the first client is not doing anything wrong.

In short: No. Your API should be "user-friendly" meaning, if there is an error it should return it in a way that the user can figure out what the problem was. Returning 404 is like saying that the service was not found which is not true. The response should be 403 - cause it could be that the resource with the ID that the client tries to approach belong to a different client!
In addition, the response should contain an error message/code (in the body) which can be parsed and analyzed by the client.

This is a bit grey area.
Although the 500 response code looks like a good fit because of its broader context, the 404 response code could also be considered.
The reason that I am not sure about the 404 code is the main purpose of your request. The request is sent to create a new resource. It is not for retrieving an existing resource. Though the root cause is the "Not Found" resource, the intention of the request is for a new entity. Getting the 404 response code might cause ambiguity for the client. Therefore, the 500 with a good explanation looks like a better option.
I can clearly state that the 400 response code is not convenient for this case because there is nothing wrong with the request syntax.
The following definitions from MDN Web Docs - HTTP response status codes might help to make a decision.
400 Bad Request:
The server could not understand the request due to invalid syntax.
404 Not Found:
The server can not find the requested resource. In the browser, this
means the URL is not recognized. In an API, this can also mean that
the endpoint is valid but the resource itself does not exist. Servers
may also send this response instead of 403 to hide the existence of a
resource from an unauthorized client. This response code is probably
the most famous one due to its frequent occurrence on the web.
500 Internal Server Error:
The server has encountered a situation it doesn't know how to handle.

4xx is entitled "Client Error" in the standard
5xx is entitled "Server Error"
If the server is 100% sure that the reference to Bar could not be correct (that id is totally invalid format or couldn't have existed) then that's a straight up 400 Bad Request.
If the server allowed someone to delete that Bar where such deletion should not be allowed (Foo should go down with it) then that's a 500 Internal Server Error.
Here the client is creating a Foo with a dangling reference to a Bar (since it's a POST, if it were updating a Foo it would be a PUT). The client got a reference to the referenced Bar somehow and can presumably find an appropriate existing Bar if it tried again. In that case, the server returns 409 Conflict to signal that the request, while valid, is in conflict with the state of the server and needs to be dropped or reconstructed so that it is consistent with the state of the server. The 409 response should specify that the problem is that the referenced Bar does not exist.

Related

What should be the response status code when data present in body is not found in DB

The request sent to api is :
url: /users/{userid}respource/{resourceid}
method: POST
body: {SubResourceId: 6, Message: ''}
So it is a post api. It creates some mapping of user and resource and subresource.
In this case if user or resource is not found , then api returns 404. But what should be the status code if subresource(which is passed in Body) is not found in DB?
I think you should use a 4** error, because it is a client error, they are referencing a non-existent subresource. If you look at the definitions of the HTTP status errors you see that for example 400 bad request means bad syntax, where the client should not try the same request again. However a 404 means not found, yet it might be available in the future so the request can be tried again at a later time.
In all cases there should be an informative message offering more detail if available. So in this case you should probably send a 404 and a message explaining that the subresource cannot be found. Basically you are passing on a 404 from a deeper level.
There is an arguement to be made that 'the resource' that you refer to in the URI was found, and that 404 is not perfect. However looking at the various status codes available in the w3c Definitions there does not seem to be a more appropriate one.
The other option I would consider is a 500, internal server error. You could argue that the server should expect a request with a valid subresourceid. Since the subresource does not exist, the server cannot further process the request. Again, as long as their is a clear error message this can work, but it feels like more of a stretch than the 404.
But most importably, make sure you are consistent when it comes to error handling in your API(s).
Ideally the response code should be 200 with message saying that no sub-resource was found, it can also be "204 No Content". you can read more about it at wiki link.
It needs to be consistent with Response codes you have been using throughout the application.

Relevant HTTP Status code on the Rest API

I have a scenario by passing invalid data in Path variable which is input to fetch the data from Database.As the provided data is not valid so it triggers "500 Internal Server Error" from the database as could not found the data.
and have customized HTTP Status as 404(NOT_FOUND) because data is not found.
Would like to understand,what can be the best HTTP Status code for this scenario other than 404?
HTTP is an application protocol, whose application domain is the transfer of documents over a network (Jim Webber, 2011). The status codes we use in the response are metadata from the domain of document transfer -- which is to say, we care about what the message means, not why our implementation is sending it.
The information specific to your domain, which communicates the details of the problem to the client, belongs in the message-body of the response. The status code is there so that generic components, that don't know the specifics of your domain, can "do the right thing" -- where the right thing is constrained by HTTP semantics.
Michael Kropat published flow charts that may help select the correct status code. Alternatively, you can look through the HTTP Status Code Registry, which has links to the standard that defines the semantics of each code.
Broadly speaking, if the problem is with the request, then we use some message from the 4xx message class; problems in the request are client errors. 404 specifically directs the client's attention to the target-uri.
So if the request is bad because information encoded into a path segment is incorrect, then 404 is the correct choice, because it tells the client where to look for the problem. The only reason that you would look elsewhere is if some other part of the 404 semantics were inappropriate for your circumstances.
Would like to understand what can be the best HTTP status code for this scenario other than 404?
If you are looking for something other than 404, then you could look into the more generic 400. From the RFC 7231:
6.5.1. 400 Bad Request
The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
But bear in mind that the 404 status code itself is suitable for this situation. See the following quote from the RFC 7231:
6.5.4. 404 Not Found
The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. [...]

BadRequest vs NotFound when the resource is a sheet but the user required is not found

I'm just having a discussion here with my colleague regarding what is the best response to return when requesting a specific resource i.e. a datasheet for example, and the url is valid but part of the process when processing this datasheet is to get a specific user which may not be found.
I found this question on SO: Should a RESTful API return 400 or 404 when passed an invalid id
My understanding is that if the request is valid i.e. the url and the parameters pass to it, it should return a 404 (NotFound) if the user is not found.
But my colleague's point is that the datasheet is the resource and therefore since the user requested is not found, it should actually be considered as 400 (BadRequest)
Can someone clarify what it should actually be?
Thanks
Although BadRequest might make sense initially it does not fit the definition of a 400.
400: The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
Reserve a 400 for when the request is missing required fields, an incorrect data type was provided, etc.
In your case, it sounds like the user has made a valid request but that part of the data needed for completion is not found (I'm guessing this is a part of the Uri). This sounds a lot more like a 404, which is perfectly valid when something other than the specified resource is not found.
404: 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.
The specifics of what was not found can be expressed in the error code or the error message.

What status code to use when a parameter is missing in the query string?

I have an endpoint that requires a parameter passed via the query string (is a GET verb).
What is the appropriated status code to give when this parameter is missing from the request? 400 is the one? or should I respond with a 404?
[GET /search?q=ok] => 200 OK
[GET /search] => 400 Bad Request? or 404 Not Found? Or 422 Unprocessable Entity? Others?
TLDR It's an HTTP 400 - Bad Request.
It's a 400 because the user did not send the Required input field.
why not 422 - because this case fits to 400. Keeping your consumers in mind, you shouldn't go to non-popular response codes if you don't really need to.
Cases for HTTP 404:
Url which the client requested is not existing in your server (usually this will be handled by your server. Application developer usually doesn't have to do anything unless you want a nice looking 404 page or for SEO reasons).
If it was a path parameter and client was looking for an entity with an id (for Example (/students/{id} and your application couldn't find such entity, you may respond with an HTTP 404.
Let's say, user send the query parameter and you did not find any items matching the query param, make no mistake, it's still an HTTP 200 with body as an empty array or so (not a 404 unlike mentioned in the previous case). Example: /customers?lastname=unobtanium
It should be 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.
404 - Not Found
The HTTP 404 Not Found Error means that the webpage you were trying to
reach could not be found on the server. It is a Client-side Error
which means that either the page has been removed or moved and the URL
was not changed accordingly, or that you typed in the URL incorrectly.
Its means server is not able to find the URI you specified. but in your case URI is valid but parameters are missing so 400 is right way to do it.
What is the appropriated status code to give when this parameter is missing from the request? 400 is the one? or should I respond with a 404?
I would argue that 404 is appropriate
The 404 (Not Found) status code indicates that the origin server did
not find a current representation for the target resource or is not
willing to disclose that one exists.
The fact that your routing implementation happens to send /search and /search?q=ok to the same handler does not mean that they are the same resource. /search identifies a resource, there's no current representation available for it, so you send a response back to the consumer explaining the problem, and put 404 in the meta data.
The big hint in the spec is this one:
A 404 response is cacheable by default
That lets us inform the client (and any intermediary components) know that this response can be reused.
It's a useful property, and it doesn't apply (out of the box) to 400 Bad Request
Heuristic: your web api should act like a document store. If you ask a document store to give you a document, but you spell the key wrong, what do you get? Some flavor of KeyNotFound exception. Same thing you would get if you asked a web server for a document in your home directory, but your spelled the file name incorrectly.
The semantics of the response indicate the right status code to use, not the implementation details.

400 vs 422 response to POST that references an unknown entity

I'm trying to figure out what the correct status code to return on different scenarios with a "rest-like" API that I'm working on.
This example is borrowed from another question about syntax type issues in the body, but my question assumes valid syntax throughout.
Let's say I have an endpoint that allows POST'ing purchases in JSON format. It looks like this:
{
"account_number": 45645511,
"upc": "00490000486",
"price": 1.00,
"tax": 0.08
}
What is the appropriate status code if:
the account number does not exist
the account is closed or the
account identified is not the right kind of account
These are all firmly business layer issues that prevent "processing" from occuring, however, one scenario involves something that in a GET would be a 404.
Note that the account number is not in the URL, so is 404 misleading?
Let's take these one at a time. Each of these codes is a signal to your client that the server is functioning correctly, and that something must be changed in the request before it can be successfully carried out.
HTTP 400
The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
400 typically indicates a syntax error; as a user, I should look at the structure of the request before trying again.
HTTP 404
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.
404 is the standard code used when a web server can't match a url path to anything. As a client, I should look at the URL of the request before trying again.
HTTP 422
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415 (Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.
422 is generally used for content violations. As a user, I should look at the content of my request before trying again.
Now in your case, account number is an identifying number, but is not included in the URL. A 404 would signal to your user that the URL is wrong, not the payload. Stated another way, suppose your url is:
http://www.myservice.net/endpoint
A 404 would indicate to me that no service exists at /endpoint, instead of no account number. No matter what content I submit, the server will not process my request. The fix I should make then would be to look for an error in the URL, instead of the data payload. So to me a 422 would point me in the right direction, unless you begin to include the account number in the URL.
Ultimately these are design preferences, just make sure you communicate them clearly to your users.
If you consider the accounts to be part of the state of the resource (though indirectly) then you might also consider 409 since that state is in conflict with the semantics of the request.
However, 422 is gaining popularity via Ruby on Rails and Dropwizard where it is used to indicate non-syntactic issues with the body. That growing tendency represents a strong signal to a developer using the API that they need to exclude syntax and focus on the body. Developer time is usually the single largest cost your customers will ever incur, so by directing the attention of their developers you will keep them happy.
So 409 is a possible answer, though rather novel, and 422 is the more conventional approach, although obviously RoR and DropWizard are both rather new so these conventions can be said to be changing fast!
I'd say 422 is adequate in your case, but 400 isn't bad if it's consistent with the rest of your API. It's a common convention to use 400 as an umbrella error code when there's something wrong on the client side, but either the error doesn't fit a particular error code, or you don't want to use too many of them.
A 404 is definitely wrong if there's something wrong with the POST payload.
Case 1 : Account number doesn't exist.
This is a standard case for 404.
Case 2 : Account is closed.
This has do with the logic if you keep the account details when you close it.
If you donot keep the account details when the account is closed, you can give 404.
If you keep the account details after it is closed, you must be marking it (like raising some flag) (or whatever logic you have). In this case, Status code 400 with a proper message of why it is failed and possibly remediation will do.
Case 3 : Account identified is not the right kind of account.
403, as the account is not authorised for completing any purchases makes sense to me. If there is no concept like authorised account, 400 with a explanatory message will do. But I would insist to go with 403 in this case.
Actually, in this case 404 sounds good to me.