Expose media type mappings in ContentNegotiationManager
ContentNegotiationManagerFactoryBean now ensures that ContentNegotiationManager contains the MediaType mappings even if the path extension and the parameter strategies are off. There are also minor fixes to ensure the media type mappings in ContentNegotiationManagerFactoryBean aren't polluted when mapping keys are not lowercase, and likewise MappingMediaTypeFileExtensionResolver filters out duplicates in the list of all file extensions. See gh-24179
This commit is contained in:
parent
214ba63127
commit
542e187831
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2020 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,13 +20,17 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
|
||||
|
@ -132,11 +136,7 @@ public class ContentNegotiationManager implements ContentNegotiationStrategy, Me
|
|||
|
||||
@Override
|
||||
public List<String> resolveFileExtensions(MediaType mediaType) {
|
||||
Set<String> result = new LinkedHashSet<>();
|
||||
for (MediaTypeFileExtensionResolver resolver : this.resolvers) {
|
||||
result.addAll(resolver.resolveFileExtensions(mediaType));
|
||||
}
|
||||
return new ArrayList<>(result);
|
||||
return doResolveExtensions(resolver -> resolver.resolveFileExtensions(mediaType));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,11 +152,44 @@ public class ContentNegotiationManager implements ContentNegotiationStrategy, Me
|
|||
*/
|
||||
@Override
|
||||
public List<String> getAllFileExtensions() {
|
||||
Set<String> result = new LinkedHashSet<>();
|
||||
return doResolveExtensions(MediaTypeFileExtensionResolver::getAllFileExtensions);
|
||||
}
|
||||
|
||||
private List<String> doResolveExtensions(Function<MediaTypeFileExtensionResolver, List<String>> extractor) {
|
||||
List<String> result = null;
|
||||
for (MediaTypeFileExtensionResolver resolver : this.resolvers) {
|
||||
result.addAll(resolver.getAllFileExtensions());
|
||||
List<String> extensions = extractor.apply(resolver);
|
||||
if (CollectionUtils.isEmpty(extensions)) {
|
||||
continue;
|
||||
}
|
||||
result = (result != null ? result : new ArrayList<>(4));
|
||||
for (String extension : extensions) {
|
||||
if (!result.contains(extension)) {
|
||||
result.add(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(result);
|
||||
return (result != null ? result : Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all registered lookup key to media type mappings by iterating
|
||||
* {@link MediaTypeFileExtensionResolver}s.
|
||||
* @since 5.2.4
|
||||
*/
|
||||
public Map<String, MediaType> getMediaTypeMappings() {
|
||||
Map<String, MediaType> result = null;
|
||||
for (MediaTypeFileExtensionResolver resolver : this.resolvers) {
|
||||
if (resolver instanceof MappingMediaTypeFileExtensionResolver) {
|
||||
Map<String, MediaType> map = ((MappingMediaTypeFileExtensionResolver) resolver).getMediaTypes();
|
||||
if (CollectionUtils.isEmpty(map)) {
|
||||
continue;
|
||||
}
|
||||
result = (result != null ? result : new HashMap<>(4));
|
||||
result.putAll(map);
|
||||
}
|
||||
}
|
||||
return (result != null ? result : Collections.emptyMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ import org.springframework.web.context.ServletContextAware;
|
|||
* {@link #setFavorPathExtension(boolean) favorPathExtension} and
|
||||
* {@link #setIgnoreUnknownPathExtensions(boolean) ignoreUnknownPathExtensions}
|
||||
* are deprecated in order to discourage use of path extensions for content
|
||||
* negotiation and for request mapping (with similar deprecations in
|
||||
* negotiation as well as for request mapping (with similar deprecations in
|
||||
* {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
|
||||
* RequestMappingHandlerMapping}). For further context, please read issue
|
||||
* <a href="https://github.com/spring-projects/spring-framework/issues/24179">#24719</a>.
|
||||
|
@ -157,46 +157,52 @@ public class ContentNegotiationManagerFactoryBean
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a mapping from a key, extracted from a path extension or a query
|
||||
* parameter, to a MediaType. This is required in order for the parameter
|
||||
* strategy to work. Any extensions explicitly registered here are also
|
||||
* whitelisted for the purpose of Reflected File Download attack detection
|
||||
* (see Spring Framework reference documentation for more details on RFD
|
||||
* attack protection).
|
||||
* <p>The path extension strategy will also try to use
|
||||
* Add a mapping from a key to a MediaType where the key are normalized to
|
||||
* lowercase and may have been extracted from a path extension, a filename
|
||||
* extension, or passed as a query parameter.
|
||||
* <p>The {@link #setFavorParameter(boolean) parameter strategy} requires
|
||||
* such mappings in order to work while the {@link #setFavorPathExtension(boolean)
|
||||
* path extension strategy} can fall back on lookups via
|
||||
* {@link ServletContext#getMimeType} and
|
||||
* {@link org.springframework.http.MediaTypeFactory} to resolve path extensions.
|
||||
* {@link org.springframework.http.MediaTypeFactory}.
|
||||
* <p><strong>Note:</strong> Mappings registered here may be accessed via
|
||||
* {@link ContentNegotiationManager#getMediaTypeMappings()} and may be used
|
||||
* not only in the parameter and path extension strategies. For example,
|
||||
* with the Spring MVC config, e.g. {@code @EnableWebMvc} or
|
||||
* {@code <mvc:annotation-driven>}, the media type mappings are also plugged
|
||||
* in to:
|
||||
* <ul>
|
||||
* <li>Determine the media type of static resources served with
|
||||
* {@code ResourceHttpRequestHandler}.
|
||||
* <li>Determine the media type of views rendered with
|
||||
* {@code ContentNegotiatingViewResolver}.
|
||||
* <li>Whitelist extensions for RFD attack detection (check the Spring
|
||||
* Framework reference docs for details).
|
||||
* </ul>
|
||||
* @param mediaTypes media type mappings
|
||||
* @see #addMediaType(String, MediaType)
|
||||
* @see #addMediaTypes(Map)
|
||||
*/
|
||||
public void setMediaTypes(Properties mediaTypes) {
|
||||
if (!CollectionUtils.isEmpty(mediaTypes)) {
|
||||
mediaTypes.forEach((key, value) -> {
|
||||
String extension = ((String) key).toLowerCase(Locale.ENGLISH);
|
||||
MediaType mediaType = MediaType.valueOf((String) value);
|
||||
this.mediaTypes.put(extension, mediaType);
|
||||
});
|
||||
mediaTypes.forEach((key, value) ->
|
||||
addMediaType((String) key, MediaType.valueOf((String) value)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An alternative to {@link #setMediaTypes} for use in Java code.
|
||||
* @see #setMediaTypes
|
||||
* @see #addMediaTypes
|
||||
* An alternative to {@link #setMediaTypes} for programmatic registrations.
|
||||
*/
|
||||
public void addMediaType(String fileExtension, MediaType mediaType) {
|
||||
this.mediaTypes.put(fileExtension, mediaType);
|
||||
public void addMediaType(String key, MediaType mediaType) {
|
||||
this.mediaTypes.put(key.toLowerCase(Locale.ENGLISH), mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* An alternative to {@link #setMediaTypes} for use in Java code.
|
||||
* @see #setMediaTypes
|
||||
* @see #addMediaType
|
||||
* An alternative to {@link #setMediaTypes} for programmatic registrations.
|
||||
*/
|
||||
public void addMediaTypes(@Nullable Map<String, MediaType> mediaTypes) {
|
||||
if (mediaTypes != null) {
|
||||
this.mediaTypes.putAll(mediaTypes);
|
||||
mediaTypes.forEach(this::addMediaType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,6 +321,7 @@ public class ContentNegotiationManagerFactoryBean
|
|||
* Create and initialize a {@link ContentNegotiationManager} instance.
|
||||
* @since 5.0
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public ContentNegotiationManager build() {
|
||||
List<ContentNegotiationStrategy> strategies = new ArrayList<>();
|
||||
|
||||
|
@ -336,7 +343,6 @@ public class ContentNegotiationManagerFactoryBean
|
|||
}
|
||||
strategies.add(strategy);
|
||||
}
|
||||
|
||||
if (this.favorParameter) {
|
||||
ParameterContentNegotiationStrategy strategy = new ParameterContentNegotiationStrategy(this.mediaTypes);
|
||||
strategy.setParameterName(this.parameterName);
|
||||
|
@ -348,17 +354,24 @@ public class ContentNegotiationManagerFactoryBean
|
|||
}
|
||||
strategies.add(strategy);
|
||||
}
|
||||
|
||||
if (!this.ignoreAcceptHeader) {
|
||||
strategies.add(new HeaderContentNegotiationStrategy());
|
||||
}
|
||||
|
||||
if (this.defaultNegotiationStrategy != null) {
|
||||
strategies.add(this.defaultNegotiationStrategy);
|
||||
}
|
||||
}
|
||||
|
||||
this.contentNegotiationManager = new ContentNegotiationManager(strategies);
|
||||
|
||||
// Ensure media type mappings are available via ContentNegotiationManager#getMediaTypeMappings()
|
||||
// independent of path extension or parameter strategies.
|
||||
|
||||
if (!CollectionUtils.isEmpty(this.mediaTypes) && !this.favorPathExtension && !this.favorParameter) {
|
||||
this.contentNegotiationManager.addFileExtensionResolvers(
|
||||
new MappingMediaTypeFileExtensionResolver(this.mediaTypes));
|
||||
}
|
||||
|
||||
return this.contentNegotiationManager;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
@ -18,9 +18,11 @@ package org.springframework.web.accept;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
@ -53,7 +55,7 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten
|
|||
*/
|
||||
public MappingMediaTypeFileExtensionResolver(@Nullable Map<String, MediaType> mediaTypes) {
|
||||
if (mediaTypes != null) {
|
||||
List<String> allFileExtensions = new ArrayList<>();
|
||||
Set<String> allFileExtensions = new HashSet<>(mediaTypes.size());
|
||||
mediaTypes.forEach((extension, mediaType) -> {
|
||||
String lowerCaseExtension = extension.toLowerCase(Locale.ENGLISH);
|
||||
this.mediaTypes.put(lowerCaseExtension, mediaType);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -70,21 +71,29 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
|||
|
||||
this.servletRequest.setRequestURI("/flower.gif");
|
||||
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).as("Should be able to resolve file extensions by default").isEqualTo(Collections.singletonList(MediaType.IMAGE_GIF));
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.as("Should be able to resolve file extensions by default")
|
||||
.isEqualTo(Collections.singletonList(MediaType.IMAGE_GIF));
|
||||
|
||||
this.servletRequest.setRequestURI("/flower.foobarbaz");
|
||||
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).as("Should ignore unknown extensions by default").isEqualTo(ContentNegotiationStrategy.MEDIA_TYPE_ALL_LIST);
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.as("Should ignore unknown extensions by default")
|
||||
.isEqualTo(ContentNegotiationStrategy.MEDIA_TYPE_ALL_LIST);
|
||||
|
||||
this.servletRequest.setRequestURI("/flower");
|
||||
this.servletRequest.setParameter("format", "gif");
|
||||
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).as("Should not resolve request parameters by default").isEqualTo(ContentNegotiationStrategy.MEDIA_TYPE_ALL_LIST);
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.as("Should not resolve request parameters by default")
|
||||
.isEqualTo(ContentNegotiationStrategy.MEDIA_TYPE_ALL_LIST);
|
||||
|
||||
this.servletRequest.setRequestURI("/flower");
|
||||
this.servletRequest.addHeader("Accept", MediaType.IMAGE_GIF_VALUE);
|
||||
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).as("Should resolve Accept header by default").isEqualTo(Collections.singletonList(MediaType.IMAGE_GIF));
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.as("Should resolve Accept header by default")
|
||||
.isEqualTo(Collections.singletonList(MediaType.IMAGE_GIF));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -101,29 +110,33 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
|||
|
||||
this.servletRequest.setRequestURI("/flower");
|
||||
this.servletRequest.addParameter("format", "bar");
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).isEqualTo(Collections.singletonList(new MediaType("application", "bar")));
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.isEqualTo(Collections.singletonList(new MediaType("application", "bar")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void favorPath() throws Exception {
|
||||
this.factoryBean.setFavorPathExtension(true);
|
||||
this.factoryBean.addMediaTypes(Collections.singletonMap("bar", new MediaType("application", "bar")));
|
||||
this.factoryBean.addMediaType("bar", new MediaType("application", "bar"));
|
||||
this.factoryBean.afterPropertiesSet();
|
||||
ContentNegotiationManager manager = this.factoryBean.getObject();
|
||||
|
||||
this.servletRequest.setRequestURI("/flower.foo");
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).isEqualTo(Collections.singletonList(new MediaType("application", "foo")));
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.isEqualTo(Collections.singletonList(new MediaType("application", "foo")));
|
||||
|
||||
this.servletRequest.setRequestURI("/flower.bar");
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).isEqualTo(Collections.singletonList(new MediaType("application", "bar")));
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.isEqualTo(Collections.singletonList(new MediaType("application", "bar")));
|
||||
|
||||
this.servletRequest.setRequestURI("/flower.gif");
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).isEqualTo(Collections.singletonList(MediaType.IMAGE_GIF));
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.isEqualTo(Collections.singletonList(MediaType.IMAGE_GIF));
|
||||
}
|
||||
|
||||
@Test // SPR-10170
|
||||
public void favorPathWithIgnoreUnknownPathExtensionTurnedOff() throws Exception {
|
||||
public void favorPathWithIgnoreUnknownPathExtensionTurnedOff() {
|
||||
this.factoryBean.setFavorPathExtension(true);
|
||||
this.factoryBean.setIgnoreUnknownPathExtensions(false);
|
||||
this.factoryBean.afterPropertiesSet();
|
||||
|
@ -139,10 +152,7 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
|||
@Test
|
||||
public void favorParameter() throws Exception {
|
||||
this.factoryBean.setFavorParameter(true);
|
||||
|
||||
Map<String, MediaType> mediaTypes = new HashMap<>();
|
||||
mediaTypes.put("json", MediaType.APPLICATION_JSON);
|
||||
this.factoryBean.addMediaTypes(mediaTypes);
|
||||
this.factoryBean.addMediaType("json", MediaType.APPLICATION_JSON);
|
||||
|
||||
this.factoryBean.afterPropertiesSet();
|
||||
ContentNegotiationManager manager = this.factoryBean.getObject();
|
||||
|
@ -150,11 +160,12 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
|||
this.servletRequest.setRequestURI("/flower");
|
||||
this.servletRequest.addParameter("format", "json");
|
||||
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).isEqualTo(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.isEqualTo(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||
}
|
||||
|
||||
@Test // SPR-10170
|
||||
public void favorParameterWithUnknownMediaType() throws HttpMediaTypeNotAcceptableException {
|
||||
public void favorParameterWithUnknownMediaType() {
|
||||
this.factoryBean.setFavorParameter(true);
|
||||
this.factoryBean.afterPropertiesSet();
|
||||
ContentNegotiationManager manager = this.factoryBean.getObject();
|
||||
|
@ -162,8 +173,52 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
|||
this.servletRequest.setRequestURI("/flower");
|
||||
this.servletRequest.setParameter("format", "invalid");
|
||||
|
||||
assertThatExceptionOfType(HttpMediaTypeNotAcceptableException.class).isThrownBy(() ->
|
||||
manager.resolveMediaTypes(this.webRequest));
|
||||
assertThatExceptionOfType(HttpMediaTypeNotAcceptableException.class)
|
||||
.isThrownBy(() -> manager.resolveMediaTypes(this.webRequest));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mediaTypeMappingsWithoutPathAndParameterStrategies() {
|
||||
|
||||
this.factoryBean.setFavorPathExtension(false);
|
||||
this.factoryBean.setFavorParameter(false);
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.put("JSon", "application/json");
|
||||
|
||||
this.factoryBean.setMediaTypes(properties);
|
||||
this.factoryBean.addMediaType("pdF", MediaType.APPLICATION_PDF);
|
||||
this.factoryBean.addMediaTypes(Collections.singletonMap("xML", MediaType.APPLICATION_XML));
|
||||
|
||||
ContentNegotiationManager manager = this.factoryBean.build();
|
||||
assertThat(manager.getMediaTypeMappings())
|
||||
.hasSize(3)
|
||||
.containsEntry("json", MediaType.APPLICATION_JSON)
|
||||
.containsEntry("pdf", MediaType.APPLICATION_PDF)
|
||||
.containsEntry("xml", MediaType.APPLICATION_XML);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileExtensions() {
|
||||
|
||||
this.factoryBean.setFavorPathExtension(false);
|
||||
this.factoryBean.setFavorParameter(false);
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.put("json", "application/json");
|
||||
properties.put("pdf", "application/pdf");
|
||||
properties.put("xml", "application/xml");
|
||||
this.factoryBean.setMediaTypes(properties);
|
||||
|
||||
this.factoryBean.addMediaType("jsON", MediaType.APPLICATION_JSON);
|
||||
this.factoryBean.addMediaType("pdF", MediaType.APPLICATION_PDF);
|
||||
|
||||
this.factoryBean.addMediaTypes(Collections.singletonMap("JSon", MediaType.APPLICATION_JSON));
|
||||
this.factoryBean.addMediaTypes(Collections.singletonMap("xML", MediaType.APPLICATION_XML));
|
||||
|
||||
ContentNegotiationManager manager = this.factoryBean.build();
|
||||
assertThat(manager.getAllFileExtensions()).containsExactlyInAnyOrder("json", "xml", "pdf");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -175,7 +230,8 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
|||
this.servletRequest.setRequestURI("/flower");
|
||||
this.servletRequest.addHeader("Accept", MediaType.IMAGE_GIF_VALUE);
|
||||
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).isEqualTo(ContentNegotiationStrategy.MEDIA_TYPE_ALL_LIST);
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.isEqualTo(ContentNegotiationStrategy.MEDIA_TYPE_ALL_LIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -210,10 +266,12 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
|||
this.factoryBean.afterPropertiesSet();
|
||||
ContentNegotiationManager manager = this.factoryBean.getObject();
|
||||
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).isEqualTo(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.isEqualTo(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||
|
||||
this.servletRequest.addHeader("Accept", MediaType.ALL_VALUE);
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest)).isEqualTo(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||
assertThat(manager.resolveMediaTypes(this.webRequest))
|
||||
.isEqualTo(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.web.accept;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -34,12 +35,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*/
|
||||
public class MappingMediaTypeFileExtensionResolverTests {
|
||||
|
||||
private final Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
|
||||
private final MappingMediaTypeFileExtensionResolver resolver = new MappingMediaTypeFileExtensionResolver(this.mapping);
|
||||
private static final Map<String, MediaType> DEFAULT_MAPPINGS =
|
||||
Collections.singletonMap("json", MediaType.APPLICATION_JSON);
|
||||
|
||||
|
||||
@Test
|
||||
public void resolveExtensions() {
|
||||
List<String> extensions = this.resolver.resolveFileExtensions(MediaType.APPLICATION_JSON);
|
||||
List<String> extensions = new MappingMediaTypeFileExtensionResolver(DEFAULT_MAPPINGS)
|
||||
.resolveFileExtensions(MediaType.APPLICATION_JSON);
|
||||
|
||||
assertThat(extensions).hasSize(1);
|
||||
assertThat(extensions.get(0)).isEqualTo("json");
|
||||
|
@ -47,20 +50,24 @@ public class MappingMediaTypeFileExtensionResolverTests {
|
|||
|
||||
@Test
|
||||
public void resolveExtensionsNoMatch() {
|
||||
List<String> extensions = this.resolver.resolveFileExtensions(MediaType.TEXT_HTML);
|
||||
|
||||
assertThat(extensions).isEmpty();
|
||||
assertThat(new MappingMediaTypeFileExtensionResolver(DEFAULT_MAPPINGS)
|
||||
.resolveFileExtensions(MediaType.TEXT_HTML)).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit test for SPR-13747 - ensures that reverse lookup of media type from media
|
||||
* type key is case-insensitive.
|
||||
*/
|
||||
@Test
|
||||
@Test // SPR-13747
|
||||
public void lookupMediaTypeCaseInsensitive() {
|
||||
MediaType mediaType = this.resolver.lookupMediaType("JSON");
|
||||
|
||||
assertThat(mediaType).isEqualTo(MediaType.APPLICATION_JSON);
|
||||
assertThat(new MappingMediaTypeFileExtensionResolver(DEFAULT_MAPPINGS).lookupMediaType("JSON"))
|
||||
.isEqualTo(MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allFileExtensions() {
|
||||
Map<String, MediaType> mappings = new HashMap<>();
|
||||
mappings.put("json", MediaType.APPLICATION_JSON);
|
||||
mappings.put("JsOn", MediaType.APPLICATION_JSON);
|
||||
mappings.put("jSoN", MediaType.APPLICATION_JSON);
|
||||
|
||||
MappingMediaTypeFileExtensionResolver resolver = new MappingMediaTypeFileExtensionResolver(mappings);
|
||||
assertThat(resolver.getAllFileExtensions()).containsExactly("json");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue