Check HTTP method before raising 415

This commit moves the check whether an HTTP method supports request
body up to the base class so that all sub-classes can benefit (not just
@RequestBody).

Issue: SPR-13176
This commit is contained in:
Rossen Stoyanchev
2015-06-30 15:24:01 -04:00
parent 244c95b076
commit 3272a3b8ba
5 changed files with 50 additions and 24 deletions

View File

@@ -22,6 +22,7 @@ import java.io.PushbackInputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
@@ -37,6 +38,8 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.converter.GenericHttpMessageConverter;
@@ -60,6 +63,9 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver;
*/
public abstract class AbstractMessageConverterMethodArgumentResolver implements HandlerMethodArgumentResolver {
private static final List<HttpMethod> SUPPORTED_METHODS =
Arrays.asList(HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH);
private static final Object NO_VALUE = new Object();
@@ -170,6 +176,7 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
targetClass = (Class<T>) resolvableType.resolve();
}
HttpMethod httpMethod = ((HttpRequest) inputMessage).getMethod();
inputMessage = new EmptyBodyCheckingHttpInputMessage(inputMessage);
Object body = NO_VALUE;
@@ -213,6 +220,9 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
}
if (body == NO_VALUE) {
if (!SUPPORTED_METHODS.contains(httpMethod)) {
return null;
}
throw new HttpMediaTypeNotSupportedException(contentType, this.allSupportedMediaTypes);
}
@@ -273,6 +283,8 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
private final InputStream body;
private final HttpMethod method;
public EmptyBodyCheckingHttpInputMessage(HttpInputMessage inputMessage) throws IOException {
this.headers = inputMessage.getHeaders();
@@ -296,6 +308,7 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
pushbackInputStream.unread(b);
}
}
this.method = ((HttpRequest) inputMessage).getMethod();
}
@Override
@@ -307,6 +320,10 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
public InputStream getBody() throws IOException {
return this.body;
}
public HttpMethod getMethod() {
return this.method;
}
}
}

View File

@@ -150,14 +150,11 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
Object arg = null;
if (webRequest.getHeader("Content-Type") != null ||
SUPPORTED_METHODS.contains(inputMessage.getMethod())) {
arg = readWithMessageConverters(inputMessage, methodParam, paramType);
if (arg == null) {
if (methodParam.getParameterAnnotation(RequestBody.class).required()) {
throw new HttpMessageNotReadableException("Required request body is missing: " +
methodParam.getMethod().toGenericString());
}
arg = readWithMessageConverters(inputMessage, methodParam, paramType);
if (arg == null) {
if (methodParam.getParameterAnnotation(RequestBody.class).required()) {
throw new HttpMessageNotReadableException("Required request body is missing: " +
methodParam.getMethod().toGenericString());
}
}
return arg;