Support "Accept-Patch" for OPTIONS requests

This commit introduces support in both servlet and webflux for the
"Accept-Patch" header in OPTIONS requests, as defined in section 3.1 of
RFC 5789.

See gh-26759
This commit is contained in:
Arjen Poutsma
2021-04-08 10:36:00 +02:00
parent 44e1d6d1bf
commit 97f3846971
5 changed files with 124 additions and 22 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -244,7 +244,8 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
if (helper.hasMethodsMismatch()) {
Set<String> methods = helper.getAllowedMethods();
if (HttpMethod.OPTIONS.matches(request.getMethod())) {
HttpOptionsHandler handler = new HttpOptionsHandler(methods);
Set<MediaType> mediaTypes = helper.getConsumablePatchMediaTypes();
HttpOptionsHandler handler = new HttpOptionsHandler(methods, mediaTypes);
return new HandlerMethod(handler, HTTP_OPTIONS_HANDLE_METHOD);
}
throw new HttpRequestMethodNotSupportedException(request.getMethod(), methods);
@@ -411,6 +412,21 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
return result;
}
/**
* Return declared "consumable" types but only among those that have
* PATCH specified, or that have no methods at all.
*/
public Set<MediaType> getConsumablePatchMediaTypes() {
Set<MediaType> result = new LinkedHashSet<>();
for (PartialMatch match : this.partialMatches) {
Set<RequestMethod> methods = match.getInfo().getMethodsCondition().getMethods();
if (methods.isEmpty() || methods.contains(RequestMethod.PATCH)) {
result.addAll(match.getInfo().getConsumesCondition().getConsumableMediaTypes());
}
}
return result;
}
/**
* Container for a RequestMappingInfo that matches the URL path at least.
@@ -475,8 +491,9 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
private final HttpHeaders headers = new HttpHeaders();
public HttpOptionsHandler(Set<String> declaredMethods) {
public HttpOptionsHandler(Set<String> declaredMethods, Set<MediaType> acceptPatch) {
this.headers.setAllow(initAllowedHttpMethods(declaredMethods));
this.headers.setAcceptPatch(new ArrayList<>(acceptPatch));
}
private static Set<HttpMethod> initAllowedHttpMethods(Set<String> declaredMethods) {