Describe the bug I have simple SpringMVC Controller returning StreamingResponseBody
@RestController
class SampleController {
@RequestMapping("/streaming" ,method = [GET])
fun data(): ResponseEntity<StreamingResponseBody> {
return ResponseEntity(
StreamingResponseBody { out ->
out.write("some data".toByteArray())
}, HttpStatus.OK)
}
}
and there is simple test for this controller
@WebMvcTest(SampleController::class)
@ContextConfiguration(classes = [SampleController::class])
internal class SampleControllerTest {
@Autowired
lateinit var mockMvc: MockMvc
@Autowired
lateinit var controller: SampleController
@WithMockUser("my-user")
@Test
@RepeatedTest(100)
fun `StreamingResponseBody response in combination with spring security sometimes fail`() {
// when
val response = mockMvc.perform(MockMvcRequestBuilders.get("/streaming")).andReturn().response
// then
assertThat(response.status).isEqualTo(HttpStatus.OK.value())
}
}
most of the time, the test is OK, but in some cases there is NPE:
java.lang.NullPointerException
at org.springframework.mock.web.MockHttpServletResponse.doAddHeaderValue(MockHttpServletResponse.java:676)
at org.springframework.mock.web.MockHttpServletResponse.addHeaderValue(MockHttpServletResponse.java:629)
at org.springframework.mock.web.MockHttpServletResponse.addHeader(MockHttpServletResponse.java:603)
at javax.servlet.http.HttpServletResponseWrapper.addHeader(HttpServletResponseWrapper.java:174)
at org.springframework.security.web.firewall.FirewalledResponse.addHeader(FirewalledResponse.java:60)
at javax.servlet.http.HttpServletResponseWrapper.addHeader(HttpServletResponseWrapper.java:174)
at org.springframework.security.web.util.OnCommittedResponseWrapper.addHeader(OnCommittedResponseWrapper.java:64)
at org.springframework.security.web.header.writers.StaticHeadersWriter.writeHeaders(StaticHeadersWriter.java:64)
at org.springframework.security.web.header.HeaderWriterFilter.writeHeaders(HeaderWriterFilter.java:99)
at org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterResponse.writeHeaders(HeaderWriterFilter.java:133)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:93)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:183)
at SampleControllerTest.StreamingResponseBody response in combination with spring security sometimes fail(SampleControllerTest.kt:30)
at jdk.internal.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
.... omitted ...
To Reproduce run tests
Expected behavior all tests should pass
Sample there is link to sample project with tests https://github.com/vloo/streaming-response-body-sample
Comment From: eleftherias
Thank you for the sample. It looks like this is a duplicate of gh-9175 (see gh-9176 for the reasoning).
I used the workaround of setting HeaderWriterFilter.shouldWriteHeadersEagerly = true on the sample you provided and the tests passed ever time.
Can you confirm whether that works for you?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.