Proper Http status codes for uploading files on rest end point - java

We are developing an application that allows a user to upload file on rest end point.
Could someone please guide if it is correct to send 400 error code for the failure of following validation scenario:
1) The Length of file name exceeds permissible limit.
2) File name contains special characters
3) Uploaded file was empty
4) The System failed to read the uploaded file from disk.
Regards,
Tarun

The Length of file name exceeds permissible limit.
I think the 400 is not an appropriate because syntax of the request is correct in this case. The 422 Unprocessable Entity is better in this case.
File name contains special characters
Illegal characters mean the syntax is broken. So 400 Bad Request is a proper response in this case. Someone may claim that a definition of illegal characters is needed so the server may authoritatively send 400.
Uploaded file was empty
I think it is not an error because an empty file is a legal file.
The System failed to read the uploaded file from disk.
Does the system mean the server? Then the server should return a 5xx response because it is not a client failure. In case of general read error the server should return 500.
EDIT:
Uploaded file was empty.
When application semantic forbids an empty file the 400 or 422 appropriate. More details about them is at 400 vs 422 response to POST of data

4xx statuses are for client-side errors, 5xx are for server-side errors. So, generally you need 4xx codes for your cases 1) to 3), while 4) should be a 5xx error.
Let’s first say that for your case 4), a simple HTTP 500 seems appropriate. If you want to indicate that the client could try again later, HTTP 503 would be more suitable.
Now for 1) to 3): According to RFC 2616, HTTP 400 indicates syntax errors; this would usually be protocoll errors, e.g. invalid headers. Semantical or payload errors aren’t really defined in this generic RFC, however, (as Zaboj mentions) WebDAV offers HTTP 422, which seems suitable, though it’s not really meant for generic HTTP.
In the end, it doesn’t really matter which particular codes you send. If your upload fails with HTTP 400 or 422, in either case the client will perform some error routine (e.g. show or log the error message).
The important thing to know is that some codes can trigger client behaviour (e.g. HTTP 401 combined with certain headers can trigger an authentication dialog in a browser), and you should be aware of these side effects.
In my opinion, it is much more important to send a useful error description in the response body to help the client fix their problem, than finding the “perfect” HTTP status code. I know that REST zealots will disagree, but none of them will be able to give you the right HTTP status code for every situation.
That said, if you want to issue fine-grained error codes/messages for automated processing, you can introduce custom HTTP header fields, e.g.
X-MyApp-Error-Code: 2.1.6
X-MyApp-Error-Message: The uploaded file is empty
Then you would provide a documentation and/or SDK which reveals all possible error code values for X-MyApp-Error-Code to your API consumers.

Related

Should HTTP codes be used to represent Business Failure?

My team had a discussion early this week about if HTTP Codes should represent Business Failures.
Imagine a scenario where we have a Customer REST API. Within that API, we have lots of operations, like:
POST - mydomain.com/customers (receive a JSON body and create a new Customer)
GET - mydomain.com/customers/{id} (search for a specific Customer)
PATCH - mydomain.com/customers/{id} (receive a JSON body and patch a specific Customer)
DELETE - mydomain.com;customers/{id} (deletes a specific Customer)
Now, imagine a situation where I'm looking for a Customer which has the id = 5.
There's no Customer with the id = 5. What should I do in terms of HTTP status code?
Customer not found is a Business Failure. Should I return a 404 - NOT FOUND? Should I return a 200 - OK (with a JSON body describing that the Customer with ID 5 do not exist)?
We had a discussion exactly on that behavior.
Controller.java (example)
#GetMapping("/customers/{id}")
public ResponseEntity<?> handleRequestOfRetrieveCustomerById(#PathVariable("id") Integer id) throws CustomerNotFoundException {
try {
ResponseEntity.ok(customerService.findCustomerById(id));
} catch(CustomerNotFoundException e) {
// log at Controller level and rethrow
throw e;
}
}
Handler.java (example)
#ExceptionHandler(BusinessResourceNotFoundException.class)
#ResponseBody
protected ResponseEntity<Fault> handleExceptionOfBusinessResourceNotFound(BusinessResourceNotFoundException exception) {
return new ResponseEntity<Fault>(exception.getFault(), HttpStatus.NOT_FOUND);
}
In this example, a 404 - NOT FOUND is returned with a body giving more details to the client.
From reading the HTTP/1.1 Specification:
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.
If "The server has not found anything matching the Request-URI...", I understand that returning a 404 - NOT FOUND would be the correct approach., since the /id composes my URI (mydomain.com/customers/id)
Am I right?
Which one is the better / right (if there's a wrong way) approach?
Status codes are meant to describe the result of the server's attempt to understand and satisfy the client's corresponding request.
Ultimately, if a client requests a representation of a resource that doesn't exist, the server should return 404 to indicate that. It's essentially a client error and should be reported as such.
Returning 200 would be misleading and would cause confusion to API clients.
Sometimes the HTTP status codes are not sufficient to convey enough information about an error to be helpful.
The RFC 7807 was created to define 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.
Technically and from the http point of view, 404 should also be returned for any misspelling of the entity name (cutsomer instead of customer).
So even if you decide that "customer not found" will result in http 404, you cannot conclude that http 404 will imply "entity occurrence not found".
HTTP codes exist for a reason. Whoever consumes your API should be able to handle the response straight away, without having to result on the body contents.
In your case, 404(Not Found) looks quite suitable.
Alternatively, if you always return a 200, doesn't that beat the purpose of a response code altogether? If you are getting a response, you already know that your request got through to some extent.
TLDR;
Use 404 :)
I have recently worked on a Rest API with Spring Boot and the best practices found on the internet said this :
Parameters null or value not set : 400 / Bad request
Returned value not found (record or list empty) : 404 / Not found
Exception from server (database error, network error etc.) : 500 / Internal server error
Those links will help you : best practice error handling, ControllerAdvice, error message
A REST API is part of the integration domain, not the business domain. It's a skin that your domain model wears to disguise itself as a web site aka an HTTP compliant key value store.
Here, 404 is an appropriate choice because it mimics the response that would be returned by a key value store if you tried to get a key that wasn't currently stored.
I would follow the meaning of HTTP status codes.
Wiki says (https://en.wikipedia.org/wiki/List_of_HTTP_status_codes):
This class of status code is intended for situations in which the error seems to have been caused by the client
So to be clear: mydomain.com/customers/{id} is a valid URL an the server understands the request. The fact that customer with id=5 doesn't exists has nothing to do with a "false URL" or "not understandable request".
In my opinion this should return some 2xx status code with further information inside json (definitions made by your REST API)

Rest error codes/ success code

I am working on REST project using jersey. On success I am returning 200 code along with the json response for particular request. I know there are may different classifications of error codes, like server error which start with 500, client error which start with 400 etc. My question is suppose we are subtracting some value in database for example count, for example count in database is 5 and request comes to subtract 3, it is valid and i will send request but my business rule states that count cannot be less than zero, so if request comes 6, i cannot subtract that , so in that case should i actually send status code as 200 and send error information is json respose {"errorCode" : "1","errorMessage":""} so i should send different HTTP status code like 5## that there is server problem or 4## saying bad request.
Can anyone please suggest me good (in the sense which is restful and follow all standars) REST project on github which I can refer.
If any error occurs during request processing you should never send a 2XX status code. Why? Because 2XX indicates successful processing which in this particular situation did not happen.
When you send a value to be subtracted from another value in DB and the assumption is that the result can't be lower than 0 you should reply with 409 Conflict HTTP status code and clarification in a response body stating e.g.:
The request can't be completed since the result value will be lower than 0.
It would be 400 Bad Request if null e.g. is sent instead of a number.
In the particular use case, you mentioned, you should return 400 as status code (bad request). errorCode in the json is your business domain, so you can use what you want ( Also, take a look at JSend standard for sending the http "error status" in the response https://labs.omniti.com/labs/jsend )
You're exactly right: you should send an HTTP "400" for a client error, a "500" for a server error, etc; along with a specific error message.
You may or may not want more granular HTTP status codes (for example, "403" for client authentication failed, otherwise "400" for other client-related errors).
Are are two good lists you can use for guidance:
Common MS-Azure REST Error Codes
HTTP Status Codes
NOTE:
There is no "standard" per se. The two links I gave above are useful "examples". The "official" IETF RFC for HTTP 1.1 Error codes is RFC 2616:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Spring REST tutorial [duplicate]

I'm building a REST API, but I've encountered a problem.
It seems that accepted practice in designing a REST API is that if the resource requested doesn't exist, a 404 is returned.
However, to me, this adds unnecessary ambiguity. HTTP 404 is more traditionally associated with a bad URI. So in effect we're saying "Either you got to the right place, but that specific record does not exist, or there's no such location on the Internets! I'm really not sure which one..."
Consider the following URI:
http://mywebsite/api/user/13
If I get a 404 back, is that because User 13 does not exist? Or is it because my URL should have been:
http://mywebsite/restapi/user/13
In the past, I've just returned a NULL result with an HTTP 200 OK response code if the record doesn't exist. It's simple, and in my opinion very clean, even if it's not necessarily accepted practice. But is there a better way to do this?
404 is just the HTTP response code. On top of that, you can provide a response body and/or other headers with a more meaningful error message that developers will see.
Use 404 if the resource does not exist. Don't return 200 with an empty body.
This is akin to undefined vs empty string (e.g. "") in programming. While very similar, there is definitely a difference.
404 means that nothing exists at that URI (like an undefined variable in programming). Returning 200 with an empty body means that something does exist there and that something is just empty right now (like an empty string in programming).
404 doesn't mean it was a "bad URI". There are special HTTP codes that are intended for URI errors (e.g. 414 Request-URI Too Long).
As with most things, "it depends". But to me, your practice is not bad and is not going against the HTTP spec per se. However, let's clear some things up.
First, URI's should be opaque. Even if they're not opaque to people, they are opaque to machines. In other words, the difference between http://mywebsite/api/user/13, http://mywebsite/restapi/user/13 is the same as the difference between http://mywebsite/api/user/13 and http://mywebsite/api/user/14 i.e. not the same is not the same period. So a 404 would be completely appropriate for http://mywebsite/api/user/14 (if there is no such user) but not necessarily the only appropriate response.
You could also return an empty 200 response or more explicitly a 204 (No Content) response. This would convey something else to the client. It would imply that the resource identified by http://mywebsite/api/user/14 has no content or is essentially nothing. It does mean that there is such a resource. However, it does not necessarily mean that you are claiming there is some user persisted in a data store with id 14. That's your private concern, not the concern of the client making the request. So, if it makes sense to model your resources that way, go ahead.
There are some security implications to giving your clients information that would make it easier for them to guess legitimate URI's. Returning a 200 on misses instead of a 404 may give the client a clue that at least the http://mywebsite/api/user part is correct. A malicious client could just keep trying different integers. But to me, a malicious client would be able to guess the http://mywebsite/api/user part anyway. A better remedy would be to use UUID's. i.e. http://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66 is better than http://mywebsite/api/user/14. Doing that, you could use your technique of returning 200's without giving much away.
That is an very old post but I faced to a similar problem and I would like to share my experience with you guys.
I am building microservice architecture with rest APIs. I have some rest GET services, they collect data from back-end system based on the request parameters.
I followed the rest API design documents and I sent back HTTP 404 with a perfect JSON error message to client when there was no data which align to the query conditions (for example zero record was selected).
When there was no data to sent back to the client I prepared an perfect JSON message with internal error code, etc. to inform the client about the reason of the "Not Found" and it was sent back to the client with HTTP 404. That works fine.
Later I have created a rest API client class which is an easy helper to hide the HTTP communication related code and I used this helper all the time when I called my rest APIs from my code.
BUT I needed to write confusing extra code just because HTTP 404 had two different functions:
the real HTTP 404 when the rest API is not available in the given url, it is thrown by the application server or web-server where the rest API application runs
client get back HTTP 404 as well when there is no data in database based on the where condition of the query.
Important: My rest API error handler catches all the exceptions appears in the back-end service which means in case of any error my rest API always returns with a perfect JSON message with the message details.
This is the 1st version of my client helper method which handles the two different HTTP 404 response:
public static String getSomething(final String uuid) {
String serviceUrl = getServiceUrl();
String path = "user/" + , uuid);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_UTF8)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
// HTTP 200
return response.readEntity(String.class);
} else {
// confusing code comes here just because
// I need to decide the type of HTTP 404...
// trying to parse response body
try {
String responseBody = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(responseBody, ErrorInfo.class);
// re-throw the original exception
throw new MyException(errorInfo);
} catch (IOException e) {
// this is a real HTTP 404
throw new ServiceUnavailableError(response, requestUrl, httpMethod);
}
// this exception will never be thrown
throw new Exception("UNEXPECTED ERRORS, BETTER IF YOU DO NOT SEE IT IN THE LOG");
}
BUT, because my Java or JavaScript client can receive two kind of HTTP 404 somehow I need to check the body of the response in case of HTTP 404. If I can parse the response body then I am sure I got back a response where there was no data to send back to the client.
If I am not able to parse the response that means I got back a real HTTP 404 from the web server (not from the rest API application).
It is so confusing and the client application always needs to do extra parsing to check the real reason of HTTP 404.
Honestly I do not like this solution. It is confusing, needs to add extra bullshit code to clients all the time.
So instead of using HTTP 404 in this two different scenarios I decided that I will do the following:
I am not using HTTP 404 as a response HTTP code in my rest application anymore.
I am going to use HTTP 204 (No Content) instead of HTTP 404.
In that case client code can be more elegant:
public static String getString(final String processId, final String key) {
String serviceUrl = getServiceUrl();
String path = String.format("key/%s", key);
String requestUrl = serviceUrl + path;
String httpMethod = "GET";
log(requestUrl);
Response response = client
.target(serviceUrl)
.path(path)
.request(ExtendedMediaType.APPLICATION_JSON_UTF8)
.header(CustomHttpHeader.PROCESS_ID, processId)
.get();
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
return response.readEntity(String.class);
} else {
String body = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ErrorInfo errorInfo = mapper.readValue(body, ErrorInfo.class);
throw new MyException(errorInfo);
}
throw new AnyServerError(response, requestUrl, httpMethod);
}
I think this handles that issue better.
If you have any better solution please share it with us.
404 Not Found technically means that uri does not currently map to a resource. In your example, I interpret a request to http://mywebsite/api/user/13 that returns a 404 to imply that this url was never mapped to a resource. To the client, that should be the end of conversation.
To address concerns with ambiguity, you can enhance your API by providing other response codes. For example, suppose you want to allow clients to issue GET requests the url http://mywebsite/api/user/13, you want to communicate that clients should use the canonical url http://mywebsite/restapi/user/13. In that case, you may want to consider issuing a permanent redirect by returning a 301 Moved Permanently and supply the canonical url in the Location header of the response. This tells the client that for future requests they should use the canonical url.
So in essence, it sounds like the answer could depend on how the request is formed.
If the requested resource forms part of the URI as per a request to http://mywebsite/restapi/user/13 and user 13 does not exist, then a 404 is probably appropriate and intuitive because the URI is representative of a non-existent user/entity/document/etc. The same would hold for the more secure technique using a GUID http://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66 and the api/restapi argument above.
However, if the requested resource ID was included in the request header [include your own example], or indeed, in the URI as a parameter, eg http://mywebsite/restapi/user/?UID=13 then the URI would still be correct (because the concept of a USER does exits at http://mywebsite/restapi/user/); and therefore the response could reasonable be expected to be a 200 (with an appropriately verbose message) because the specific user known as 13 does not exist but the URI does. This way we are saying the URI is good, but the request for data has no content.
Personally a 200 still doesn't feel right (though I have previously argued it does). A 200 response code (without a verbose response) could cause an issue not to be investigated when an incorrect ID is sent for example.
A better approach would be to send a 204 - No Contentresponse. This is compliant with w3c's description *The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.*1 The confusion, in my opinion is caused by the Wikipedia entry stating 204 No Content - The server successfully processed the request, but is not returning any content. Usually used as a response to a successful delete request. The last sentence is highly debateable. Consider the situation without that sentence and the solution is easy - just send a 204 if the entity does not exist. There is even an argument for returning a 204 instead of a 404, the request has been processed and no content has been returned! Please be aware though, 204's do not allow content in the response body
Sources
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
1. http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
This old but excellent article... http://www.infoq.com/articles/webber-rest-workflow says this about it...
404 Not Found - The service is far too lazy (or secure) to give us a real reason why our request failed, but whatever the reason, we need to deal with it.
This recently came up with our team.
We use both 404 Not found with a message body and 204 No Content based on the following rational.
If the request URI indicates the location of a single resource, we use 404 Not found. When the request queries a URI, we use 204 No Content
http://mywebsite/api/user/13 would return 404 when user 13 does not exist
http://mywebsite/api/users?id=13 would return 204 no content
http://mywebsite/api/users?firstname=test would return 204 no content
The idea here being, 'query routes' are expected to be able to return 1, many or no content.
Whatever pattern you choose, the most important things is to be consistent - so get buy in from your team.
The Uniform Resource Identifier is a unique pointer to the resource. A poorly form URI doesn't point to the resource and therefore performing a GET on it will not return a resource. 404 means The server has not found anything matching the Request-URI. If you put in the wrong URI or bad URI that is your problem and the reason you didn't get to a resource whether a HTML page or IMG.
Since this discussion seems to be able to survive the end of time I'll throw in the JSON:API Specifications
404 Not Found
A server MUST respond with 404 Not Found when processing a request to fetch a single resource that does not exist, except when the request warrants a 200 OK response with null as the primary data (as described above).
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "http://example.com/articles/1/author"
},
"data": null
}
Also please see this Stackoverflow question
For this scenario HTTP 404 is response code for the response from the REST API
Like 400, 401, 404 , 422 unprocessable entity
use the Exception handling to check the full exception message.
try{
// call the rest api
} catch(RestClientException e) {
//process exception
if(e instanceof HttpStatusCodeException){
String responseText=((HttpStatusCodeException)e).getResponseBodyAsString();
//now you have the response, construct json from it, and extract the errors
System.out.println("Exception :" +responseText);
}
}
This exception block give you the proper message thrown by the REST API

