Skip to content

Commit 3fc8ec4

Browse files
committed
MockHttpServletRequest returns a single InputStream or Reader
Issue: SPR-16505 Issue: SPR-16499
1 parent 9aed9bf commit 3fc8ec4

File tree

5 files changed

+113
-38
lines changed

5 files changed

+113
-38
lines changed

spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java

+27-6
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ public class MockHttpServletRequest implements HttpServletRequest {
178178
@Nullable
179179
private String contentType;
180180

181+
@Nullable
182+
private ServletInputStream inputStream;
183+
184+
@Nullable
185+
private BufferedReader reader;
186+
181187
private final Map<String, String[]> parameters = new LinkedHashMap<>(16);
182188

183189
private String protocol = DEFAULT_PROTOCOL;
@@ -492,12 +498,18 @@ public String getContentType() {
492498

493499
@Override
494500
public ServletInputStream getInputStream() {
495-
if (this.content != null) {
496-
return new DelegatingServletInputStream(new ByteArrayInputStream(this.content));
501+
if (this.inputStream != null) {
502+
return this.inputStream;
497503
}
498-
else {
499-
return EMPTY_SERVLET_INPUT_STREAM;
504+
else if (this.reader != null) {
505+
throw new IllegalStateException(
506+
"Cannot call getInputStream() after getReader() has already been called for the current request") ;
500507
}
508+
509+
this.inputStream = (this.content != null ?
510+
new DelegatingServletInputStream(new ByteArrayInputStream(this.content)) :
511+
EMPTY_SERVLET_INPUT_STREAM);
512+
return this.inputStream;
501513
}
502514

503515
/**
@@ -695,16 +707,25 @@ public int getServerPort() {
695707

696708
@Override
697709
public BufferedReader getReader() throws UnsupportedEncodingException {
710+
if (this.reader != null) {
711+
return this.reader;
712+
}
713+
else if (this.inputStream != null) {
714+
throw new IllegalStateException(
715+
"Cannot call getReader() after getInputStream() has already been called for the current request") ;
716+
}
717+
698718
if (this.content != null) {
699719
InputStream sourceStream = new ByteArrayInputStream(this.content);
700720
Reader sourceReader = (this.characterEncoding != null) ?
701721
new InputStreamReader(sourceStream, this.characterEncoding) :
702722
new InputStreamReader(sourceStream);
703-
return new BufferedReader(sourceReader);
723+
this.reader = new BufferedReader(sourceReader);
704724
}
705725
else {
706-
return EMPTY_BUFFERED_READER;
726+
this.reader = EMPTY_BUFFERED_READER;
707727
}
728+
return this.reader;
708729
}
709730

710731
public void setRemoteAddr(String remoteAddr) {

spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java

+33
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
* @author Sam Brannen
4848
* @author Brian Clozel
4949
* @author Jakub Narloch
50+
* @author Av Pinzur
5051
*/
5152
public class MockHttpServletRequestTests {
5253

@@ -112,6 +113,38 @@ public void noContent() throws IOException {
112113
assertNull(request.getContentAsByteArray());
113114
}
114115

116+
@Test // SPR-16505
117+
public void getReaderTwice() throws IOException {
118+
byte[] bytes = "body".getBytes(Charset.defaultCharset());
119+
request.setContent(bytes);
120+
assertSame(request.getReader(), request.getReader());
121+
}
122+
123+
@Test // SPR-16505
124+
public void getInputStreamTwice() throws IOException {
125+
byte[] bytes = "body".getBytes(Charset.defaultCharset());
126+
request.setContent(bytes);
127+
assertSame(request.getInputStream(), request.getInputStream());
128+
}
129+
130+
@Test // SPR-16499
131+
public void getReaderAfterGettingInputStream() throws IOException {
132+
exception.expect(IllegalStateException.class);
133+
exception.expectMessage(
134+
"Cannot call getReader() after getInputStream() has already been called for the current request");
135+
request.getInputStream();
136+
request.getReader();
137+
}
138+
139+
@Test // SPR-16499
140+
public void getInputStreamAfterGettingReader() throws IOException {
141+
exception.expect(IllegalStateException.class);
142+
exception.expectMessage(
143+
"Cannot call getInputStream() after getReader() has already been called for the current request");
144+
request.getReader();
145+
request.getInputStream();
146+
}
147+
115148
@Test
116149
public void setContentType() {
117150
String contentType = "test/plain";

spring-web/src/test/java/org/springframework/http/converter/ObjectToStringHttpMessageConverterTests.java

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -52,14 +52,15 @@ public class ObjectToStringHttpMessageConverterTests {
5252

5353

5454
@Before
55-
public void setUp() {
55+
public void setup() {
5656
ConversionService conversionService = new DefaultConversionService();
5757
this.converter = new ObjectToStringHttpMessageConverter(conversionService);
5858

5959
this.servletResponse = new MockHttpServletResponse();
6060
this.response = new ServletServerHttpResponse(this.servletResponse);
6161
}
6262

63+
6364
@Test
6465
public void canRead() {
6566
assertFalse(this.converter.canRead(Math.class, null));
@@ -121,20 +122,22 @@ public void writeAcceptCharsetTurnedOff() throws IOException {
121122

122123
@Test
123124
public void read() throws IOException {
125+
Short shortValue = Short.valueOf((short) 781);
124126
MockHttpServletRequest request = new MockHttpServletRequest();
125127
request.setContentType(MediaType.TEXT_PLAIN_VALUE);
126-
127-
Short shortValue = Short.valueOf((short) 781);
128-
request.setContent(shortValue.toString().getBytes(
129-
StringHttpMessageConverter.DEFAULT_CHARSET));
128+
request.setContent(shortValue.toString().getBytes(StringHttpMessageConverter.DEFAULT_CHARSET));
130129
assertEquals(shortValue, this.converter.read(Short.class, new ServletServerHttpRequest(request)));
131130

132131
Float floatValue = Float.valueOf(123);
132+
request = new MockHttpServletRequest();
133+
request.setContentType(MediaType.TEXT_PLAIN_VALUE);
133134
request.setCharacterEncoding("UTF-16");
134135
request.setContent(floatValue.toString().getBytes("UTF-16"));
135136
assertEquals(floatValue, this.converter.read(Float.class, new ServletServerHttpRequest(request)));
136137

137138
Long longValue = Long.valueOf(55819182821331L);
139+
request = new MockHttpServletRequest();
140+
request.setContentType(MediaType.TEXT_PLAIN_VALUE);
138141
request.setCharacterEncoding("UTF-8");
139142
request.setContent(longValue.toString().getBytes("UTF-8"));
140143
assertEquals(longValue, this.converter.read(Long.class, new ServletServerHttpRequest(request)));

spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java

+29-12
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ public class MockHttpServletRequest implements HttpServletRequest {
174174

175175
private String contentType;
176176

177+
private ServletInputStream inputStream;
178+
179+
private BufferedReader reader;
180+
177181
private final Map<String, String[]> parameters = new LinkedHashMap<>(16);
178182

179183
private String protocol = DEFAULT_PROTOCOL;
@@ -473,12 +477,18 @@ public String getContentType() {
473477

474478
@Override
475479
public ServletInputStream getInputStream() {
476-
if (this.content != null) {
477-
return new DelegatingServletInputStream(new ByteArrayInputStream(this.content));
480+
if (this.inputStream != null) {
481+
return this.inputStream;
478482
}
479-
else {
480-
return EMPTY_SERVLET_INPUT_STREAM;
483+
else if (this.reader != null) {
484+
throw new IllegalStateException(
485+
"Cannot call getInputStream() after getReader() has already been called for the current request") ;
481486
}
487+
488+
this.inputStream = (this.content != null ?
489+
new DelegatingServletInputStream(new ByteArrayInputStream(this.content)) :
490+
EMPTY_SERVLET_INPUT_STREAM);
491+
return this.inputStream;
482492
}
483493

484494
/**
@@ -507,8 +517,7 @@ public void setParameter(String name, String... values) {
507517
*/
508518
public void setParameters(Map<String, ?> params) {
509519
Assert.notNull(params, "Parameter map must not be null");
510-
for (String key : params.keySet()) {
511-
Object value = params.get(key);
520+
params.forEach((key, value) -> {
512521
if (value instanceof String) {
513522
setParameter(key, (String) value);
514523
}
@@ -519,7 +528,7 @@ else if (value instanceof String[]) {
519528
throw new IllegalArgumentException(
520529
"Parameter map value must be single value " + " or array of type [" + String.class.getName() + "]");
521530
}
522-
}
531+
});
523532
}
524533

525534
/**
@@ -557,8 +566,7 @@ public void addParameter(String name, String... values) {
557566
*/
558567
public void addParameters(Map<String, ?> params) {
559568
Assert.notNull(params, "Parameter map must not be null");
560-
for (String key : params.keySet()) {
561-
Object value = params.get(key);
569+
params.forEach((key, value) -> {
562570
if (value instanceof String) {
563571
addParameter(key, (String) value);
564572
}
@@ -569,7 +577,7 @@ else if (value instanceof String[]) {
569577
throw new IllegalArgumentException("Parameter map value must be single value " +
570578
" or array of type [" + String.class.getName() + "]");
571579
}
572-
}
580+
});
573581
}
574582

575583
/**
@@ -677,16 +685,25 @@ public int getServerPort() {
677685

678686
@Override
679687
public BufferedReader getReader() throws UnsupportedEncodingException {
688+
if (this.reader != null) {
689+
return this.reader;
690+
}
691+
else if (this.inputStream != null) {
692+
throw new IllegalStateException(
693+
"Cannot call getReader() after getInputStream() has already been called for the current request") ;
694+
}
695+
680696
if (this.content != null) {
681697
InputStream sourceStream = new ByteArrayInputStream(this.content);
682698
Reader sourceReader = (this.characterEncoding != null) ?
683699
new InputStreamReader(sourceStream, this.characterEncoding) :
684700
new InputStreamReader(sourceStream);
685-
return new BufferedReader(sourceReader);
701+
this.reader = new BufferedReader(sourceReader);
686702
}
687703
else {
688-
return EMPTY_BUFFERED_READER;
704+
this.reader = EMPTY_BUFFERED_READER;
689705
}
706+
return this.reader;
690707
}
691708

692709
public void setRemoteAddr(String remoteAddr) {

spring-web/src/test/java/org/springframework/web/filter/FormContentFilterTests.java

+15-14
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ public class FormContentFilterTests {
5050
@Before
5151
public void setup() {
5252
this.request = new MockHttpServletRequest("PUT", "/");
53-
this.request.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=ISO-8859-1");
5453
this.request.setContentType("application/x-www-form-urlencoded; charset=ISO-8859-1");
5554
this.response = new MockHttpServletResponse();
5655
this.filterChain = new MockFilterChain();
@@ -59,29 +58,31 @@ public void setup() {
5958

6059
@Test
6160
public void wrapPutPatchAndDeleteOnly() throws Exception {
62-
this.request.setContent("foo=bar".getBytes("ISO-8859-1"));
6361
for (HttpMethod method : HttpMethod.values()) {
64-
this.request.setMethod(method.name());
62+
MockHttpServletRequest request = new MockHttpServletRequest(method.name(), "/");
63+
request.setContent("foo=bar".getBytes("ISO-8859-1"));
64+
request.setContentType("application/x-www-form-urlencoded; charset=ISO-8859-1");
6565
this.filterChain = new MockFilterChain();
66-
this.filter.doFilter(this.request, this.response, this.filterChain);
66+
this.filter.doFilter(request, this.response, this.filterChain);
6767
if (method == HttpMethod.PUT || method == HttpMethod.PATCH || method == HttpMethod.DELETE) {
68-
assertNotSame(this.request, this.filterChain.getRequest());
68+
assertNotSame(request, this.filterChain.getRequest());
6969
}
7070
else {
71-
assertSame(this.request, this.filterChain.getRequest());
71+
assertSame(request, this.filterChain.getRequest());
7272
}
7373
}
7474
}
7575

7676
@Test
7777
public void wrapFormEncodedOnly() throws Exception {
78-
this.request.setContent("".getBytes("ISO-8859-1"));
7978
String[] contentTypes = new String[] {"text/plain", "multipart/form-data"};
8079
for (String contentType : contentTypes) {
81-
this.request.setContentType(contentType);
80+
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/");
81+
request.setContent("".getBytes("ISO-8859-1"));
82+
request.setContentType(contentType);
8283
this.filterChain = new MockFilterChain();
83-
this.filter.doFilter(this.request, this.response, this.filterChain);
84-
assertSame(this.request, this.filterChain.getRequest());
84+
this.filter.doFilter(request, this.response, this.filterChain);
85+
assertSame(request, this.filterChain.getRequest());
8586
}
8687
}
8788

@@ -146,7 +147,7 @@ public void getParameterValues() throws Exception {
146147
String[] values = this.filterChain.getRequest().getParameterValues("name");
147148

148149
assertNotSame("Request not wrapped", this.request, filterChain.getRequest());
149-
assertArrayEquals(new String[]{"value1", "value2", "value3", "value4"}, values);
150+
assertArrayEquals(new String[] {"value1", "value2", "value3", "value4"}, values);
150151
}
151152

152153
@Test
@@ -160,7 +161,7 @@ public void getParameterValuesFromQueryString() throws Exception {
160161
String[] values = this.filterChain.getRequest().getParameterValues("name");
161162

162163
assertNotSame("Request not wrapped", this.request, this.filterChain.getRequest());
163-
assertArrayEquals(new String[]{"value1", "value2"}, values);
164+
assertArrayEquals(new String[] {"value1", "value2"}, values);
164165
}
165166

166167
@Test
@@ -173,7 +174,7 @@ public void getParameterValuesFromFormContent() throws Exception {
173174
String[] values = this.filterChain.getRequest().getParameterValues("anotherName");
174175

175176
assertNotSame("Request not wrapped", this.request, this.filterChain.getRequest());
176-
assertArrayEquals(new String[]{"anotherValue"}, values);
177+
assertArrayEquals(new String[] {"anotherValue"}, values);
177178
}
178179

179180
@Test
@@ -211,7 +212,7 @@ public void hiddenHttpMethodFilterFollowedByHttpPutFormContentFilter() throws Ex
211212
this.request.addParameter("hiddenField", "testHidden");
212213
this.filter.doFilter(this.request, this.response, this.filterChain);
213214

214-
assertArrayEquals(new String[]{"testHidden"},
215+
assertArrayEquals(new String[] {"testHidden"},
215216
this.filterChain.getRequest().getParameterValues("hiddenField"));
216217
}
217218

0 commit comments

Comments
 (0)