HTTP Status codes confusion - rest

So, I am trying to display meaningful and accurate HTTP status codes and I'm getting confused even after going through the examples online. Here's my situation:
In the URL which accepts the query param:
#POST query
Sample URL: /putRecord?Name=A&Age=25&house=permanent
what status code do i return when one of the params is missing? (All 3 are mandatory) - from what I've read, I am guessing it is a 400: Bad request. But this seems too general. Is there a way for me to say that the query was malformed? Source:here
Assuming I validate the name for duplicates against the DB, if I get a duplicate, what status code do I return?
So, if there's a duplicate entry available already, I can't add the record. Do I display 304 (Not modified) or just the error code from 2?
Clarification: For 3, another possibility is when I can't actually commit to the DB and I rollback(possibly). What status code will it be now?
Thanks so much!

Ad 1. You can return, besides the code itself (400) also a short message with explanation. So, instead of returing "400 Bad Request" you could respond with "400 Query param name required" or something similar. This message is called "reason phrase" and is defined in 6.1 in RFC 2616. Or, if you need more flexibility, you could return document with the explanation.
Ad 2. I would consider using 422 Unprocessable entity. From the RFC 4918:
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity, 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.
Ad 3. I would return 422, but it really depends whether this situation is considered an error in your logic, or is it a regular, expected situation.
Edit: As #War10ck suggested in the comment, HTTP 409 (in place of HTTP 422) might make sense as well.
Note on handling duplicates: it seems (correct me if I'm wrong) that you consider new entity being a duplicate if it's name is already in the database. If so, that you could maybe consider using a HTTP PUT instead of HTTP POST?
You could define the following resource:
HTTP PUT /record/:name
So, "name" would be a part of the URI. Then, in case there is a second PUT to the same resource (same "name"), it'd be elegant to respond with 409/422.
If you're using different key for unique constraint, modify the URI appropriately.
As a rule of thumb, POST is for situations where you can have multiple instances of a given resource, i.e.
HTTP POST /log ;; Because we have many logs
And PUT for situations where each resource is unique:
HTTP PUT /person/:name (or /person/:tax-number if :name isn't unique)
Also, note that I've renamed your resource from "putRecord" to "record" - PUT is a HTTP method, no reason to have it in URI as well.

Related

Should a REST API return a 404 when POSTing a non-existing ID?

As far as I understand it, in addition to returning a 404 Not Found for unknown endpoints, a REST API should also return a 404 in the following cases:
requesting a resource with an ID that does not exist in the path: route /users/{id} exists, but /users/123456 does not exist
requesting a resource with an ID that does not exist in the query parameters: route /search exists, but /search?user=123456 returns a 404 if the user does not exist (I asked a similar question a few years ago)
Now what about the use case where an endpoint accepts a JSON object with a number of fields, one of them being the ID of a user that does not exist:
POST /makeReservation HTTP/1.1
...
{
"userId": 123456,
...
}
Should this return a 404 as well, or is this considered a different kind of error (validation error?) in this case?
As far as I understand it
I'd say your current understanding is a little bit more complicated than it should be.
404 Not Found means:
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.
In case "target resource" is unclear, we can review the specification of the Request Line.
request-line = method SP request-target SP HTTP-version CRLF
The request-target identifies the target resource upon which to apply the request, as defined in Section 5.3.
In other words, 404 says "there is a problem with the spelling of the request-target".
Therefore, it is misleading to suggest that there is a problem with the request-target, when the actual problem is in the request body.
The error code you probably want for this case is 422 Unprocessable Entity
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.
IANA's HTTP Status Code Registry is a good place to look when you are sure that there should be a standardized code for your use case, but you are having trouble guessing which specification describes it.
it's part of WebDAV and I'm not sure how correct it is to use it for other applications?
TL;DR: it's correct to use it for other applications.
The HTTP specification defines the process by which new codes can be added to the status code registry, and that process has been followed for the WebDAV codes. So we can be confident that the meaning of 422 won't be replaced by some other semantic (for compatibility, status codes are retired -- see status code 306.)
The definition of 422 in the WebDAV specification is not WebDAV specific.
Furthermore, the behavior of clients that are not aware of the WebDAV specification is described in RFC 7231
a client MUST understand the class of any status code, as indicated by the first digit, and treat an unrecognized status code as being equivalent to the x00 status code of that class, with the exception that a recipient MUST NOT cache a response with an unrecognized status code.
You can also review appendix B of the WebDAV specification.
(As a side note, I think your concern is reasonable -- WebDAV methods are much harder to re-use outside of that context.)
Update 2022-07-12: the IANA registered reference for status code 422 is now RFC 9110 (HTTP Semantics). We no longer need be concerned when we use that status code outside of a WebDAV context.

HTTP status code for PATCH requests meaning "you are not allowed to make such request"

I am trying to implement some PATCH requests in our software(following https://www.rfc-editor.org/rfc/rfc7396). The resources have some fields which must not be modified, so I am thinking to return some error status code when such fields appear in HTTP JSON request body. 400 seems a bit too generic (I am using it for validation errors e.g. email format and the like). Perhaps there is some other status code used in such situations?
There's a code for that . . . 8-)
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
https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Furthermore, 403 is suitable even if there are no credential problems.
This is explained in RFC7231 Section 6.5.3:
a request might be forbidden for reasons
unrelated to the credentials
RFC 7231 section 8.2 a status code registry, so that's the place to start.
This is clearly a problem with the request; something the client might be able to fix, so an entry from the 4xx class is appropriate.
405 Method Not Allowed is wrong for the case you describe -- a different merge patch document would be accepted by this resource, but not the one that is present.
403 Forbidden is wrong, as it communicates a problem related to credentials, but you are describing a problem with payload.
409 Conflict could be reasonable...
the request could not be completed due to a conflict with the current state of the target resource.
I don't see any reason that the conflict can't be in an immutable part of the "current state".
But I think your best bet is 422 Unprocessable Entity
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.
Another good resource to consider is the HTTP Patch specification. RFC 5789 enumerates a number of reasons that a patch might fail, and what code would be appropriate to use in each context. You can decide for yourself whether you think those distinctions are appropriate in your circumstances.
There may also be more specific errors like "Conflicting State" that could be signaled with this status code, but the more specific error would generally be more helpful.

HTTP status code in REST API for using GET to query a “Not Ready Yet, Try Again Later” resource?

First of all, I've read some relevant posts:
Best HTTP status code in REST API for “Not Ready Yet, Try Again Later”? It is about GET an item
Is it wrong to return 202 “Accepted” in response to HTTP GET? It is about GET an item
HTTP Status Code for Resource not yet available It is about POST
HTTP status code for in progress? It is about GET but no clear answer.
but I still think I should raise my question and my thoughts here. What should be the HTTP status code in REST API for using GET to QUERY a “Not Ready Yet, Try Again Later” resource? For example, client tries to query all local news happen in future(!) by make an HTTP GET to this url: http://example.com/news?city=chicago&date=2099-12-31 so what shall the server reply?
These are the http status code I considered, their rfc definition and why I am not fully satisfied with:
3xx Redirection. Comment: Not an option because there is no other link to be redirected to.
503 Service Unavailable: The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. Comment: The retry behavior is desired, but semantically the situation is not server's fault at all, so all 5xx look weird.
4xx Client Error. Comment: Looks promising. See below.
413 Request Entity Too Large: The server is refusing to process a request because the request entity is larger than the server is willing or able to process. ... If the condition is temporary, the server SHOULD include a Retry- After header field to indicate that it is temporary and after what time the client MAY try again. Comment: The retry behavior is desired, however the "Entity Too Large" part is somewhat misleading.
417 Expectation Failed: The expectation given in an Expect request-header field (see section 14.20) could not be met by this server. Comment: So it should be caused by an Expect request-header, not applicable to my case.
406 Not Acceptable: The resource ... not acceptable according to the accept headers sent in the request. Comment: so it is caused by the Accept request-header, not applicable to my case.
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. ... Conflicts are most likely to occur in response to a PUT request. Comment: This one is close. Although my case is not about PUT, and isn't actually caused by conflict.
404 Not Found: The server has not found anything matching the Request-URI. Comment: Technically, my url path (http://example.com/news) DOES exist, it is the parameters causing problems. In this case, returning an empty collection instead of a 404, is probably more appropriate.
403 Forbidden: The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. Comment: Generally this is supposed to be used in any restricted resource?
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. Comment: It is not true in my case. My server understands the request, its syntax is good, only the meaning is bad.
2xx Successful. Comment: If 4xx doesn't work, how about 2xx? See below.
200 OK. Comment: Fine. So what should I include in the response body? null or [] or {} or {"date": "2099-12-31", "content_list": null} or ... which one is more intuitive? On the other hand, I prefer a way to clearly differentiate the minor "future news" error from the more common "all query criteria are good, just no news this day" situation.
202 Accepted: The request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon. Comment: Providing that we can use 202 in a GET request, it is acceptable. Then refer to the 200 comment.
204 No Content: The server has fulfilled the request but does not need to return an entity-body. Comment: Providing that we can use 204 in a GET request, it is acceptable. Just don't know whether this is better than 202 or 200.
More on 2xx: Comment: I assume all 2xx response will likely be cached somewhere. But in my case, if I return an empty body for "tomorrow's news", I don't want it to be cached. Ok, explicitly specify the "no cache" headers should help.
Your thoughts?
Use 404.
Your objection to it is based on a popular understanding of a URI as not including the querystring. "Because I have multiple URI's that map to the same handler," goes the logic, "my resource does in fact exist and is just being parameterized by querystring args."
This is incorrect. As the URI spec itself says in Section 3.3 (emphasis mine),
"The path component contains data, usually organized in hierarchical
form, that, along with data in the non-hierarchical query
component (Section 3.4), serves to identify a resource within the
scope of the URI's scheme and naming authority (if any)."
Resources are identified by URI's, and any change to any part of an absolute-URI identifies a separate resource. Tweet that to everyone you know once a day until they tell you to stop. Therefore a 404 is a perfect match: "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."
You are retrieving the news for that day, which is a valid day, there just isn't any news. A 200 response of an empty body, or a what ever makes sense based on the mediatype would seem the logical. This depends on the media type you have decided with the client.
404 would make more sense if the date format was wrong (you asked for the 45th day of November, or asked for a city that doesn't exist.)
As an aside the URL would be better in the format http://example.com/news/chicago/2099-12-31 since that is the specific resource you want to retrieve. This format would make things like 404s clearer as well.

What REST PUT/POST/DELETE calls should return by a convention?

According to the "REST ideology" what should be in the response body for a PUT/POST/DELETE requests?
What about return codes? Is HTTP_OK enough?
What is the reason for such conventions, if any?
I've found a good post describing POST/PUT differences: POST vs PUT
But it still doesn't answer my question.
Forgive the flippancy, but if you are doing REST over HTTP then RFC7231 describes exactly what behaviour is expected from GET, PUT, POST and DELETE.
Update (Jul 3 '14):
The HTTP spec intentionally does not define what is returned from POST or DELETE. The spec only defines what needs to be defined. The rest is left up to the implementer to choose.
Overall, the conventions are “think like you're just delivering web pages”.
For a PUT, I'd return the same view that you'd get if you did a GET immediately after; that would result in a 200 (well, assuming the rendering succeeds of course). For a POST, I'd do a redirect to the resource created (assuming you're doing a creation operation; if not, just return the results); the code for a successful create is a 201, which is really the only HTTP code for a redirect that isn't in the 300 range.
I've never been happy about what a DELETE should return (my code currently produces an HTTP 204 and an empty body in this case).
Creating a resource is generally mapped to POST, and that should return the location of the new resource; for example, in a Rails scaffold a CREATE will redirect to the SHOW for the newly created resource. The same approach might make sense for updating (PUT), but that's less of a convention; an update need only indicate success. A delete probably only needs to indicate success as well; if you wanted to redirect, returning the LIST of resources probably makes the most sense.
Success can be indicated by HTTP_OK, yes.
The only hard-and-fast rule in what I've said above is that a CREATE should return the location of the new resource. That seems like a no-brainer to me; it makes perfect sense that the client will need to be able to access the new item.
I like Alfonso Tienda responce from
HTTP status code for update and delete?
Here are some Tips:
DELETE
200 (if you want send some additional data in the Response) or 204 (recommended).
202 Operation deleted has not been committed yet.
If there's nothing to delete, use 204 or 404 (DELETE operation is idempotent, delete an already deleted item is operation successful, so you can return 204, but it's true that idempotent doesn't necessarily imply the same response)
Other errors:
400 Bad Request (Malformed syntax or a bad query is strange but possible).
401 Unauthorized Authentication failure
403 Forbidden: Authorization failure or invalid Application ID.
405 Not Allowed. Sure.
409 Resource Conflict can be possible in complex systems.
And 501, 502 in case of errors.
PUT
If you're updating an element of a collection
200/204 with the same reasons as DELETE above.
202 if the operation has not been commited yet.
The referenced element doesn't exists:
PUT can be 201 (if you created the element because that is your behaviour)
404 If you don't want to create elements via PUT.
400 Bad Request (Malformed syntax or a bad query more common than in case of DELETE).
401 Unauthorized
403 Forbidden: Authentication failure or invalid Application ID.
405 Not Allowed. Sure.
409 Resource Conflict can be possible in complex systems, as in DELETE.
422 Unprocessable entity It helps to distinguish between a "Bad request" (e.g. malformed XML/JSON) and invalid field values
And 501, 502 in case of errors.
By the RFC7231 it does not matter and may be empty
How we implement json api standard based solution in the project:
post/put: outputs object attributes as in get (field filter/relations applies the same)
delete: data only contains null (for its a representation of missing object)
status for standard delete: 200

what http response code for rest service on put method when domain rules invalid

What is the most appropriate response code to return when using the PUT method to update a resource, and the request contains some data that would invalidate the domain rules?
For example, a customer resource must have a name specified. If an agent tries to issue a PUT without supplying a name I don't want to update the resource, and I want to tell the caller that they need to supply a name.
What HTTP response code?
How about 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."
RFC 4918, Section 11.2
The response code is not related to the http method in this case. You should return the same status code as if it had been a POST request. I'd say you should use 400 or 409 (Note: See further discussion of the difference between the two in the comments).
I would return a 400. Strictly, this is for "malformed syntax" (not invalid data), but in practice the YouTube, Twitter, etc. use it for more generally "bad" requests.