HTTP status code to return by a REST API when image size exceeds limit - api

A POST to a specific end point allows to upload an image except if the image is too large, so I want to return the appropiate http status code response in that case.
A http status code 400 response it does not seem to fit well in this case.
400 Bad Request: "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 think that the image being too large it does not imply that the request is malformed or syntactically incorrect.
Any suggestions?

This seems like it would be an ideal candidate for 413 Payload Too Large. From Section 6.5.11 of RFC 7231:
The 413 (Payload Too Large) status code indicates that the server is
refusing to process a request because the request payload is larger
than the server is willing or able to process.

You can use 420 or even 422, but I would avoid that until you have really good reason to have separate code for it. Usually is better to keep number of different status codes rather small. Check top 10 on that list: http://www.restapitutorial.com/httpstatuscodes.html
You should avoid using more than 10 codes, because your API will become too complex.
So my answer is: use 400 with proper error message returned to the client like: "Image too large, you can upload files up to XX MB"

Related

Correct http status for invalid config in request body?

I am having trouble picking the correct HTTP Status for when an API is receives an attribute that maps additional data in the system but that additional data is not found. I was initially thinking 422 since it describes the use case but sounds like it is reserved for WebDAV. Then I was thinking maybe a 404 but I mentally associate that to a URL being incorrect. The other option was using error code 200 and have a failure message.
Example: the key nvdaKey is not a key configuration that the system knows about.
POST: pgpTool.com/encrypt
{
"message": "my secret message",
"keyConfigName": "nvdaKey"
}
The IANA HTTP Status Code Registry currently lists HTTP Semantics as the authoritative reference for status code 422
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 was unable to process
the contained instructions.
So if you think that's a winner, go for it.
403 Forbidden is also an option ("I understood your request, but I refuse to fulfill it").
Status codes are meta data in the transfer of documents over a network domain; the intended audience is general purpose HTTP components (browsers, caches, proxies....) Clients are supposed to be getting the semantics of the message from the body (in just the same way we expect humans reading the web to learn of errors by reading the returned web page, rather than by reading HTTP headers).
So apart from some purely mechanical concerns (caching, interpretation of headers) it is not necessarily critical that you produce precisely the right status code, so long as you get the class (Client Error / 4xx) correct.
Do note that a client that doesn't recognize a 422 is expected to treat the response as though it were a 400.

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.

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.

What is the benefit of passing HTTP status with API responses?

With your error responses you need to pass some attribute that indicates the error type anyway. So that makes HTTP status code redundant or sometimes even inaccurate.
Any real benefit here, and why it shouldn't just be 200?
Assuming we're talking about a RESTful API:
Because if you return an error message with a HTTP Status Code of 200, the client will assume his request was successful, and maybe not read the response body at all.
If the status code is 200, the client will not be looking for an error message in the response body.
An HTTP status code is not redundant. Pretty much in the same way a book's index is not redundant. First you look at the index for a topic you want to read on, and then you flip to that page and read more on that topic. Similarly, the client first reads the status code to know what happened, and then reads the response body to find out more about it.

REST/HTTP: best status code to prevent cached upload?

I'm designing an API where a client PUTs a file to the server, but the server may already have a copy of this file and not need it re-uploaded.
I'm already planning on using Expect: 100-continue so that the server can inform the client before the client performs the entire, inefficient upload.
My question is, what's the best status code to return instead of 100 Continue in the case that the server doesn't need the upload?
Typically, the client could send an If-None-Match header, and the server could respond with a 412 Precondition Failed if there was already a match.
But, in my case, the de-duplication is almost an implementation detail, and I don't want the client to be concerned with knowing the de-dup'ing strategy (e.g. what the value to match is).
Would a 302 Found, a 303 See Other, or a 304 Not Modified make sense?
It doesn't seem like a 4xx is appropriate since it's not a client error, nor 5xx since I don't want to trigger any automatic retry logic in the client.
Thanks!
From the client's point of view, the PUT succeeded. So I believe a 2xx status code would be right; such as 200 with a message body giving a status message.
At least using cURL as a client, it turns out that 304 works great.