Skip to content

Commit ccf505a

Browse files
committed
Add Accept-Query handling and remove versions from since
1 parent 9dc89dd commit ccf505a

File tree

11 files changed

+88
-21
lines changed

11 files changed

+88
-21
lines changed

spring-web/src/main/java/org/springframework/http/HttpHeaders.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
108108
* @see <a href="https://tools.ietf.org/html/rfc7233#section-2.3">Section 5.3.5 of RFC 7233</a>
109109
*/
110110
public static final String ACCEPT_RANGES = "Accept-Ranges";
111+
112+
/**
113+
* The HTTP {@code Accept-Query} header field name.
114+
* @see <a href="https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/">IETF Draft</a>
115+
*/
116+
public static final String ACCEPT_QUERY = "Accept-Query";
111117
/**
112118
* The CORS {@code Access-Control-Allow-Credentials} response header field name.
113119
* @see <a href="https://www.w3.org/TR/cors/">CORS W3C recommendation</a>
@@ -568,6 +574,27 @@ public List<MediaType> getAcceptPatch() {
568574
return MediaType.parseMediaTypes(get(ACCEPT_PATCH));
569575
}
570576

577+
/**
578+
* Set the list of acceptable {@linkplain MediaType media types} for
579+
* {@code QUERY} methods, as specified by the {@code Accept-QUERY} header.
580+
* @since x.x.x
581+
*/
582+
public void setAcceptQuery(List<MediaType> mediaTypes) {
583+
set(ACCEPT_QUERY, MediaType.toString(mediaTypes));
584+
}
585+
586+
/**
587+
* Return the list of acceptable {@linkplain MediaType media types} for
588+
* {@code QUERY} methods, as specified by the {@code Accept-Query} header.
589+
* <p>Returns an empty list when the acceptable media types are unspecified.
590+
* @since x.x.x
591+
*/
592+
public List<MediaType> getAcceptQuery() {
593+
return MediaType.parseMediaTypes(get(ACCEPT_QUERY));
594+
}
595+
596+
597+
571598
/**
572599
* Set the (new) value of the {@code Access-Control-Allow-Credentials} response header.
573600
*/

spring-web/src/main/java/org/springframework/http/HttpMethod.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public final class HttpMethod implements Comparable<HttpMethod>, Serializable {
8484

8585
/**
8686
* The HTTP method {@code QUERY}.
87-
* @see <a href="https://httpwg.org/http-extensions/draft-ietf-httpbis-safe-method-w-body.html">IETF Draft</a>
87+
* @see <a href="https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/">IETF Draft</a>
8888
*/
8989
public static final HttpMethod QUERY = new HttpMethod("QUERY");
9090

spring-web/src/main/java/org/springframework/http/RequestEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ public static BodyBuilder query(URI url) {
349349
* @param uriTemplate the uri template to use
350350
* @param uriVariables variables to expand the URI template with
351351
* @return the created builder
352-
* @since 6.2
352+
* @since x.x.x
353353
*/
354354
public static BodyBuilder query(String uriTemplate, Object... uriVariables) {
355355
return method(HttpMethod.QUERY, uriTemplate, uriVariables);

spring-web/src/main/java/org/springframework/web/HttpMediaTypeNotSupportedException.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ public HttpHeaders getHeaders() {
134134
if (HttpMethod.PATCH.equals(this.httpMethod)) {
135135
headers.setAcceptPatch(getSupportedMediaTypes());
136136
}
137+
if (HttpMethod.QUERY.equals(this.httpMethod)) {
138+
headers.setAcceptQuery(getSupportedMediaTypes());
139+
}
137140
return headers;
138141
}
139142

spring-web/src/main/java/org/springframework/web/bind/annotation/QueryMapping.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
* such as {@code @GetMapping}, {@code @PutMapping}, etc.
4040
*
4141
* @author Mario Ruiz
42-
* @since 6.2
42+
* @since x.x.x
4343
* @see GetMapping
4444
* @see PutMapping
4545
* @see PostMapping

spring-web/src/main/java/org/springframework/web/server/UnsupportedMediaTypeStatusException.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ public HttpHeaders getHeaders() {
165165
if (this.method == HttpMethod.PATCH) {
166166
headers.setAcceptPatch(this.supportedMediaTypes);
167167
}
168+
if (this.method == HttpMethod.QUERY) {
169+
headers.setAcceptQuery(this.supportedMediaTypes);
170+
}
168171
return headers;
169172
}
170173

spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RouterFunctions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ public interface Builder {
700700
* Adds a route to the given handler function that handles HTTP {@code QUERY} requests.
701701
* @param handlerFunction the handler function to handle all {@code QUERY} requests
702702
* @return this builder
703-
* @since 6.2
703+
* @since x.x.x
704704
*/
705705
Builder QUERY(HandlerFunction<ServerResponse> handlerFunction);
706706

@@ -722,7 +722,7 @@ public interface Builder {
722722
* @param handlerFunction the handler function to handle all {@code QUERY} requests that
723723
* match {@code predicate}
724724
* @return this builder
725-
* @since 6.2
725+
* @since x.x.x
726726
* @see RequestPredicates
727727
*/
728728
Builder QUERY(RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMapping.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,9 @@ protected HandlerMethod handleNoMatch(Set<RequestMappingInfo> infos,
192192
HttpMethod httpMethod = request.getMethod();
193193
Set<HttpMethod> methods = helper.getAllowedMethods();
194194
if (HttpMethod.OPTIONS.equals(httpMethod)) {
195-
Set<MediaType> mediaTypes = helper.getConsumablePatchMediaTypes();
196-
HttpOptionsHandler handler = new HttpOptionsHandler(methods, mediaTypes);
195+
Set<MediaType> patchMediaTypes = helper.getConsumablePatchMediaTypes();
196+
Set<MediaType> queryMediaTypes = helper.getConsumableQueryMediaTypes();
197+
HttpOptionsHandler handler = new HttpOptionsHandler(methods, patchMediaTypes, queryMediaTypes);
197198
return new HandlerMethod(handler, HTTP_OPTIONS_HANDLE_METHOD);
198199
}
199200
throw new MethodNotAllowedException(httpMethod, methods);
@@ -326,14 +327,23 @@ public List<Set<NameValueExpression<String>>> getParamConditions() {
326327
* PATCH specified, or that have no methods at all.
327328
*/
328329
public Set<MediaType> getConsumablePatchMediaTypes() {
329-
Set<MediaType> result = new LinkedHashSet<>();
330-
for (PartialMatch match : this.partialMatches) {
331-
Set<RequestMethod> methods = match.getInfo().getMethodsCondition().getMethods();
332-
if (methods.isEmpty() || methods.contains(RequestMethod.PATCH)) {
333-
result.addAll(match.getInfo().getConsumesCondition().getConsumableMediaTypes());
334-
}
335-
}
336-
return result;
330+
return getConsumableMediaTypesForMethod(RequestMethod.PATCH);
331+
}
332+
333+
/**
334+
* Return declared "consumable" types but only among those that have
335+
* PATCH specified, or that have no methods at all.
336+
*/
337+
public Set<MediaType> getConsumableQueryMediaTypes() {
338+
return getConsumableMediaTypesForMethod(RequestMethod.QUERY);
339+
}
340+
341+
private Set<MediaType> getConsumableMediaTypesForMethod(RequestMethod method) {
342+
return this.partialMatches.stream()
343+
.map(PartialMatch::getInfo)
344+
.filter(info -> info.getMethodsCondition().getMethods().isEmpty() || info.getMethodsCondition().getMethods().contains(method))
345+
.flatMap(info -> info.getConsumesCondition().getConsumableMediaTypes().stream())
346+
.collect(Collectors.toCollection(LinkedHashSet::new));
337347
}
338348

339349

@@ -403,9 +413,10 @@ private static class HttpOptionsHandler {
403413
private final HttpHeaders headers = new HttpHeaders();
404414

405415

406-
public HttpOptionsHandler(Set<HttpMethod> declaredMethods, Set<MediaType> acceptPatch) {
416+
public HttpOptionsHandler(Set<HttpMethod> declaredMethods, Set<MediaType> acceptPatch, Set<MediaType> acceptQuery) {
407417
this.headers.setAllow(initAllowedHttpMethods(declaredMethods));
408418
this.headers.setAcceptPatch(new ArrayList<>(acceptPatch));
419+
this.headers.setAcceptQuery(new ArrayList<>(acceptQuery));
409420
}
410421

411422
private static Set<HttpMethod> initAllowedHttpMethods(Set<HttpMethod> declaredMethods) {

spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ private void testHttpMediaTypeNotSupportedException(String url) {
377377
.isEqualTo(Collections.singletonList(new MediaType("application", "xml"))));
378378
}
379379

380-
private void testHttpOptions(String requestURI, Set<HttpMethod> allowedMethods, @Nullable MediaType acceptPatch) {
380+
private void testHttpOptions(String requestURI, Set<HttpMethod> allowedMethods, @Nullable MediaType acceptMediaType) {
381381
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.options(requestURI));
382382
HandlerMethod handlerMethod = (HandlerMethod) this.handlerMapping.getHandler(exchange).block();
383383

@@ -395,9 +395,15 @@ private void testHttpOptions(String requestURI, Set<HttpMethod> allowedMethods,
395395
HttpHeaders headers = (HttpHeaders) value;
396396
assertThat(headers.getAllow()).hasSameElementsAs(allowedMethods);
397397

398-
if (acceptPatch != null && headers.getAllow().contains(HttpMethod.PATCH) ) {
399-
assertThat(headers.getAcceptPatch()).containsExactly(acceptPatch);
398+
if (acceptMediaType != null) {
399+
if (headers.getAllow().contains(HttpMethod.PATCH)) {
400+
assertThat(headers.getAcceptPatch()).containsExactly(acceptMediaType);
401+
}
402+
if (headers.getAllow().contains(HttpMethod.QUERY)) {
403+
assertThat(headers.getAcceptQuery()).containsExactly(acceptMediaType);
404+
}
400405
}
406+
401407
}
402408

403409
private void testMediaTypeNotAcceptable(String url) {

spring-webmvc/src/main/java/org/springframework/web/servlet/function/RouterFunctions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ public interface Builder {
614614
* Adds a route to the given handler function that handles HTTP {@code QUERY} requests.
615615
* @param handlerFunction the handler function to handle all {@code QUERY} requests
616616
* @return this builder
617-
* @since 5.3
617+
* @since x.x.x
618618
*/
619619
Builder QUERY(HandlerFunction<ServerResponse> handlerFunction);
620620

@@ -636,7 +636,7 @@ public interface Builder {
636636
* @param handlerFunction the handler function to handle all {@code QUERY} requests that
637637
* match {@code predicate}
638638
* @return this builder
639-
* @since 5.3
639+
* @since x.x.x
640640
* @see RequestPredicates
641641
*/
642642
Builder QUERY(RequestPredicate predicate, HandlerFunction<ServerResponse> handlerFunction);

0 commit comments

Comments
 (0)