From 5fd73f0baece1fd347b649b17bae3cc45bb3e315 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 31 Jan 2023 18:45:07 +0100 Subject: [PATCH] Fix MockHttpServletRequest InputStream for empty body Prior to this commit, a recent change applied in gh-29125 changed the behavior of `MockHttpServletRequest` instances. In case of an empty request body, the returned `InputStream` would be static and could not be reused across requests. This could result in `java.io.IOException: Stream closed` exceptions if a previous request was read. This commit ensures that a new instance of an empty stream is returned for each request instance. Fixes gh-29901 --- .../mock/web/MockHttpServletRequest.java | 9 +++------ .../mock/web/MockHttpServletRequestTests.java | 11 +++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java index c012118079..7592528b62 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -101,9 +101,6 @@ public class MockHttpServletRequest implements HttpServletRequest { private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); - private static final ServletInputStream EMPTY_SERVLET_INPUT_STREAM = - new DelegatingServletInputStream(InputStream.nullInputStream()); - private static final BufferedReader EMPTY_BUFFERED_READER = new BufferedReader(new StringReader("")); @@ -513,12 +510,12 @@ public class MockHttpServletRequest implements HttpServletRequest { } else if (this.reader != null) { throw new IllegalStateException( - "Cannot call getInputStream() after getReader() has already been called for the current request") ; + "Cannot call getInputStream() after getReader() has already been called for the current request"); } this.inputStream = (this.content != null ? new DelegatingServletInputStream(new ByteArrayInputStream(this.content)) : - EMPTY_SERVLET_INPUT_STREAM); + new DelegatingServletInputStream(InputStream.nullInputStream())); return this.inputStream; } diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java index 89a728f2f2..2b2348aa2f 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java @@ -82,6 +82,17 @@ class MockHttpServletRequestTests { assertThat(StreamUtils.copyToString(request.getInputStream(), Charset.defaultCharset())).isEqualTo("body"); } + @Test + void readEmptyInputStreamWorksAcrossRequests() throws IOException { + MockHttpServletRequest firstRequest = new MockHttpServletRequest(); + firstRequest.getInputStream().readAllBytes(); + firstRequest.getInputStream().close(); + + MockHttpServletRequest secondRequest = new MockHttpServletRequest(); + secondRequest.getInputStream().readAllBytes(); + secondRequest.getInputStream().close(); + } + @Test void setContentAndGetReader() throws IOException { byte[] bytes = "body".getBytes(Charset.defaultCharset());