Skip to content
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

StringHttpMessageConverter flush out response immediately before execute posthandler [SPR-16046] #20595

Closed
spring-issuemaster opened this issue Oct 4, 2017 · 2 comments
Assignees

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Oct 4, 2017

eric wang opened SPR-16046 and commented

the problem is related @RequestBody the ajax request, if the response content-type is text/plain that means the handler method return string directly, the StringHttpMessageConverter will getting used to handler the HTTP message convert. the problem seems in the writeInternal method, it is calling StreamUtils.copy(String in, Charset charset, OutputStream out) which will create a new Write and flush the response content out immediately.

this problem caused all subsequence handlers like posthandler got executed after response return to the client.

the repro steps should be easy, just create a controller with @ResponseBody and return string directly.


Affects: 4.3.11

Issue Links:

  • #13864 Response is committed before Interceptor postHandle invoked ("duplicates")
  • #12553 Make HandlerInterceptor play nice with @ResponseBody
@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Oct 4, 2017

Elizabeth Hartoog commented

I work with Eric, and I was the one having the issue. I wrote this email to my fellow developers to inform them off the issue:

There is a bug in the spring framework that causes responses using @ResponseBody to not execute interceptor posthandlers before the response is returned to the client. Specifically, if you have a response type of String for your response body, it will use a message converter that is bugged. This mostly applies to calls made by the javascript to [app name], aka [ajax call] request mappings.

So if you have a request mapping that fits this description, be aware that any cookies or response changes made in the posthandler will not be executed until after the response is already returned to the client. Session updates will still execute and will probably still work as expected.

Eric uses Spring 4. I use Spring 3 MVC.

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 7, 2018

Brian Clozel commented

Hello eric wang, Elizabeth Hartoog,

Thanks for reaching out!
This is in fact working as designed (or a known limitation of the WebRequestInterceptor, depending on how you see it).

As explained in the WebRequestInterceptor javadoc:

This interface assumes MVC-style request processing: A handler gets executed,
exposes a set of model objects, then a view gets rendered based on that model.
Alternatively, a handler may also process the request completely, with no
view to be rendered.

In the case of @ResponseBody methods, no view rendering is involved and the whole response is rendered by the handler. So it's not technically about this HttpMessageConverter, but more:

  • if a HttpMessageConverter flushes (like the String one, or the Jackson library itself for JSON payloads), the response is committed
  • if the response buffer fills up, the container may flush the response anyway

Your only choice here is to consider a different infrastructure, like using a ContentCachingResponseWrapper in a Servlet Filter (see ShallowEtagHeaderFilter. You can also get more background information about that in the comments section of #13864.

Feel free to comment here with specifics about your use case so that we can discuss your best options here.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.