Http Status Code 400 vs 412 - api

So I'm developing a Rest API
When a POST is made to create a resource and a required field is missing what should I return?
400 - Bad Request
OR
412 - Precondition Failed
And Why?

Use 400 if the request parameters are wrong. Use 412 if one of the If-* request headers like If-Match, If-Modified-Since, etc are wrong.
Why? That's just what RFC says. See for example this extract of If-Match specification:
If none of the entity tags match, or if "*" is given and no current entity exists, the server MUST NOT perform the requested method, and MUST return a 412 (Precondition Failed) response. This behavior is most useful when the client wants to prevent an updating method, such as PUT, from modifying a resource that has changed since the client last retrieved it.

412 is used when your server does not meet a condition specified by the client.
In your case you should use a 400. It is just a bad request.
See this link for some explaination on pre-condition headers.
The Etag header is, generally, a string that represents our resource
in the HTTP headers. You ask for a resource with an If-Match is a
preconditional HTTP header. It will send a 412 if it does not match
the code you sent.
If-None-Match tells the server to process a whole response only if the
Etag is different from the one sent by the client.

You could use status code 422. If you don't want to, 400 is fine.

Related

What response code corresponds in REST API to not finding a resource due to query params?

I found in my job that people are designing a RESTs API that has endpoints that return a single Json object (not a collection) based in query params (not path param).
For example:
/users?name=John&surname=Sparrow
with response body
{id:10, name="John", surname="Sparrow", gender="male"}
But what response code corresponds in REST API to not finding a resource due to query params?
For example:
/users?name=John&surname=Smith
(when John Smith doesn't exist).
I don't think it is a 404 error because /users endpoint exists, but I don't know if I must return a 400 error or a 200 without body (or null value) or other kind of response
Can you help me?
Thanks
What is most appropriate depends on whether an empty result list is OK or a clear failure. Whether parameters are PathParams or QueryParams has no bearing on return codes.
My general approach is that search functions such as findStuffBySearchTerms always return a successful HTTP code such as 200 and either the results or an empty list. On the other hand, fetchStuffById where I expect the entity to be found will return HTTP 404 if it is not found.
What response code corresponds in REST API to not finding a resource due to query params?
404 Not Found.
I don't think it is a 404 error because /users endpoint exists,
The resource identifier includes the query params. Which is to say, the query parameters are part of the identifier in precisely the same sense that path segments are part of the identifier.
In your request body, you can describe the circumstances of your implementation as precisely as you like.
But the audience of HTTP status codes includes general purpose components (browsers, proxies, web crawlers), for whom the response code is the primary mechanism for describing the semantics of the response:
The status-code element is a 3-digit integer code describing the result of the server's attempt to understand and satisfy the client's corresponding request. The rest of the response message is to be interpreted in light of the semantics defined for that status code. -- RFC 7230
That said, your server owns its own resources, and therefore you get to decide whether or not a resource exists, and what it's current representation looks like.
GET /users?name=Dave HTTP/1.1
200 OK
Content-Type: text/plain
Dave's not here, man.
From an HTTP/REST framing, that's a perfectly reasonable exchange; somebody asked for the latest representation of /users?name=Dave, and the latest representation is a plain text document. Absolutely fine.
The key idea here is that that HTTP status-code is metadata of the transfer of documents over a network domain.
HTTP is indifferent to the semantic meaning of the representations of resources.
That said, you should be considering in your design concerns like "what does this look like in our access logs?" If you want your operators to be able to distinguish this case from the similar case where the query parameters match information in your database, 200 vs 404 is the natural way to do that.
You'll normally prefer 404 to the other error status codes for this case because 404 indicates the response is cacheable, which is probably want you want when you are passed a request-target that has a spelling error in it somewhere.

HTTP response body for server command request

I am solving one question with my team about REST API specification.
We have a case where in some requests we are sending only some particular command via HTTP request for example : We are using POST (now considering PATCH request) to endpoint : /server/startSomeOperation . Backend developers told us that this request is only telling hardware to start some functionality on backend that affects the measurement of the user but it really has nothing to return. My question is :
Should we (according to some REST API specification) always return body of such a request when we know that no additional returned data will be needed except HTTP status code? Until now we were strictly following the rule that every request needs to have some sort of body returned but until now every body response even when it was a command to a server made sense.
Should we (according to some REST API specification) always return body of such a request when we know that no additional returned data will be needed except HTTP status code?
No - it is perfectly fine to send a 204 No Content or a 205 Reset Content when the semantics of your response is well aligned with the standard meaning of those codes.
You also have the option of declaring that the "representation of the status of, or results obtained from, the action" is zero bytes long, in which case you could use a 200 OK with a Content-Length header.

400 vs 422 for Client Error Request

I've read a lot of posts and articles regarding proper http status code to return for client request error.
Others suggest to use 400 as it has been redefined in RFC 7231 though I'm not sure if the example given covers all the client error in my mind because the examples are syntactic.
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).
I did find this statement in the Appendix B of the rfc 7231:
The 400 (Bad Request) status code has been relaxed so that it isn't
limited to syntax errors. (Section 6.5.1)
Does this mean that I can consider any type of client error a bad request? Would it be better to use 400 for client requests and just specify a more specific error in the message?
On the other hand, others say that it's better to use 422 (Unprocessable Entity). While this is more focused on semantics, it's only listed in [RFC 4918][2] which is a webDAV extension for http/1.1
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.
Can I use this webDAV extension codes to handle my http requests? In the case of 422, can I use it even though it's not in the core http codes.
Should I use 400 or 422 for my client error?
Here are the possible client error I have in mind:
1.) Invalid parameter. The client provided parameters but are found invalid. Example: I said that the userId is 1, but when I checked there's no userId of 1. Another example of invalid parameter is wrong data type.
2.) Missing required parameters
3.) Let's say I need to hash a value based on given params and it failed
4.) Blocked content is being used. Like, i want to apply for membership and i passed the userId of 1. However, userId of one is blocked / deactivated
5.) When I try to delete an entry but the entry is still being used in another table.
6.) Let's say i require a signature in my payload and the signature does not match when recalculated in the backend
7.) Let's say I have a value that counts a specific attribute like "shares" and it has reached the maximum value like 10.
etc...
Any informative response will be highly appreciated. Thanks a lot, guys!
Update: I checked google api errors and they are not using 422. On the other hand, Twitter uses 422. I'm more confused than ever >.< Though there's a part of me that thinks 400 is the better choice as it is included in the RFC doc and 422 is not. I could be wrong though.
Can I use this WebDAV extension codes to handle my HTTP requests? In the case of 422, can I use it even though it's not in the core HTTP codes.
HTTP is an extensible protocol and 422 is registered in IANA, which makes it a standard status code. So nothing stops you from using 422 in your application.
And since June 2022, 422 is defined in the RFC 9110, which is the document that currently defines the semantics of the HTTP protocol:
Status code 422 (previously defined in Section 11.2 of RFC 4918) has been added because of its general applicability.
For reference, here's how 422 is defined:
15.5.21. 422 Unprocessable Content
The 422 (Unprocessable Content) status code indicates that the server
understands the content type of the request content (hence a 415
(Unsupported Media Type) status code is inappropriate), and the syntax
of the request content is correct, but it was unable to process the
contained instructions. For example, this status code can be sent if
an XML request content contains well-formed (i.e., syntactically
correct), but semantically erroneous XML instructions.
While defined in the RFC 4918, the reason phrase of 422 was "Unprocessable Entity". Since it was added to the RFC 9110, it's reason phrase is "Unprocessable Content".
Should I use 400 or 422 for my client error?
You certainly could use both. In general, use 400 to indicate syntax errors in the payload or invalid parameters in the URL. And use 422 to indicate semantic problems in the payload.
As an example, see the approach used by the GitHub v3 API:
Client errors
There are three possible types of client errors on API calls that receive request bodies:
Sending invalid JSON will result in a 400 Bad Request response.
HTTP/1.1 400 Bad Request
Content-Length: 35
{"message":"Problems parsing JSON"}
Sending the wrong type of JSON values will result in a 400 Bad Request response.
HTTP/1.1 400 Bad Request
Content-Length: 40
{"message":"Body should be a JSON object"}
Sending invalid fields will result in a 422 Unprocessable Entity response.
HTTP/1.1 422 Unprocessable Entity
Content-Length: 149
{
"message": "Validation Failed",
"errors": [
{
"resource": "Issue",
"field": "title",
"code": "missing_field"
}
]
}
Picking the most suitable 4xx status code
Michael Kropat put together a set of decision charts that helps determine the best status code for each situation. See the following for 4xx status codes:
Problem details for HTTP APIs
HTTP status codes are sometimes not sufficient to convey enough information about an error to be helpful. The RFC 7807 defines simple JSON and XML document formats to inform the client about a problem in a HTTP API. It's a great start point for reporting errors in your API.
It also defines the application/problem+json and application/problem+xml media types.

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.

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.