From dd2c253fce51827789edaada920a3f1b3485e643 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 28 Nov 2024 07:56:07 +1100 Subject: [PATCH] Allow BadMessageException to propagate unwrapped through HttpInput (#12571) Allow BadMessageException to propagate unwrapped through HttpInput. Whilst Jetty handling will correctly unwrap it, 3rd party handling may not. --- .../java/org/eclipse/jetty/server/HttpInput.java | 6 ++++++ .../jetty/server/handler/SizeLimitHandlerTest.java | 2 +- .../jetty/test/HttpInputInterceptorTest.java | 14 ++++++++------ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java index 4ab04aaa79b0..cd94a4b60552 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpInput.java @@ -499,6 +499,10 @@ private Content intercept(Content content) throws IOException { return _interceptor.readFrom(content); } + catch (RuntimeException | Error x) + { + throw x; + } catch (Throwable x) { IOException failure = new IOException("Bad content", x); @@ -1146,6 +1150,8 @@ public int noContent() throws IOException { if (_error instanceof IOException) throw (IOException)_error; + if (_error instanceof RuntimeException) + throw (RuntimeException)_error; throw new IOException(_error); } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/SizeLimitHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/SizeLimitHandlerTest.java index 10373acc4f49..b3fa0da26a4a 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/SizeLimitHandlerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/SizeLimitHandlerTest.java @@ -252,7 +252,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques String text = new String(data, 0, 1024, Charset.defaultCharset()); for (int i = 0; i < 9; i++) - endp.addInput("400\r\n" + text + "\r\n"); + endp.addInput(Integer.toHexString(text.length()) + ";\r\n" + text + "\r\n"); HttpTester.Response response = HttpTester.parseResponse(endp.getResponse()); diff --git a/tests/test-integration/src/test/java/org/eclipse/jetty/test/HttpInputInterceptorTest.java b/tests/test-integration/src/test/java/org/eclipse/jetty/test/HttpInputInterceptorTest.java index 6c76cac81f6c..628702adff35 100644 --- a/tests/test-integration/src/test/java/org/eclipse/jetty/test/HttpInputInterceptorTest.java +++ b/tests/test-integration/src/test/java/org/eclipse/jetty/test/HttpInputInterceptorTest.java @@ -40,6 +40,7 @@ import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.util.BytesContentProvider; +import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpTester; @@ -63,9 +64,10 @@ import org.junit.jupiter.params.provider.ValueSource; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.sameInstance; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -110,10 +112,10 @@ public void handle(String target, Request jettyRequest, HttpServletRequest reque // Throw immediately from the interceptor. jettyRequest.getHttpInput().addInterceptor(content -> { - throw new RuntimeException(); + throw new BadMessageException(); }); - assertThrows(IOException.class, () -> IO.readBytes(request.getInputStream())); + assertThrows(BadMessageException.class, () -> IO.readBytes(request.getInputStream())); serverLatch.countDown(); response.setStatus(HttpStatus.NO_CONTENT_204); } @@ -159,7 +161,7 @@ public void handle(String target, Request jettyRequest, HttpServletRequest reque throw new RuntimeException(); }); - assertThrows(IOException.class, () -> IO.readBytes(request.getInputStream())); + assertThrows(RuntimeException.class, () -> IO.readBytes(request.getInputStream())); serverLatch.countDown(); response.setStatus(HttpStatus.NO_CONTENT_204); } @@ -362,7 +364,7 @@ public void onDataAvailable() // Now the interceptor should throw, but isReady() should not. if (input.isReady()) { - assertThrows(IOException.class, () -> assertEquals(bytes[0], input.read())); + assertThrows(RuntimeException.class, () -> assertEquals(bytes[0], input.read())); readFailureLatch.countDown(); response.setStatus(HttpStatus.NO_CONTENT_204); asyncContext.complete(); @@ -431,7 +433,7 @@ public void onAllDataRead() @Override public void onError(Throwable error) { - assertSame(failure, error.getCause()); + assertThat(failure, anyOf(sameInstance(error), sameInstance(error.getCause()))); response.setStatus(HttpStatus.NO_CONTENT_204); asyncContext.complete(); }