Skip to content

Commit 69c330d

Browse files
committed
Attempt fallback Part resolution even without StandardMultipartHttpServletRequest
Closes gh-25829
1 parent ec9de94 commit 69c330d

File tree

2 files changed

+60
-26
lines changed

2 files changed

+60
-26
lines changed

spring-web/src/main/java/org/springframework/web/multipart/support/RequestPartServletServerHttpRequest.java

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 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.
@@ -22,11 +22,13 @@
2222
import java.nio.charset.Charset;
2323

2424
import javax.servlet.http.HttpServletRequest;
25+
import javax.servlet.http.Part;
2526

2627
import org.springframework.http.HttpHeaders;
2728
import org.springframework.http.MediaType;
2829
import org.springframework.http.server.ServerHttpRequest;
2930
import org.springframework.http.server.ServletServerHttpRequest;
31+
import org.springframework.lang.Nullable;
3032
import org.springframework.web.multipart.MultipartException;
3133
import org.springframework.web.multipart.MultipartFile;
3234
import org.springframework.web.multipart.MultipartHttpServletRequest;
@@ -46,58 +48,75 @@ public class RequestPartServletServerHttpRequest extends ServletServerHttpReques
4648

4749
private final MultipartHttpServletRequest multipartRequest;
4850

49-
private final String partName;
51+
private final String requestPartName;
5052

51-
private final HttpHeaders headers;
53+
private final HttpHeaders multipartHeaders;
5254

5355

5456
/**
5557
* Create a new {@code RequestPartServletServerHttpRequest} instance.
5658
* @param request the current servlet request
57-
* @param partName the name of the part to adapt to the {@link ServerHttpRequest} contract
59+
* @param requestPartName the name of the part to adapt to the {@link ServerHttpRequest} contract
5860
* @throws MissingServletRequestPartException if the request part cannot be found
5961
* @throws MultipartException if MultipartHttpServletRequest cannot be initialized
6062
*/
61-
public RequestPartServletServerHttpRequest(HttpServletRequest request, String partName)
63+
public RequestPartServletServerHttpRequest(HttpServletRequest request, String requestPartName)
6264
throws MissingServletRequestPartException {
6365

6466
super(request);
6567

6668
this.multipartRequest = MultipartResolutionDelegate.asMultipartHttpServletRequest(request);
67-
this.partName = partName;
69+
this.requestPartName = requestPartName;
6870

69-
HttpHeaders headers = this.multipartRequest.getMultipartHeaders(this.partName);
70-
if (headers == null) {
71-
throw new MissingServletRequestPartException(partName);
71+
HttpHeaders multipartHeaders = this.multipartRequest.getMultipartHeaders(this.requestPartName);
72+
if (multipartHeaders == null) {
73+
throw new MissingServletRequestPartException(requestPartName);
7274
}
73-
this.headers = headers;
75+
this.multipartHeaders = multipartHeaders;
7476
}
7577

7678

7779
@Override
7880
public HttpHeaders getHeaders() {
79-
return this.headers;
81+
return this.multipartHeaders;
8082
}
8183

8284
@Override
8385
public InputStream getBody() throws IOException {
86+
// Prefer Servlet Part resolution to cover file as well as parameter streams
8487
if (this.multipartRequest instanceof StandardMultipartHttpServletRequest) {
85-
try {
86-
return this.multipartRequest.getPart(this.partName).getInputStream();
87-
}
88-
catch (Exception ex) {
89-
throw new MultipartException("Could not parse multipart servlet request", ex);
88+
Part part = retrieveServletPart();
89+
if (part != null) {
90+
return part.getInputStream();
9091
}
9192
}
92-
else {
93-
MultipartFile file = this.multipartRequest.getFile(this.partName);
94-
if (file != null) {
95-
return file.getInputStream();
96-
}
97-
else {
98-
String paramValue = this.multipartRequest.getParameter(this.partName);
99-
return new ByteArrayInputStream(paramValue.getBytes(determineCharset()));
100-
}
93+
94+
// Spring-style distinction between MultipartFile and String parameters
95+
MultipartFile file = this.multipartRequest.getFile(this.requestPartName);
96+
if (file != null) {
97+
return file.getInputStream();
98+
}
99+
String paramValue = this.multipartRequest.getParameter(this.requestPartName);
100+
if (paramValue != null) {
101+
return new ByteArrayInputStream(paramValue.getBytes(determineCharset()));
102+
}
103+
104+
// Fallback: Servlet Part resolution even if not indicated
105+
Part part = retrieveServletPart();
106+
if (part != null) {
107+
return part.getInputStream();
108+
}
109+
110+
throw new IllegalStateException("No body available for request part '" + this.requestPartName + "'");
111+
}
112+
113+
@Nullable
114+
private Part retrieveServletPart() {
115+
try {
116+
return this.multipartRequest.getPart(this.requestPartName);
117+
}
118+
catch (Exception ex) {
119+
throw new MultipartException("Failed to retrieve request part '" + this.requestPartName + "'", ex);
101120
}
102121
}
103122

spring-web/src/test/java/org/springframework/web/multipart/support/RequestPartServletServerHttpRequestTests.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 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.
@@ -32,11 +32,13 @@
3232
import org.springframework.web.multipart.MultipartFile;
3333
import org.springframework.web.testfixture.servlet.MockMultipartFile;
3434
import org.springframework.web.testfixture.servlet.MockMultipartHttpServletRequest;
35+
import org.springframework.web.testfixture.servlet.MockPart;
3536

3637
import static org.assertj.core.api.Assertions.assertThat;
3738

3839
/**
3940
* @author Rossen Stoyanchev
41+
* @author Juergen Hoeller
4042
*/
4143
public class RequestPartServletServerHttpRequestTests {
4244

@@ -137,4 +139,17 @@ public HttpHeaders getMultipartHeaders(String paramOrFileName) {
137139
assertThat(result).isEqualTo(bytes);
138140
}
139141

142+
@Test
143+
public void getBodyViaRequestPart() throws Exception {
144+
byte[] bytes = "content".getBytes("UTF-8");
145+
MockPart mockPart = new MockPart("part", bytes);
146+
mockPart.getHeaders().setContentType(MediaType.APPLICATION_JSON);
147+
mockRequest.addPart(mockPart);
148+
this.mockRequest.addPart(mockPart);
149+
ServerHttpRequest request = new RequestPartServletServerHttpRequest(this.mockRequest, "part");
150+
151+
byte[] result = FileCopyUtils.copyToByteArray(request.getBody());
152+
assertThat(result).isEqualTo(bytes);
153+
}
154+
140155
}

0 commit comments

Comments
 (0)