How to return Http Status-Line with Error Response? - spring

I am working on a Spring-Boot application. With each response I would like to return http Status-Line, Headers and Body. As per standards a Status-Line looks like: HTTP-Version SP Status-Code SP Reason-Phrase CRLF.
For Example: Http/1.1 400 Bad Request
I am using ResponseEntity with VnDErrors but Status-Line is not forming as per standards. I am able to see only "Http/1.1 400". Here Reason-Phrase is missing.
I have tried with #ResponseBody with #ResponseStatus annotation but no luck to achieve desired result.
Here is piece of code which I am using:
#ExceptionHandler(HttpRequestMethodNotSupportedException)
ResponseEntity<VndErrors> httpRequestMethodNotSupportedException(ex) {
LOGGER.error(ex.message)
ResponseEntity.status(BAD_REQUEST).contentType(VND_ERROR).body(new
VndErrors(BAD_REQUEST, exceptionMessage))
}
Expected reponse which conatins Status-Line: "Http/1.1 400 Bad Request"
Would like to know is this achievable? If yes, then how I can proceed to do same.

This is the standard behavior of tomcat see tomcat-8.5-changelog.html
spring-boot-issue-6789
RFC 7230 states that clients should ignore reason phrases in HTTP/1.1 response messages. Since the reason phrase is optional, Tomcat no longer sends it. As a result the system property org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER is no longer used and has been removed. (markt)

Related

meaning of 'readbody' when when working with ruby http responses

What is readbody supposed to mean/indicate?
"#<Net::HTTPOK 200 OK readbody=true> "
"#<Net::HTTPUnauthorized 401 Unauthorized readbody=true>"
source
I'm going to take a shot and guess that it means that they were able to read the body of the HTTP request.
There's the source code of the #read_body method in the link you provided.
https://github.com/ruby/ruby/blob/fe8cc13685a847f5b4b687d9edb88f5bee58fd70/lib/net/http/response.rb#L19
https://apidock.com/ruby/Net/HTTPResponse/read_body

Spring MVC response Headers: ETag has double quotes for GET request but not for PUT request

We upgraded our Spring MVC from 4.0 to 4.3 in our service. It caused ETag format change in the response headers for "GET" method. Clients making "GET" calls will get ETags with double quotes in the response headers. Previously ETag in the response headers had no double quotes for "GET" method.
For example:
Now: etag →"TVMzTWFpbmxpbmVEZXZvLTI5ODIxMQ"
Previously: etag →TVMzTWFpbmxpbmVEZXZvLTI5ODIxMQ
The response of "PUT" request does not have double quotes around ETag in Headers, just like before.
Anyone has any ideas why?
Prior to Spring 4.2.x, there was no management for the ETag header. It has been introduced since then in the HttpEntityMethodProcessor. The class has evolved during time and the management of the ETag header respect the RFC (or is close enough).
As you can see in this commit, Spring team fixed an issue with its management:
Fix missing ETag/LastModified headers in responses
Prior to this commit, the HttpEntityMethodProcessor would avoid
writing ETag/Last-Modified response headers before calling
ServletWebRequest to process conditional requests. This was done to
avoid duplicate response header values due to headers being already
written to the underlying servlet response.
This is still necessary for GET/HEAD requests, since this is properly
handled by ServletWebRequest for those cases. But
HttpEntityMethodProcessor should not make that decision for
PUT/PATCH/POST responses since developers are adding response headers on
purpose and should be in control of the situation — whereas
ServletWebRequest does not write those headers in those cases.
The relevant part of modified code is here.
So basically, when you are manually adding an ETag header, in case of a 200 status of a GET or HEAD method, the framework removes it, then recreates it. That is why with a PUT, there are no double quotes.
In HttpEntityMethodProcessor:
if (inputMessage.getMethod() == HttpMethod.GET || inputMessage.getMethod() == HttpMethod.HEAD) {
responseHeaders.remove(HttpHeaders.ETAG);
responseHeaders.remove(HttpHeaders.LAST_MODIFIED);
}
Then in ServletWebRequest:
private String padEtagIfNecessary(String etag) {
if (!StringUtils.hasLength(etag)) {
return etag;
}
if ((etag.startsWith("\"") || etag.startsWith("W/\"")) && etag.endsWith("\"")) {
return etag;
}
return "\"" + etag + "\"";
}
As you can see, this respects the chapter 2.4 of the RFC:
2.4. When to Use Entity-Tags and Last-Modified Dates
In 200 (OK) responses to GET or HEAD, an origin server:
o SHOULD send an entity-tag validator unless it is not feasible to
generate one.
o MAY send a weak entity-tag instead of a strong entity-tag, if
performance considerations support the use of weak entity-tags, or
if it is unfeasible to send a strong entity-tag.
o SHOULD send a Last-Modified value if it is feasible to send one.
In other words, the preferred behavior for an origin server is to
send both a strong entity-tag and a Last-Modified value in successful
responses to a retrieval request.
But I found that it is not backward compatible and breaks what developer could have used prior to these versions, without the possibility to skip/override what they did.
Here is the description of the ETag from the MDN (more clearer).
Hope it helped in comprehension.

JAX-RS GET: MessageBodyReader not found for media type=text/plain

I'm getting following error while trying to do JAX-RS GET request:
MessageBodyReader not found for media type=text/plain, type=class com.intuit.accountant.services.common.cdm.Job, genericType=class com.intuit.accountant.services.common.cdm.Job
Below is my code:
Response response = target("jobs/Hello")
.request()
.header("intuit_offeringid", "testOfferingId")
.header(RequestHeaders.REALM, CommonUtil.DEFAULT_REALM_ID_FOR_INTUIT_EMPLOYEE)
.header(RequestHeaders.AUTH, "002923")
.header(RequestHeaders.TICKET,"00303")
.get(Response.class);
What does this error mean? How can I fix this?
You need to post all the code. The error is almost assuredly not happening in that code sample you posted. The get(Response.class) is converting it to a generic http response where you can see the response payload, status, response headers etc.
What you didn't post would most likely look somemthing like this. response.readEntity(com.intuit.accountant.services.common.cdm.Job)
In this case you don't have a reader registered to convert a text/plain response from the server to an entity. I don't know if the response was supposed to be json/xml and you are receiving text because there was an error of some kind. You should check the response as text like this to see what you are getting. This will probably point you in the right direction. If you are getting text you would have to write an implementation of MessageBodyReader to convert the plain text into an entity.
Try this...
System.out.println("Response body is " + response.getEntity(String.class));

HTTP response for validation request

I've got a service that validates names, that can be used to check whether a username is OK. It looks something like this:
POST http://names.myservice.com/validate
content-type: application/json
{"name": "Abdul Hideo McDodgycharacter¬§(*&^$%£!"}
=> 200 OK
{"errors": "contains invalid characters"}
So the point of the service is to check the validity of a proposed username, also checking in my db to see whether it's already been taken. My question is: should the response code be 400 (Bad Request) when there are validation errors?
If I was building a user API to create users, that's what I'd do when presented with Abdul here, but I'm not. In this case the request is for validation, the input data is acceptable, and the response contains the requested representation, which is a list of errors for the supplied data, so a 200 OK feels right. A 400 would indicate my validation request was malformed, and the data to be validated couldn't be identified.
I realise that this isn't very RESTful, because "validate" is basically a verb, so if there's another way to do this that solves my query, please suggest it!
If the request for validation was successful, then 200 (OK) is the correct response code. As far as endpoints, you can consider
POST /validated-names

Overwriting HTTP response headers

Is there a way to overwrite the http response headers returned in Jmeter? I'm testing a web service that returns JSON and when an invalid request is sent, the JSON response returned doesn't contain application/json (or any for that matter) in the response header. If I save the response to a file, I see the actual JSON returned, but looking at the response in a Results tree doesn't show a response. Unless there is a way to load the response from file and parse the error message from the file, I'm hoping to somehow overwrite the HTTP response header and force jmeter to treat the response as JSON.
Any suggestions are welcome!
Using a beanshell post processor, you can write some script that would force the value for the header, or write out to a file.
You can also add a listener that would write the results to file for you. Granted - this is less convenient for debugging then Tree View.
As it turns out JMeter does not support response header overloading. While the response isn't displayed in the Results tree, it is actually available to other assertions. I was able to still provide assertions to validate responses even though the response was missing from the GUI.

Resources