How to keep ResponseBody on 204 No Content response? - java

I want to return a 204 no content http status code. Though I want to add a custom error messages that gives details why where was no content.
Problem: I'm using spring-mvc, and when returning HttpStatus.NO_CONTENT type, the response body is always removed and empty for the client!
#RestControllerAdvice
public class ExeptionHandler {
#ExceptionHandler(Exception.class)
#ResponseStatus(HttpStatus.NO_CONTENT)
public Object handler(HttpServletRequest req, Exception e) {
return new ResponseEntity<String>(e.getMessage(), HttpStatus.NO_CONTENT);
}
}
If I change the type eg to HttpStatus.NOT_FOUND then the error message is shown as response body.
How can I achieve the same with 204?

I want to return a 204 no content HTTP status code. Though I want to add a custom error messages that gives details why where was no content.
You can't.
Problem: I'm using Spring MVC, and when returning HttpStatus.NO_CONTENT type, the response body is always removed and empty for the client!
That's the expected behaviour.
If I change the type eg to HttpStatus.NOT_FOUND then the error message is shown as response body. How can I achieve the same with 204?
You won't achieve it with 204. You are misunderstanding (and probably misusing) such status code. The purpose of 204 is to indicate that the server has successfully fulfilled the request and there's not additional content to send in the response payload.
For reference, see how this status code is defined in the RFC 7231:
6.3.5. 204 No Content
The 204 (No Content) status code indicates that the server has
successfully fulfilled the request and that there is no additional
content to send in the response payload body. [...]
A 204 response is terminated by the first empty line after the header
fields because it cannot contain a message body. [...]
Depending on the situation, you'd better use 404 or 200 with an empty array in the response payload. This answer may give you some insights.

204 is for successful requests. It should have no error message included.
If an error happened, a different HTTP Code should be used.
see https://httpstatuses.com/204
A 204 response is terminated by the first empty line after the header fields because it cannot contain a message body.

Related

Difference between HttpClientErrorException.getStatusText and HttpClientErrorException.getResponseBodyAsString

I use httpResp.sendError(400, "You are missing customer id") to send the response back
When I try to retrieve the message on the client side (using Rest template to call the endpoint).
However, printing the HttpClientErrorException always produces the following result for me:
HttpClientErrorException: 400 null
I see that I have HttpClientErrorException.getResponseBody has all the information about time stamp, message etc. But HttpClientErrorException.getStatusText is always empty.
My question is : How do you design your ResponseEntity on the server-side such that the HTTP client finds the server-side exception message in response.getStatusText() instead of null?
here is the code I have
try{
ResponseEntity<String> responseEntity = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, String.class );
System.out.println(responseEntity.getBody());
}
catch (HttpClientErrorException | HttpServerErrorException e) {
if (e.getStatusCode().equals(HttpStatus.UNAUTHORIZED) || e.getStatusCode().equals(HttpStatus.FORBIDDEN)) { System.out.println("Response Body returned:");
System.out.println(e.getResponseBodyAsString());
System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
System.out.println("Status text is:");
System.out.println(e.getStatusText());
} else if (e.getStatusCode().equals(HttpStatus.BAD_REQUEST)) {
System.out.println("Response Body returned:");
System.out.println(e.getResponseBodyAsString());
System.out.println("-------------------------------");
System.out.println("Status text is:");
System.out.println(e.getStatusText());
} else {
throw e;
}
}
Sprint Boot Version: 2.1.0.RELEASE
I traced the code for how RestTemplate actually makes the calls. Basically what happens is the result of HttpClientErrorException.getStatusText() is populated by the HTTP status code's text and not your custom error message. For example, instead of just returning back error code 400, a server might return back error 400 Bad Request. Instead of status code 200, a server might return back 200 OK. If the server responds back with that optional text, that's what you'll see when you call getStatusText(). Note that that text like OK and Bad Request can't be customized by you on the server side.
This is happening because, internally, Spring is making use of SimpleClientHttpResponse.getStatusText() which is internally relying on HttpUrlConnection.getResponseMessage(). As you can see from getResponseMessage's Javadoc, the possible values returned aren't meant to be custom error messages. Note that in your case, getStatusText() is returning null because your server is just sending back a status line like 400 and not 400 Bad Request. You can also see this from the Javadoc. You can probably configure your server to send back status code text messages, but doing so still won't help you use the getStatusText() method to get your custom error message.
Consequently, the HttpClientErrorException.getStatusText() just isn't what you need. Instead, you need to continue calling getResponseBodyAsString(). However, if you know the format of the response body that is sent back from the server (since this will likely be wrapped in HTML and other stuff) you can use a regex to filter out the non-useful parts of the response message.

OData POST Response

I am giving request to OData POST in Json format and it's returning the same request to me.
POST URL= http://localhost:8085/MagicXpiOData/Odata_get.OData_1/Student_details
Body:
{"Division": "Nashik"}
Content-Type = application/json
Response:
{
"#odata.context": "$metadata#Student_details",
"Division": "Nashik"
}
Is this a correct response?
I think it should return a status code for success or not.
What you show above is the response body, which usually contains the OData.Context. Beside that you should find the HTTP Status Code in the header, which might be something like
HTTP/1.1 200 OK
HTTP/1.1 201 Created
and when you create a new entry also a location header.
Some examples that show typical requests and responses can be found in this Basic Tutorial
So generally your response looks ok. Maybe you can add the response header in your question, then we can see if everything is there what should be there.
When you send your request with a tool like Postman or Fiddler, you might by default only see the response body. To see the headers you need to switch to Headers, or Raw in Fiddler to see the full response (header and body).

What is the HTTP status return code for a successful DELETE statement in REST?

I am studying how to Spring handle REST web services (but I don't know if it is a Spring related answer or more generically it is related only to REST concept).
So my doubt is: what exactly is the HTTP status return code for a successful DELETE statement?
Is it the 204 or the 200?
I know that the 200 means that my request was correctly fulfilled but reading online it seems to me that it I expect it after a successful GET returning content and not after a delete.
Somewhere I found that the 204 status is obtained after
successful PUT or DELETE. Is it true? I can't understand, it means that the response is empty, why an empty respons means that the PUT or the DELETE operation are gone succesfull?
There are no strict rules on which HTTP status code is the correct one for each method. It depends on what exactly happened, what information you need to send to the client, etc. I can think of a few examples:
A successful DELETE, with no further information. 204 No Content
A successful DELETE, but you have a warning about related orphan resources that should be deleted too. 200 OK.
You accepted the DELETE request, but it might take a long time and you're going to do it asynchronously. The client should check it later. 202 Accepted.
You accepted the DELETE request, but the resource can't be removed and the URI is instead reset to a default. 205 Reset Content.
An empty response body doesn't mean that a delete is successful, a successful delete (usually) means that the response body is empty.
There's no official status code list for RESTful APIs, but most agree that a 204 is a good response code for a successful delete, as there's usually not a good reason to return a response body after deleting something.
In general, if an operation is successful and the response body is empty return 204. If an operation is successul and the response body is NOT empty, return 200
An empty response doesn't mean the operation was successful, the HTTP error code is supposed to indicate success/failure, and the response body may or may not contain data.
The response body may contain additional information regarding the request, e.g., a specific message to display to the UI, stats or timing info regarding the information, whatever. But it doesn't have to, and the body's purpose is informational/diagnostic if it exists.
2xx represents the request was successful. The xx just allows for you to be more specific about what happened (what the server did or is returning).

Client gets empty response after setting status to HttpServletResponse

In a java web-app I write to my HttpServletResponse:
httpResponse.getWriter().write(someJsonString);
httpResponse.getWriter().flush();
The client (apache jmeter in this case) gets the response with the json in the body and status 200 as expected.
If I decide to change the response status:
httpResponse.getWriter().write(someJsonString);
httpResponse.setStatus(Response.Status.NO_CONTENT.getStatusCode());
httpResponse.getWriter().flush();
My client gets the response with the right status (204 in this case) but an empty body for some reason.
What can cause this?
When you send response as 204, it means there is no body.
See w3c rfc
The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.
It means while sending response either container is not considering body or your client is discarding after reading status in response.
One way could be to check this response in web-browser if possible. With tools like fire-bug or similar in Chrome you could actual check response.

Get only the response code not the full source of a url

I have an URL and i want only to check the response code of the page and not the complete page source as fetching the the complete page source is quite slow. what is right way to go ?
does getResponseCode() in HttpUrlConnection feches the complete page source or only the header ?
Straight from the docs, HttpUrlConnection#getResponseCode()
Gets the status code from an HTTP response message. For example, in the case of the following status lines:
HTTP/1.0 200 OK
HTTP/1.0 401 Unauthorized
It will return 200 and 401 respectively. Returns -1 if no code can be discerned from the response (i.e., the response is not valid HTTP).
Depends what you're motivation is in making the request. If the request is normally just a GET request for a resource and doesn't have any side effects.
You can perform a HTTP HEAD request instead, which if implemented correctly should get you the same status codes but not the body. (i.e. setRequestMethod(HEAD))
Here method may be PostMethod or GetMethod
you can get status code from an HTTP response message by getStatusCode()
example:-
int statuscode=method.getStatusCode();

Categories

Resources