Change MethodNotAllowedException to use HttpMethod
Changed the MethodNotAllowedException to use HttpMethod, instead of Strings.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -33,14 +34,21 @@ import org.springframework.util.Assert;
|
||||
@SuppressWarnings("serial")
|
||||
public class MethodNotAllowedException extends ResponseStatusException {
|
||||
|
||||
private String method;
|
||||
private final String method;
|
||||
|
||||
private Set<String> supportedMethods;
|
||||
private final Set<HttpMethod> supportedMethods;
|
||||
|
||||
|
||||
public MethodNotAllowedException(String method, Collection<String> supportedMethods) {
|
||||
public MethodNotAllowedException(HttpMethod method, Collection<HttpMethod> supportedMethods) {
|
||||
this(method.name(), supportedMethods);
|
||||
}
|
||||
|
||||
public MethodNotAllowedException(String method, Collection<HttpMethod> supportedMethods) {
|
||||
super(HttpStatus.METHOD_NOT_ALLOWED, "Request method '" + method + "' not supported");
|
||||
Assert.notNull(method, "'method' is required");
|
||||
if (supportedMethods == null) {
|
||||
supportedMethods = Collections.emptySet();
|
||||
}
|
||||
this.method = method;
|
||||
this.supportedMethods = Collections.unmodifiableSet(new HashSet<>(supportedMethods));
|
||||
}
|
||||
@@ -56,7 +64,7 @@ public class MethodNotAllowedException extends ResponseStatusException {
|
||||
/**
|
||||
* Return the list of supported HTTP methods.
|
||||
*/
|
||||
public Set<String> getSupportedMethods() {
|
||||
public Set<HttpMethod> getSupportedMethods() {
|
||||
return supportedMethods;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -21,10 +21,9 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -89,14 +88,10 @@ public class ResourceWebHandler
|
||||
implements WebHandler, InitializingBean, SmartInitializingSingleton {
|
||||
|
||||
/** Set of supported HTTP methods */
|
||||
private static final Set<String> SUPPORTED_METHODS = new LinkedHashSet<>(2);
|
||||
private static final Set<HttpMethod> SUPPORTED_METHODS = EnumSet.of(HttpMethod.GET, HttpMethod.HEAD);
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ResourceWebHandler.class);
|
||||
|
||||
static {
|
||||
SUPPORTED_METHODS.addAll(Arrays.asList("GET", "HEAD"));
|
||||
}
|
||||
|
||||
|
||||
private final List<Resource> locations = new ArrayList<>(4);
|
||||
|
||||
@@ -294,9 +289,9 @@ public class ResourceWebHandler
|
||||
}
|
||||
|
||||
// Supported methods and required session
|
||||
String httpMehtod = exchange.getRequest().getMethod().name();
|
||||
if (!SUPPORTED_METHODS.contains(httpMehtod)) {
|
||||
return Mono.error(new MethodNotAllowedException(httpMehtod, SUPPORTED_METHODS));
|
||||
HttpMethod httpMethod = exchange.getRequest().getMethod();
|
||||
if (!SUPPORTED_METHODS.contains(httpMethod)) {
|
||||
return Mono.error(new MethodNotAllowedException(httpMethod, SUPPORTED_METHODS));
|
||||
}
|
||||
|
||||
// Header phase
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -20,6 +20,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
@@ -218,12 +219,12 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
|
||||
if (helper.hasMethodsMismatch()) {
|
||||
HttpMethod httpMethod = request.getMethod();
|
||||
Set<String> methods = helper.getAllowedMethods();
|
||||
Set<HttpMethod> methods = helper.getAllowedMethods();
|
||||
if (HttpMethod.OPTIONS.matches(httpMethod.name())) {
|
||||
HttpOptionsHandler handler = new HttpOptionsHandler(methods);
|
||||
return new HandlerMethod(handler, HTTP_OPTIONS_HANDLE_METHOD);
|
||||
}
|
||||
throw new MethodNotAllowedException(httpMethod.name(), methods);
|
||||
throw new MethodNotAllowedException(httpMethod, methods);
|
||||
}
|
||||
|
||||
if (helper.hasConsumesMismatch()) {
|
||||
@@ -280,42 +281,42 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
* Any partial matches for "methods"?
|
||||
*/
|
||||
public boolean hasMethodsMismatch() {
|
||||
return !this.partialMatches.stream().
|
||||
filter(PartialMatch::hasMethodsMatch).findAny().isPresent();
|
||||
return this.partialMatches.stream().
|
||||
noneMatch(PartialMatch::hasMethodsMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Any partial matches for "methods" and "consumes"?
|
||||
*/
|
||||
public boolean hasConsumesMismatch() {
|
||||
return !this.partialMatches.stream().
|
||||
filter(PartialMatch::hasConsumesMatch).findAny().isPresent();
|
||||
return this.partialMatches.stream().
|
||||
noneMatch(PartialMatch::hasConsumesMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Any partial matches for "methods", "consumes", and "produces"?
|
||||
*/
|
||||
public boolean hasProducesMismatch() {
|
||||
return !this.partialMatches.stream().
|
||||
filter(PartialMatch::hasProducesMatch).findAny().isPresent();
|
||||
return this.partialMatches.stream().
|
||||
noneMatch(PartialMatch::hasProducesMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Any partial matches for "methods", "consumes", "produces", and "params"?
|
||||
*/
|
||||
public boolean hasParamsMismatch() {
|
||||
return !this.partialMatches.stream().
|
||||
filter(PartialMatch::hasParamsMatch).findAny().isPresent();
|
||||
return this.partialMatches.stream().
|
||||
noneMatch(PartialMatch::hasParamsMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return declared HTTP methods.
|
||||
*/
|
||||
public Set<String> getAllowedMethods() {
|
||||
public Set<HttpMethod> getAllowedMethods() {
|
||||
return this.partialMatches.stream().
|
||||
flatMap(m -> m.getInfo().getMethodsCondition().getMethods().stream()).
|
||||
map(requestMethod -> requestMethod.name()).
|
||||
collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
map(requestMethod -> HttpMethod.resolve(requestMethod.name())).
|
||||
collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,29 +414,23 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
|
||||
public HttpOptionsHandler(Set<String> declaredMethods) {
|
||||
public HttpOptionsHandler(Set<HttpMethod> declaredMethods) {
|
||||
this.headers.setAllow(initAllowedHttpMethods(declaredMethods));
|
||||
}
|
||||
|
||||
private static Set<HttpMethod> initAllowedHttpMethods(Set<String> declaredMethods) {
|
||||
Set<HttpMethod> result = new LinkedHashSet<>(declaredMethods.size());
|
||||
private static Set<HttpMethod> initAllowedHttpMethods(Set<HttpMethod> declaredMethods) {
|
||||
if (declaredMethods.isEmpty()) {
|
||||
for (HttpMethod method : HttpMethod.values()) {
|
||||
if (!HttpMethod.TRACE.equals(method)) {
|
||||
result.add(method);
|
||||
}
|
||||
}
|
||||
return EnumSet.allOf(HttpMethod.class).stream()
|
||||
.filter(method -> !method.equals(HttpMethod.TRACE))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
else {
|
||||
boolean hasHead = declaredMethods.contains("HEAD");
|
||||
for (String method : declaredMethods) {
|
||||
result.add(HttpMethod.valueOf(method));
|
||||
if (!hasHead && "GET".equals(method)) {
|
||||
result.add(HttpMethod.HEAD);
|
||||
}
|
||||
Set<HttpMethod> result = new LinkedHashSet<>(declaredMethods);
|
||||
if (result.contains(HttpMethod.GET)) {
|
||||
result.add(HttpMethod.HEAD);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@@ -187,7 +187,7 @@ public class HandshakeWebSocketService implements WebSocketService, Lifecycle {
|
||||
}
|
||||
|
||||
if (HttpMethod.GET != method) {
|
||||
return Mono.error(new MethodNotAllowedException(method.name(), Collections.singleton("GET")));
|
||||
return Mono.error(new MethodNotAllowedException(method, Collections.singleton(HttpMethod.GET)));
|
||||
}
|
||||
|
||||
if (!"WebSocket".equalsIgnoreCase(headers.getUpgrade())) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -56,11 +57,7 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.HEAD;
|
||||
@@ -141,7 +138,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
Mono<Object> mono = this.handlerMapping.getHandler(exchange);
|
||||
|
||||
assertError(mono, MethodNotAllowedException.class,
|
||||
ex -> assertEquals(new HashSet<>(Arrays.asList("GET", "HEAD")), ex.getSupportedMethods()));
|
||||
ex -> assertEquals(EnumSet.of(HttpMethod.GET, HttpMethod.HEAD), ex.getSupportedMethods()));
|
||||
}
|
||||
|
||||
@Test // SPR-9603
|
||||
@@ -192,10 +189,10 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
|
||||
@Test
|
||||
public void getHandlerHttpOptions() throws Exception {
|
||||
testHttpOptions("/foo", "GET,HEAD");
|
||||
testHttpOptions("/person/1", "PUT");
|
||||
testHttpOptions("/persons", "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS");
|
||||
testHttpOptions("/something", "PUT,POST");
|
||||
testHttpOptions("/foo", EnumSet.of(HttpMethod.GET, HttpMethod.HEAD));
|
||||
testHttpOptions("/person/1", EnumSet.of(HttpMethod.PUT));
|
||||
testHttpOptions("/persons", EnumSet.of(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH, HttpMethod.DELETE, HttpMethod.OPTIONS));
|
||||
testHttpOptions("/something", EnumSet.of(HttpMethod.PUT, HttpMethod.POST));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -349,7 +346,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
ex.getSupportedMediaTypes()));
|
||||
}
|
||||
|
||||
private void testHttpOptions(String requestURI, String allowHeader) throws Exception {
|
||||
private void testHttpOptions(String requestURI, Set<HttpMethod> allowedMethods) throws Exception {
|
||||
ServerWebExchange exchange = MockServerHttpRequest.options(requestURI).toExchange();
|
||||
HandlerMethod handlerMethod = (HandlerMethod) this.handlerMapping.getHandler(exchange).block();
|
||||
|
||||
@@ -363,7 +360,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
||||
Optional<Object> value = result.getReturnValue();
|
||||
assertTrue(value.isPresent());
|
||||
assertEquals(HttpHeaders.class, value.get().getClass());
|
||||
assertEquals(allowHeader, ((HttpHeaders) value.get()).getFirst("Allow"));
|
||||
assertEquals(allowedMethods, ((HttpHeaders) value.get()).getAllow());
|
||||
}
|
||||
|
||||
private void testMediaTypeNotAcceptable(String url) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user