Error in a middle of writing to outputstream handling

I'm building an httpserver as part of my academic java course,
The server should only support basic GET and POST requests.
I was wondering if there's an elegant way to handle an error which occures in the middle of writing an html file stream content (and after I've already sent the response headers) into the HttpServer output stream.
By elegant way I refer to showing or redirecting the user to a "Internal Server Error" error page.
I tried re-sending the http response headers with 501 error code, but java throws an exception which claims that the headers were already sent...
One fix would be to read the file's contents into memory, and only then sending the headers and the content, but other problems can arise, and furthermore, I don't want to load huge files into the memory before sending them out as a response.
Once the response status is sent on the wire, it cannot be changed. So if you sent a 200 OK response, you cannot change your mind afterwards. As you found, this presents a problem in case of errors that occur mid response.
As far as I know, the only think you can do is to send a chunked response. See section 3.6.1 of RFC 2616:
The chunked encoding modifies the body of a message in order to
transfer it as a series of chunks, each with its own size indicator,
followed by an OPTIONAL trailer containing entity-header fields. This
allows dynamically produced content to be transferred along with the
information necessary for the recipient to verify that it has received
the full message.
The purpose of this trailer is to give information about the entity body that cannot be calculated before the entity body is sent. However, section 7.1 allows any header to be included in this trailer:
The extension-header mechanism allows additional entity-header fields
to be defined without changing the protocol, but these fields cannot
be assumed to be recognizable by the recipient. Unrecognized header
fields SHOULD be ignored by the recipient and MUST be forwarded by
transparent proxies.
So while you can signal that an error has occurred mid response, it must be conventioned between the two parts how this is signaled. You cannot, in general, use any method you can assume the client will understand as signaling an error condition.
Ending the connection prematurely in a message with a Content-length header is an option, but one that is explicitly forbidden:
When a Content-Length is given in a message where a message-body is
allowed, its field value MUST exactly match the number of OCTETs in
the message-body. HTTP/1.1 user agents MUST notify the user when an
invalid length is received and detected.
That said, while the server must not send a message shorter than he advertises, the client must check for this error condition and reported as such (and proxies may even cache this partial response).
By elegant way I refer to showing or redirecting the user to a
"Internal Server Error" error page.
If you can't send the 'success' response how are you going to send a different response? All you can do is log it and forget about it.

Interview Question - How to handle SOAP Based and REST based Exceptions

Can some one provide a very specific and to the point answer for this question ?
I think the basics of it are, with REST you should return the proper http response code and enough information for the client to correct the error, e.g. 404 if the resource can't be found, 400 if they client sent a bad request, 500 if the server generated an exception, etc. With SOAP it looks like you always have to return a 500 Response code and a special SOAP message that says exactly what the error was (according to the SOAP spec).
Here is a blog post comparing the two.

Categories