-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Default Cache-Control/Expires/Pragma headers are being added in async response with custom Cache-Control header value #12865
Comments
Any news on this? Are there any easy workarounds other than having to manually set the header for each async endpoint. |
I am experiencing a similar problem on Spring Boot 3.2.2 override suspend fun downloadImage(id: UUID): ResponseEntity<ByteArray> {
return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(30, java.util.concurrent.TimeUnit.DAYS))
.body(imageService.loadImage(id).awaitSingle())
} Those headers are not in the response when CacheControlHeadersWriter adds its own headers, resulting in duplicate headers and frontend applications being confused. My current workaround is to inject the override suspend fun downloadImage(id: UUID): ByteArray {
response.setHeader("Cache-Control", "max-age=2592000")
return imageService.loadImage(id).awaitSingle()
} Please find a way so I can use idiomatic ResponseEntity objects with typesafe CacheControl. |
I apologize for the delay in responding, @cmark. Thanks for reaching out and for providing a reproducer!
The reference docs mention in Spring MVC Async Integration:
I believe this is the reason for this issue. The headers writer fires after the initial controller method returns, but is not able to wait for the One workaround you might consider is to create a separate filter chain for your async endpoint(s) that does not write the @Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
@Order(1)
public SecurityFilterChain asyncSecurityFilterChain(HttpSecurity http) throws Exception {
http
.securityMatcher("/async")
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
.headers((headers) -> headers
.cacheControl((cacheControl) -> cacheControl.disable())
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
// ...
} Given that Spring Security does not integrate with Unfortunately, it appears this issue also exists when returning a |
Hi @sjohnr, Thank you for the detailed explanation and the workaround. In the meantime, we have solved the problem by handling the HTTP header writing ourselves (directly in the
Thanks again, |
Describe the bug
Setting up a basic async HTTP GET endpoint where the returned response is allowed to be cached by downstream clients (via the
Cache-Control
header) produces duplicateCache-Control
header values.Expires
andPragma
headers are also being added.To Reproduce
EnableWebSecurity
annotationDeferredResult
is aResponseEntity
with aCache-Control
header valueHeaders being returned in case of the async HTTP response:
Headers being returned in case of the sync HTTP response:
Expected behavior
Setting
Cache-Control
/Expires
/Pragma
headers in async request processing context should be honored by the security header writer and it should not populate the HTTP response with the default headers in this case.See the sample's sync endpoint for desired behavior.
Sample
https://github.com/cmark/spring-security-async-cache-control
The text was updated successfully, but these errors were encountered: