-
Notifications
You must be signed in to change notification settings - Fork 38.5k
RestTemplate - support response mapping to entity with potentially empty response body. [SPR-8016] #12671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
sriram commented Same issue for post calls that return 202 accepted with an empty body. |
emanuele commented Same issue for post calls returning 204 - NO CONTENT. The only way to use rest template with this kind of response is to set "null" as ResponseEntity class, but doing so you can't know what response really you had with your call. |
Shai Yallin commented Same issue for any request resulting in 304 Not Modified |
Magnus Heino commented Already fixed. |
David Victor commented Several options documented here too. http://stackoverflow.com/a/5170959/366073 :-) |
Yann Petrick commented I reopened the ticket because parts of the issue are still defect. Responses with status 200 (Ok), a single header "Connection close" and no body still don't get parsed. According to RFC 2616 Section 4.4. Message Length, Part 2 a message can be terminated by closing the connection:
|
Stéphane Nicoll commented What about the documented approach on SO (previous comment)? Can you clarify what you're after please? |
Yann Petrick commented The workaround on SO would do for me, but it would requiere a massive refactoring. In the current setup nginx modifies the requests to include a header "Connection close" . If I use the rest-template to request an entity from the backend behind nginx (e.g. the next queued job) and none was found I get an exception. If I use the rest-tempalte to directly communicate with the jetty the header "Connection close" is not send and jetty sets a header for content-length and it all works. There are many solutions to my problem, But this all are workarounds and in my oppinion the rest-template should be able to handle these responses directy, as they are valid. |
Colin Morelli commented After this change, RestTemplate can no longer communicate with a spring server using Jackson serialization. The server doesn't include the Content-Length in the response, and the client treats that as an empty response body. The commit introduced to fix this issue (9887025) actually appears to have caused the issue. The description indicates that support was to better fit RFC 7230 where a connection is closed and there is neither a content length header nor a transfer-encoding header. However, that is true only for requests. Responses follow a different set of rules with regards to the presence of a message body. Below is quoted from Section 3.3 of RFC 7230:
Because of this, the logic in the "hasMessageBody" method is incorrect in assuming that the lack of a content-length header and a closed connection implies that there is no body. HTTP/1.1 specification allows for the server to signal the send of the response body by closing the connection. |
Brian Clozel commented RestTemplate + Jackson serialization brokenCould you elaborate on this? RFC 7230The RFC does state that this applies for HTTP responses:
Also, Section 3.3.3 explains a bit better how to asses the message length in each case. This is another question that could be raised in a different JIRA issue; but in my opinion it's not related to the RestTemplate+Jackson issue, which I think is more important to investigate first. |
Colin Morelli commented Brian, Looks like you're right here. After digging deeper into the problem, I found out that it was actually the HAProxy load balancer decoding the transfer encoding and removing the header. It doesn't add a content-length in this process, although that appears to be intentional as indicated in this section from the HAProxy documentation:
But this still seems to be a problem, given that the response that HAProxy responds with is a valid HTTP response according to the RFC. My interpretation of:
Is that a response can contain neither transfer-encoding nor content-length, and still contain a 0-n length body where n is the number of bytes received between the completion of the headers and the termination of the connection. In other words, on a closed connection, any content past the HTTP headers should be interpreted as a body. It would appear that browsers treat it this way, given that accessing a page that fails to load in RestTemplate works fine in Chrome, Safari and Firefox. |
Brian Clozel commented Hi Colin, You're right, there's something wrong about this fix. I'll dig into this, but it really looks like I've got to revisit this and HttpMessageConverters implementations to make sure they don't barf when the body is of size 0 and correctly return a null. Unfortunately, the next version is scheduled tomorrow (CET), so this new fix won't make it. |
Colin Morelli commented No problem Brian, thanks for looking into this. In the meantime I can drop down my spring versions and/or change the haproxy configuration to do chunked encoding. A path of least resistance might be to simply wrap the input stream with something that is capable of peeking in on the stream (reading a single byte) to see if there's any content (and caching the received byte to be returned on any calls to read the stream). Not necessarily the best solution, but potentially saves you from having to mess with the HttpMessageConverters. |
Brian Clozel commented OK, I've got a fix ready in a PR |
Koos Gadellaa commented The fix is giving us issues, and I think it's wrong...
The spec reads:
i.e. it is valid if:
so it should read
|
Brian Clozel commented Hi Koos Gadellaa |
Koos Gadellaa commented Ah! I was looking at the 4.1.x branch, and apparently the fix hasn't been merged to it yet... It'll probably work for me, but I currently can't see any checks if the body is valid as given in https://tools.ietf.org/html/rfc7230#section-3.4 (which was originaly referred). |
Brian Clozel commented I'll backport this right now. |
Satyapal Reddy commented we are upgrading from Spring 3.2.2 to Spring 4.1.3/4.1.4 and what used to work earlier started failing due to the logic in hasMessageBody. I looked at 4.1.5 and that may work. But it may be a while before 4.1.5 is released. In our case, server is responding with a body, but with no Content-Length header and with Connection: close. |
Brian Clozel commented Hi Satyapal Reddy Thanks, |
I came along a workaround (not sure if it meets your case): `
`
finally add this interceptor to your restTemplate object as below: and call your restTemplate.postForEntity: Hope it helps. |
David Victor opened SPR-8016* and commented
I am working with an API which returns an empty response body on http status 200 (OK) & a body which is populated on http status 400 (Bad Request).
When using RestTemplate.getForEntity() this is fine for the case where the body is populated, however I get an exception for the 'null body' case.
My understanding is one should provide a class implementing the ResponseBody interface & make the call via the execute() method on the RestTemplate.
This task is a request to consider that the use case here is common & whether Spring should offer something out of the box for this situation.
Also See: http://stackoverflow.com/questions/3322381/spring-resttemplate-behavior-when-handling-responses-with-a-status-of-no-content/3648447#3648447
Affects: 3.1 M1
Issue Links:
9 votes, 19 watchers
The text was updated successfully, but these errors were encountered: