Fix regression in WebFlux support for WebDAV methods

This commit ensures that WebFlux's RequestMethodsRequestCondition
supports HTTP methods that are not in the RequestMethod enum.

- RequestMethod::resolve is introduced, to convert from a HttpMethod
(name) to enum values.
- RequestMethod::asHttpMethod is introduced, to convert from enum value
to HttpMethod.
- HttpMethod::valueOf replaced Map-based lookup to a switch statement
- Enabled tests that check for WebDAV methods

See gh-27697
Closes gh-29981
This commit is contained in:
Arjen Poutsma
2023-02-17 11:27:47 +01:00
parent 1999c78350
commit 88e6544d9d
6 changed files with 151 additions and 43 deletions

View File

@@ -17,10 +17,6 @@
package org.springframework.http;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -88,9 +84,6 @@ public final class HttpMethod implements Comparable<HttpMethod>, Serializable {
private static final HttpMethod[] values = new HttpMethod[] { GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE };
private static final Map<String, HttpMethod> mappings = Arrays.stream(values)
.collect(Collectors.toUnmodifiableMap(HttpMethod::name, Function.identity()));
private final String name;
@@ -121,13 +114,17 @@ public final class HttpMethod implements Comparable<HttpMethod>, Serializable {
*/
public static HttpMethod valueOf(String method) {
Assert.notNull(method, "Method must not be null");
HttpMethod result = mappings.get(method);
if (result != null) {
return result;
}
else {
return new HttpMethod(method);
}
return switch (method) {
case "GET" -> GET;
case "HEAD" -> HEAD;
case "POST" -> POST;
case "PUT" -> PUT;
case "PATCH" -> PATCH;
case "DELETE" -> DELETE;
case "OPTIONS" -> OPTIONS;
case "TRACE" -> TRACE;
default -> new HttpMethod(method);
};
}
/**

View File

@@ -16,6 +16,10 @@
package org.springframework.web.bind.annotation;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Enumeration of HTTP request methods. Intended for use with the
* {@link RequestMapping#method()} attribute of the {@link RequestMapping} annotation.
@@ -34,6 +38,62 @@ package org.springframework.web.bind.annotation;
*/
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
/**
* Resolve the given method value to an {@code RequestMethod} enum value.
* Returns {@code null} if {@code method} has no corresponding value.
* @param method the method value as a String
* @return the corresponding {@code RequestMethod}, or {@code null} if not found
* @since 6.0.6
*/
@Nullable
public static RequestMethod resolve(String method) {
Assert.notNull(method, "Method must not be null");
return switch (method) {
case "GET" -> GET;
case "HEAD" -> HEAD;
case "POST" -> POST;
case "PUT" -> PUT;
case "PATCH" -> PATCH;
case "DELETE" -> DELETE;
case "OPTIONS" -> OPTIONS;
case "TRACE" -> TRACE;
default -> null;
};
}
/**
* Resolve the given {@link HttpMethod} to a {@code RequestMethod} enum value.
* Returns {@code null} if {@code httpMethod} has no corresponding value.
* @param httpMethod the http method object
* @return the corresponding {@code RequestMethod}, or {@code null} if not found
* @since 6.0.6
*/
@Nullable
public static RequestMethod resolve(HttpMethod httpMethod) {
Assert.notNull(httpMethod, "HttpMethod must not be null");
return resolve(httpMethod.name());
}
/**
* Return the {@link HttpMethod} corresponding to this {@code RequestMethod}.
* @return the http method for this request method
* @since 6.0.6
*/
public HttpMethod asHttpMethod() {
return switch (this) {
case GET -> HttpMethod.GET;
case HEAD -> HttpMethod.HEAD;
case POST -> HttpMethod.POST;
case PUT -> HttpMethod.PUT;
case PATCH -> HttpMethod.PATCH;
case DELETE -> HttpMethod.DELETE;
case OPTIONS -> HttpMethod.OPTIONS;
case TRACE -> HttpMethod.TRACE;
};
}
}