WICKET-6599: unwrap ResponseIOException before leaving WicketFilter
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/b1247255 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/b1247255 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/b1247255 Branch: refs/heads/WICKET-6563 Commit: b1247255b12dd3736654bc32a59f54fcd01c0e2c Parents: e749e61 Author: Emond Papegaaij <emond.papega...@topicus.nl> Authored: Thu Oct 18 13:40:11 2018 +0200 Committer: Emond Papegaaij <emond.papega...@topicus.nl> Committed: Thu Oct 18 14:22:49 2018 +0200 ---------------------------------------------------------------------- .../wicket/protocol/http/WicketFilter.java | 37 ++++++++---- .../http/servlet/ResponseIOException.java | 5 ++ .../wicket/protocol/http/WicketFilterTest.java | 63 ++++++++++++++++++++ 3 files changed, 93 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/b1247255/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java index 47d54cc..fb3ee46 100644 --- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java +++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WicketFilter.java @@ -34,6 +34,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.wicket.ThreadContext; import org.apache.wicket.WicketRuntimeException; +import org.apache.wicket.protocol.http.servlet.ResponseIOException; import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.http.WebRequest; import org.apache.wicket.request.http.WebResponse; @@ -152,6 +153,7 @@ public class WicketFilter implements Filter HttpServletRequest httpServletRequest = (HttpServletRequest)request; HttpServletResponse httpServletResponse = (HttpServletResponse)response; + boolean ioExceptionOccurred = false; try { if (previousClassLoader != newClassLoader) @@ -212,18 +214,21 @@ public class WicketFilter implements Filter redirectURL += "?" + httpServletRequest.getQueryString(); } - try - { - // send redirect - this will discard POST parameters if the request is POST - // - still better than getting an error because of lacking trailing slash - httpServletResponse.sendRedirect(httpServletResponse.encodeRedirectURL(redirectURL)); - } - catch (IOException e) - { - throw new RuntimeException(e); - } + // send redirect - this will discard POST parameters if the request is POST + // - still better than getting an error because of lacking trailing slash + httpServletResponse.sendRedirect(httpServletResponse.encodeRedirectURL(redirectURL)); } } + catch (IOException e) + { + ioExceptionOccurred = true; + throw e; + } + catch (ResponseIOException e) + { + ioExceptionOccurred = true; + throw e.getCause(); + } finally { ThreadContext.restore(previousThreadContext); @@ -233,9 +238,17 @@ public class WicketFilter implements Filter Thread.currentThread().setContextClassLoader(previousClassLoader); } - if (response.isCommitted() && httpServletRequest.isAsyncStarted() == false) + if (!ioExceptionOccurred && response.isCommitted() && + !httpServletRequest.isAsyncStarted()) { - response.flushBuffer(); + try + { + response.flushBuffer(); + } + catch (ResponseIOException e) + { + throw e.getCause(); + } } } return res; http://git-wip-us.apache.org/repos/asf/wicket/blob/b1247255/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ResponseIOException.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ResponseIOException.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ResponseIOException.java index e6b3691..c033ba7 100644 --- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ResponseIOException.java +++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ResponseIOException.java @@ -41,4 +41,9 @@ public class ResponseIOException extends WicketRuntimeException implements IWick super(cause); } + @Override + public synchronized IOException getCause() + { + return (IOException)super.getCause(); + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/b1247255/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java b/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java index c12737c..5b4db27 100644 --- a/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/protocol/http/WicketFilterTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; @@ -58,10 +59,15 @@ import org.apache.wicket.mock.MockApplication; import org.apache.wicket.protocol.http.mock.MockHttpServletRequest; import org.apache.wicket.protocol.http.mock.MockHttpServletResponse; import org.apache.wicket.protocol.http.mock.MockServletContext; +import org.apache.wicket.protocol.http.servlet.ResponseIOException; import org.apache.wicket.request.http.WebRequest; import org.apache.wicket.request.resource.AbstractResource; +import org.apache.wicket.request.resource.ContentDisposition; import org.apache.wicket.request.resource.DynamicImageResource; import org.apache.wicket.request.resource.IResource; +import org.apache.wicket.request.resource.AbstractResource.ResourceResponse; +import org.apache.wicket.request.resource.AbstractResource.WriteCallback; +import org.apache.wicket.request.resource.IResource.Attributes; import org.apache.wicket.util.WicketTestTag; import org.apache.wicket.util.file.WebXmlFile; import org.apache.wicket.util.string.Strings; @@ -214,6 +220,63 @@ public class WicketFilterTest } } + /** + * @throws IOException + * @throws ServletException + * @throws ParseException + */ + @Test + public void ioExceptionNotWrapped() throws IOException, ServletException, ParseException + { + assertThrows(IOException.class, this::doIOExceptionNotWrapped); + } + + private void doIOExceptionNotWrapped() throws IOException, ServletException, ParseException + { + try + { + application = new MockApplication(); + WicketFilter filter = new WicketFilter(); + filter.init(new FilterTestingConfig()); + ThreadContext.setApplication(application); + IResource resource = new AbstractResource() + { + private static final long serialVersionUID = 1L; + + @Override + protected ResourceResponse newResourceResponse(Attributes attributes) + { + return new ResourceResponse(); + } + }; + application.getSharedResources().add("foo.txt", resource); + MockHttpServletRequest request = new MockHttpServletRequest(application, null, null); + request.setURL(request.getContextPath() + request.getServletPath() + + "/wicket/resource/" + Application.class.getName() + "/foo.txt"); + setIfModifiedSinceToNextWeek(request); + MockHttpServletResponse response = new MockHttpServletResponse(request) + { + @Override + public void flushBuffer() throws IOException + { + throw new IOException("caused by test"); + } + }; + filter.doFilter(request, response, new FilterChain() + { + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) + throws IOException, ServletException + { + } + }); + } + finally + { + ThreadContext.detach(); + } + } + @Test void options() throws IOException, ServletException, ParseException {