-
Notifications
You must be signed in to change notification settings - Fork 38.3k
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
ContentCachingResponseWrapper no longer honors Content-Type and Content-Length #32317
Comments
It may be caused by this commit 375e0e6 |
We have the problem that our rest controller, which sits behind a |
Do you specifically see a difference for programmatic calls on the |
spring-framework 5.3.32 may also be affected. After upgrading to it (because of CVE-2024-22243), we no longer had content type headers in responses. So I downgraded back to 5.3.29. (luckily, we don't think we have any endpoints that are vulnerable to the CVE) |
@jhoeller We set them through the |
Thanks for all of the feedback! We're looking into a fix. |
This comment was marked as outdated.
This comment was marked as outdated.
Commit 375e0e6 introduced a regression in ContentCachingResponseWrapper (CCRW). Specifically, CCRW no longer honors Content-Type and Content-Length headers that have been set on the wrapped response and returns null for those header values if they have not been set directly on the CCRW. This commit fixes this regression as follows. - The Content-Type and Content-Length headers set in the wrapped response are honored in getContentType(), containsHeader(), getHeader(), and getHeaders() unless those headers have been set directly on the CCRW. - In copyBodyToResponse(), the Content-Type in the wrapped response is only overridden if the the Content-Type has been set directly on the CCRW. See spring-projectsgh-32039 Closes spring-projectsgh-32317
I've pushed a potential fix to @yikuo123, @amuttsch, @tjalling-ran, and anybody else interested in helping out... We would be grateful if you could try out one of the upcoming If you confirm the fix works, we'll then backport to Cheers, Sam p.s. you can find information on accessing snapshot builds here. |
😎
You're welcome, and glad you found it useful.
Thanks for offering. We'll let you know as soon as we've backported anything to 5.3.x. |
Prior to this commit, getHeaderNames() returned duplicates for the Content-Type and Content-Length headers if they were set in the wrapped response as well as in ContentCachingResponseWrapper. This commit fixes that by returning a unique set from getHeaderNames(). In addition, this commit introduces a new test in ContentCachingResponseWrapperTests to verify the expected behavior for Content-Type and Content-Length headers that are set in the wrapped response as well as in ContentCachingResponseWrapper. See gh-32039 See gh-32317
This comment was marked as outdated.
This comment was marked as outdated.
Commit 375e0e6 introduced a regression in ContentCachingResponseWrapper (CCRW). Specifically, CCRW no longer honors Content-Type and Content-Length headers that have been set in the wrapped response and now incorrectly returns null for those header values if they have not been set directly in the CCRW. This commit fixes this regression as follows. - The Content-Type and Content-Length headers set in the wrapped response are honored in getContentType(), containsHeader(), getHeader(), and getHeaders() unless those headers have been set directly in the CCRW. - In copyBodyToResponse(), the Content-Type in the wrapped response is only overridden if the Content-Type has been set directly in the CCRW. Furthermore, prior to this commit, getHeaderNames() returned duplicates for the Content-Type and Content-Length headers if they were set in the wrapped response as well as in CCRW. This commit fixes that by returning a unique set from getHeaderNames(). This commit also updates ContentCachingResponseWrapperTests to verify the expected behavior for Content-Type and Content-Length headers that are set in the wrapped response as well as in CCRW. See gh-32039 See gh-32317 Closes gh-32321
Commit 375e0e6 introduced a regression in ContentCachingResponseWrapper (CCRW). Specifically, CCRW no longer honors Content-Type and Content-Length headers that have been set in the wrapped response and now incorrectly returns null for those header values if they have not been set directly in the CCRW. This commit fixes this regression as follows. - The Content-Type and Content-Length headers set in the wrapped response are honored in getContentType(), containsHeader(), getHeader(), and getHeaders() unless those headers have been set directly in the CCRW. - In copyBodyToResponse(), the Content-Type in the wrapped response is only overridden if the Content-Type has been set directly in the CCRW. Furthermore, prior to this commit, getHeaderNames() returned duplicates for the Content-Type and Content-Length headers if they were set in the wrapped response as well as in CCRW. This commit fixes that by returning a unique set from getHeaderNames(). This commit also updates ContentCachingResponseWrapperTests to verify the expected behavior for Content-Type and Content-Length headers that are set in the wrapped response as well as in CCRW. See gh-32039 See gh-32317 Closes gh-32322
@yikuo123, @amuttsch, @tjalling-ran, and anybody else interested in helping out... The proposed fix is now available in As mentioned in #32317 (comment), we'd be grateful if you can test against the snapshots and report back here to let us know if the fixes work for you. Thanks! Sam p.s. In the interim, we are leaving this issue "open" until we receive confirmations that the fixes work. |
@sbrannen I tried the 5.3.33-SNAPSHOT build shown in the screenshot below. It still has the issue - that is, there is no ContentType header in the response of the GET-request I tested with, whereas the same request on 5.3.29 does result in a response with the expected ContentType. (screenshot of https://repo.spring.io/ui/native/snapshot/org/springframework/spring-framework-bom/5.3.33-SNAPSHOT/) Judging from the decompiled class in IntelliJ, the snapshot build already has the fix: |
I may have found the issue. (Though I'm not familiar enough with the code to be fully confident that I didn't miss anything.) As you know, As long as So then the question is: how can It will not delegate to the wrapped response's And because a wrapper without content doesn't copy any of its own properties to the wrapped response, the wrapped response's content type (and possibly other properties) will remain |
Thank you very much! I tried the 6.1.5-SNAPSHOT build and the fix works. |
I tried the 6.1.5-SNAPSHOT but it did not work, the
and overwrote the version using |
I created a reproducible setup here: https://github.com/amuttsch/spring-boot-etag-content-header |
Hi everybody, Thanks a lot for all of the prompt feedback! In the end, we decided to revert the So, hopefully that will address all remaining issues. 🤞 See cca440e for details. The latest fix is now available in So, if you're using Once the fix is confirmed by a number of you, we'll then backport to Cheers, Sam |
Thanks for the quick response. My demo code works now, I can check my production code tomorrow. But I think it will most likely work too. |
You're very welcome.
Awesome! Thanks for testing that with lightning fast speed and reporting back. 🚀
That would be much appreciated. Thanks |
Just for the record: as mentioned in spring-projects/spring-boot#39745 (comment): spring-core-6.1.5-20240226.173247-18.jar fixes my issue, umlauts are shown correctly (content-length size is as it was in 6.1.3) Thanks! |
My production code works as well 👍 |
Based on feedback from several members of the community, we have decided to revert the caching of the Content-Type header that was introduced in ContentCachingResponseWrapper in 375e0e6. This commit therefore completely removes Content-Type caching in ContentCachingResponseWrapper and updates the existing tests accordingly. To provide guards against future regressions in this area, this commit also introduces explicit tests for the 6 ways to set the content length in ContentCachingResponseWrapper and modifies a test in ShallowEtagHeaderFilterTests to ensure that a Content-Type header set directly on ContentCachingResponseWrapper is propagated to the underlying response even if content caching is disabled for the ShallowEtagHeaderFilter. See gh-32039 See gh-32317 Closes gh-32321
Based on feedback from several members of the community, we have decided to revert the caching of the Content-Type header that was introduced in ContentCachingResponseWrapper in 375e0e6. This commit therefore completely removes Content-Type caching in ContentCachingResponseWrapper and updates the existing tests accordingly. To provide guards against future regressions in this area, this commit also introduces explicit tests for the 6 ways to set the content length in ContentCachingResponseWrapper and modifies a test in ShallowEtagHeaderFilterTests to ensure that a Content-Type header set directly on ContentCachingResponseWrapper is propagated to the underlying response even if content caching is disabled for the ShallowEtagHeaderFilter. See gh-32039 See gh-32317 Closes gh-32322
The fix has now been backported to If you can test your applications against those snapshots and report back here, that would be great. Thanks, Sam |
I can confirm that the issue is fixed in today's Thank you for the prompt fix @sbrannen. |
Glad to hear it, @tjalling-ran! And thanks for letting us know. |
Just tested with |
Thanks for letting us know it works for you with the 5.3.33 snapshots, @pperalta! |
As of Spring Framework 6.1.4,
ContentCachingResponseWrapper
returnsnull
forContent-Type
andContent-Length
viagetHeader("Content-Type")
,getContentType()
, etc.The text was updated successfully, but these errors were encountered: