Browse Source

Use updated message in HttpEntityMethodProcessor

Prior to this commit, the `HttpEntityMethodProcessor` would create a new
`ServletServerHttpRequest` input message to parse the native Servlet
request, but would not reuse it for reading the request body using the
message converters.

In gh-32471, we applied a change that updates HTTP headers accordingly
when request parameters are read. But not reusing the input message
means that we are losing this update when instantiating the resulting
`HttpEntity`.

This commit ensures that `HttpEntityMethodProcessor` uses the input
message it just created when decoding the request body.

Fixes gh-36298
pull/36325/head
Brian Clozel 1 month ago
parent
commit
62e590a437
  1. 2
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java
  2. 24
      spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorTests.java

2
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java

@ -154,7 +154,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro @@ -154,7 +154,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
"' in method " + parameter.getMethod() + " is not parameterized");
}
Object body = readWithMessageConverters(webRequest, parameter, paramType);
Object body = readWithMessageConverters(inputMessage, parameter, paramType);
if (RequestEntity.class == parameter.getParameterType()) {
return new RequestEntity<>(body, inputMessage.getHeaders(),
inputMessage.getMethod(), inputMessage.getURI());

24
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorTests.java

@ -36,6 +36,7 @@ import org.springframework.core.MethodParameter; @@ -36,6 +36,7 @@ import org.springframework.core.MethodParameter;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
@ -131,6 +132,26 @@ public class HttpEntityMethodProcessorTests { @@ -131,6 +132,26 @@ public class HttpEntityMethodProcessorTests {
assertThat(result.getBody()).isNull();
}
@Test // gh-36298
@SuppressWarnings("unchecked")
void shouldResolveEntityWithMutatedHeaders() throws Exception {
servletRequest.setMethod("POST");
servletRequest.addParameter("project", "spring%20framework");
servletRequest.addHeader("Content-Length", "project=spring%20framework".length());
servletRequest.setContentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE);
List<HttpMessageConverter<?>> converters = new ArrayList<>();
converters.add(new ByteArrayHttpMessageConverter());
HttpEntityMethodProcessor processor = new HttpEntityMethodProcessor(converters);
Method method = getClass().getDeclaredMethod("resolveAsByteArray", RequestEntity.class);
MethodParameter requestEntity = new MethodParameter(method, 0);
HttpEntity<byte[]> result = (HttpEntity<byte[]>) processor.resolveArgument(requestEntity,
this.mavContainer, this.webRequest, this.binderFactory);
assertThat(result.getBody().length).isEqualTo(result.getHeaders().getContentLength());
}
@Test
void resolveGenericArgument() throws Exception {
String content = "[{\"name\" : \"Jad\"}, {\"name\" : \"Robert\"}]";
@ -271,6 +292,9 @@ public class HttpEntityMethodProcessorTests { @@ -271,6 +292,9 @@ public class HttpEntityMethodProcessorTests {
return null;
}
private void resolveAsByteArray(RequestEntity<byte[]> request) {
}
@SuppressWarnings("unused")
private abstract static class MyParameterizedController<DTO extends Identifiable> {

Loading…
Cancel
Save