Skip to content

Commit 01a9251

Browse files
committed
Refactor RequestedContentTypeResolverBuilder
The revised builder emphasizes creating a list of resolvers either built-in or custom with each top-level builder method resulting in adding a resolver. By default only the Header resolver is configured. The path extension resolver is removed altogether to discourage its use but is trivial to create manually with the helpf of UriUtils#extractFileExtension + MediaTypeFactory. Issue: SPR-15639
1 parent b0e8e7f commit 01a9251

20 files changed

+340
-707
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/accept/AbstractMappingContentTypeResolver.java

Lines changed: 0 additions & 82 deletions
This file was deleted.

spring-webflux/src/main/java/org/springframework/web/reactive/accept/CompositeContentTypeResolver.java

Lines changed: 0 additions & 55 deletions
This file was deleted.

spring-webflux/src/main/java/org/springframework/web/reactive/accept/FixedContentTypeResolver.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
import org.springframework.web.server.ServerWebExchange;
2727

2828
/**
29-
* {@code RequestedContentTypeResolver} with a fixed list of media types.
29+
* Resolver that always resolves to a fixed list of media types. This can be
30+
* used as the "last in line" strategy providing a fallback for when the client
31+
* has not requested any media types.
3032
*
3133
* @author Rossen Stoyanchev
3234
* @since 5.0
@@ -65,7 +67,6 @@ public List<MediaType> getContentTypes() {
6567
}
6668

6769

68-
6970
@Override
7071
public List<MediaType> resolveMediaTypes(ServerWebExchange exchange) {
7172
if (logger.isDebugEnabled()) {

spring-webflux/src/main/java/org/springframework/web/reactive/accept/HeaderContentTypeResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import org.springframework.web.server.ServerWebExchange;
2424

2525
/**
26-
* A {@link RequestedContentTypeResolver} that checks the 'Accept' request header.
26+
* Resolver that looks at the 'Accept' header of the request.
2727
*
2828
* @author Rossen Stoyanchev
2929
* @since 5.0

spring-webflux/src/main/java/org/springframework/web/reactive/accept/ParameterContentTypeResolver.java

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -13,34 +13,50 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
package org.springframework.web.reactive.accept;
1817

18+
import java.util.ArrayList;
19+
import java.util.Collections;
20+
import java.util.List;
21+
import java.util.Locale;
1922
import java.util.Map;
23+
import java.util.concurrent.ConcurrentHashMap;
2024

2125
import org.springframework.http.MediaType;
26+
import org.springframework.http.MediaTypeFactory;
2227
import org.springframework.util.Assert;
28+
import org.springframework.util.StringUtils;
29+
import org.springframework.web.server.NotAcceptableStatusException;
2330
import org.springframework.web.server.ServerWebExchange;
2431

2532
/**
26-
* Query parameter based {@link AbstractMappingContentTypeResolver}.
33+
* Resolver that checks a query parameter and uses it to lookup a matching
34+
* MediaType. Lookup keys can be registered or as a fallback
35+
* {@link MediaTypeFactory} can be used to perform a lookup.
2736
*
2837
* @author Rossen Stoyanchev
2938
* @since 5.0
3039
*/
31-
public class ParameterContentTypeResolver extends AbstractMappingContentTypeResolver {
40+
public class ParameterContentTypeResolver implements RequestedContentTypeResolver {
41+
42+
/** Primary lookup for media types by key (e.g. "json" -> "application/json") */
43+
private final Map<String, MediaType> mediaTypes = new ConcurrentHashMap<>(64);
3244

3345
private String parameterName = "format";
3446

3547

3648
public ParameterContentTypeResolver(Map<String, MediaType> mediaTypes) {
37-
super(mediaTypes);
49+
mediaTypes.forEach((key, value) -> this.mediaTypes.put(formatKey(key), value));
50+
}
51+
52+
private static String formatKey(String key) {
53+
return key.toLowerCase(Locale.ENGLISH);
3854
}
3955

4056

4157
/**
4258
* Set the name of the parameter to use to determine requested media types.
43-
* <p>By default this is set to {@code "format"}.
59+
* <p>By default this is set to {@literal "format"}.
4460
*/
4561
public void setParameterName(String parameterName) {
4662
Assert.notNull(parameterName, "'parameterName' is required");
@@ -53,8 +69,22 @@ public String getParameterName() {
5369

5470

5571
@Override
56-
protected String getKey(ServerWebExchange exchange) {
57-
return exchange.getRequest().getQueryParams().getFirst(getParameterName());
72+
public List<MediaType> resolveMediaTypes(ServerWebExchange exchange) throws NotAcceptableStatusException {
73+
String key = exchange.getRequest().getQueryParams().getFirst(getParameterName());
74+
if (!StringUtils.hasText(key)) {
75+
return Collections.emptyList();
76+
}
77+
key = formatKey(key);
78+
MediaType match = this.mediaTypes.get(key);
79+
if (match == null) {
80+
match = MediaTypeFactory.getMediaType("filename." + key)
81+
.orElseThrow(() -> {
82+
List<MediaType> supported = new ArrayList<>(this.mediaTypes.values());
83+
return new NotAcceptableStatusException(supported);
84+
});
85+
}
86+
this.mediaTypes.putIfAbsent(key, match);
87+
return Collections.singletonList(match);
5888
}
5989

6090
}

spring-webflux/src/main/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolver.java

Lines changed: 0 additions & 45 deletions
This file was deleted.

spring-webflux/src/main/java/org/springframework/web/reactive/accept/RequestedContentTypeResolver.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
import org.springframework.web.server.ServerWebExchange;
2424

2525
/**
26-
* Strategy for resolving the requested media types for a
27-
* {@code ServerWebExchange}.
26+
* Strategy to resolve the requested media types for a {@code ServerWebExchange}.
27+
*
28+
* <p>See {@link RequestedContentTypeResolverBuilder} to create a sequence of
29+
* strategies.
2830
*
2931
* @author Rossen Stoyanchev
3032
* @since 5.0
@@ -36,7 +38,7 @@ public interface RequestedContentTypeResolver {
3638
* list is ordered by specificity first and by quality parameter second.
3739
* @param exchange the current exchange
3840
* @return the requested media types or an empty list
39-
* @throws NotAcceptableStatusException if the requested media types is invalid
41+
* @throws NotAcceptableStatusException if the requested media type is invalid
4042
*/
4143
List<MediaType> resolveMediaTypes(ServerWebExchange exchange);
4244

0 commit comments

Comments
 (0)