Ensure that ErrorPageFilter handles errors during async dispatch

Previously, the ErrorPageFilter was not invoked for async dispatches.
This meant that an error that was set during an async dispatch would
go undetected and a 200 response with an empty body would be returned.

This commit updates ErrorPageFilter to configure its
OncePerRequestFilter so that async dispatches are filtered and the
correct error handling is performed.

Closes gh-2711
pull/2740/head
Andy Wilkinson 10 years ago
parent c3a040acb3
commit 6d2bb68aba

@ -88,6 +88,11 @@ public class ErrorPageFilter extends AbstractConfigurableEmbeddedServletContaine
ErrorPageFilter.this.doFilter(request, response, chain); ErrorPageFilter.this.doFilter(request, response, chain);
} }
@Override
protected boolean shouldNotFilterAsyncDispatch() {
return false;
}
}; };
@Override @Override

@ -34,6 +34,10 @@ import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockFilterConfig; import org.springframework.mock.web.MockFilterConfig;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.StandardServletAsyncWebRequest;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
@ -373,6 +377,62 @@ public class ErrorPageFilterTests {
assertTrue(this.response.isCommitted()); assertTrue(this.response.isCommitted());
} }
@Test
public void responseIsNotCommitedDuringAsyncDispatch() throws Exception {
setUpAsyncDispatch();
this.filter.doFilter(this.request, this.response, this.chain);
assertThat(this.chain.getRequest(), equalTo((ServletRequest) this.request));
assertThat(((HttpServletResponseWrapper) this.chain.getResponse()).getResponse(),
equalTo((ServletResponse) this.response));
assertFalse(this.response.isCommitted());
}
@Test
public void responseIsCommitedWhenExceptionIsThrownDuringAsyncDispatch()
throws Exception {
this.filter.addErrorPages(new ErrorPage("/error"));
setUpAsyncDispatch();
this.chain = new MockFilterChain() {
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
super.doFilter(request, response);
throw new RuntimeException("BAD");
}
};
this.filter.doFilter(this.request, this.response, this.chain);
assertThat(this.chain.getRequest(), equalTo((ServletRequest) this.request));
assertThat(((HttpServletResponseWrapper) this.chain.getResponse()).getResponse(),
equalTo((ServletResponse) this.response));
assertTrue(this.response.isCommitted());
}
@Test
public void responseIsCommitedWhenStatusIs400PlusDuringAsyncDispatch()
throws Exception {
this.filter.addErrorPages(new ErrorPage("/error"));
setUpAsyncDispatch();
this.chain = new MockFilterChain() {
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
super.doFilter(request, response);
((HttpServletResponse) response).sendError(400, "BAD");
}
};
this.filter.doFilter(this.request, this.response, this.chain);
assertThat(this.chain.getRequest(), equalTo((ServletRequest) this.request));
assertThat(((HttpServletResponseWrapper) this.chain.getResponse()).getResponse(),
equalTo((ServletResponse) this.response));
assertTrue(this.response.isCommitted());
}
@Test @Test
public void responseIsNotFlushedIfStatusIsLessThan400AndItHasAlreadyBeenCommitted() public void responseIsNotFlushedIfStatusIsLessThan400AndItHasAlreadyBeenCommitted()
throws Exception { throws Exception {
@ -419,4 +479,14 @@ public class ErrorPageFilterTests {
assertThat(this.output.toString(), containsString("request [/test/alpha]")); assertThat(this.output.toString(), containsString("request [/test/alpha]"));
} }
private void setUpAsyncDispatch() throws Exception {
this.request.setAsyncSupported(true);
this.request.setAsyncStarted(true);
DeferredResult<String> result = new DeferredResult<String>();
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(this.request);
asyncManager.setAsyncWebRequest(new StandardServletAsyncWebRequest(this.request,
this.response));
asyncManager.startDeferredResultProcessing(result);
}
} }

Loading…
Cancel
Save