Introduce 'useRegisteredExtensionsOnly' property in classes using MediaTypeFactory
This commit introduces a `useRegisteredExtensionsOnly` property that
indicates whether classes that use the `MediaTypeFactory` for supplying
default media types can do so.
- In classes that were introduced in Spring 5.0, the
`useRegisteredExtensionsOnly` property takes the place of the
`useJaf` property that was removed in 0aaa652
- In classes that existed before Spring 5.0, the
`useRegisteredExtensionsOnly` property is added in addition to the
deprecated `useJaf`, the latter delegating to the former, but with
flipped behavior.
Issue: SPR-14908
This commit is contained in:
@@ -104,11 +104,9 @@ public class MediaTypeFactory {
|
||||
* @return the corresponding media type, or {@code null} if none found
|
||||
*/
|
||||
public static Optional<MediaType> getMediaType(Resource resource) {
|
||||
if (resource == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
String filename = resource.getFilename();
|
||||
return (filename != null ? getMediaType(filename) : Optional.empty());
|
||||
return Optional.ofNullable(resource)
|
||||
.map(Resource::getFilename)
|
||||
.flatMap(MediaTypeFactory::getMediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,8 +115,7 @@ public class MediaTypeFactory {
|
||||
* @return the corresponding media type, or {@code null} if none found
|
||||
*/
|
||||
public static Optional<MediaType> getMediaType(String filename) {
|
||||
List<MediaType> mediaTypes = getMediaTypes(filename);
|
||||
return (!mediaTypes.isEmpty() ? Optional.of(mediaTypes.get(0)) : Optional.empty());
|
||||
return getMediaTypes(filename).stream().findFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -143,7 +143,9 @@ public class ContentNegotiationManager implements ContentNegotiationStrategy, Me
|
||||
* <p>At startup this method returns extensions explicitly registered with
|
||||
* either {@link PathExtensionContentNegotiationStrategy} or
|
||||
* {@link ParameterContentNegotiationStrategy}. At runtime if there is a
|
||||
* "path extension" strategy, the list of extensions may
|
||||
* "path extension" strategy and its
|
||||
* {@link PathExtensionContentNegotiationStrategy#setUseRegisteredExtensionsOnly(boolean)
|
||||
* useRegisteredExtensionsOnly} property is set to "false", the list of extensions may
|
||||
* increase as file extensions are resolved via
|
||||
* {@link org.springframework.http.MediaTypeFactory} and cached.
|
||||
*/
|
||||
|
||||
@@ -100,6 +100,8 @@ public class ContentNegotiationManagerFactoryBean
|
||||
|
||||
private boolean ignoreUnknownPathExtensions = true;
|
||||
|
||||
private Boolean useRegisteredExtensionsOnly;
|
||||
|
||||
private String parameterName = "format";
|
||||
|
||||
private ContentNegotiationStrategy defaultNegotiationStrategy;
|
||||
@@ -175,10 +177,27 @@ public class ContentNegotiationManagerFactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated as 5.0, in favor of {@link MediaTypeFactory}, which has no JAF dependency.
|
||||
* @deprecated as of 5.0, in favor of {@link #setUseRegisteredExtensionsOnly(boolean)}, which
|
||||
* has reverse behavior.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUseJaf(boolean useJaf) {
|
||||
setUseRegisteredExtensionsOnly(!useJaf);
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link #setFavorPathExtension favorPathExtension} is set, this
|
||||
* property determines whether to use only registered {@code MediaType} mappings
|
||||
* to resolve a path extension to a specific MediaType.
|
||||
* <p>By default this is not set in which case
|
||||
* {@code PathExtensionContentNegotiationStrategy} will use defaults if available.
|
||||
*/
|
||||
public void setUseRegisteredExtensionsOnly(boolean useRegisteredExtensionsOnly) {
|
||||
this.useRegisteredExtensionsOnly = useRegisteredExtensionsOnly;
|
||||
}
|
||||
|
||||
private boolean useRegisteredExtensionsOnly() {
|
||||
return (this.useRegisteredExtensionsOnly != null && this.useRegisteredExtensionsOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,7 +263,7 @@ public class ContentNegotiationManagerFactoryBean
|
||||
|
||||
if (this.favorPathExtension) {
|
||||
PathExtensionContentNegotiationStrategy strategy;
|
||||
if (this.servletContext != null) {
|
||||
if (this.servletContext != null && !useRegisteredExtensionsOnly()) {
|
||||
strategy = new ServletPathExtensionContentNegotiationStrategy(
|
||||
this.servletContext, this.mediaTypes);
|
||||
}
|
||||
@@ -252,6 +271,9 @@ public class ContentNegotiationManagerFactoryBean
|
||||
strategy = new PathExtensionContentNegotiationStrategy(this.mediaTypes);
|
||||
}
|
||||
strategy.setIgnoreUnknownExtensions(this.ignoreUnknownPathExtensions);
|
||||
if (this.useRegisteredExtensionsOnly != null) {
|
||||
strategy.setUseRegisteredExtensionsOnly(this.useRegisteredExtensionsOnly);
|
||||
}
|
||||
strategies.add(strategy);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont
|
||||
|
||||
private UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
|
||||
private boolean useRegisteredExtensionsOnly = false;
|
||||
|
||||
private boolean ignoreUnknownExtensions = true;
|
||||
|
||||
|
||||
@@ -81,10 +83,20 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated as 5.0, in favor of {@link MediaTypeFactory}, which has no JAF dependency.
|
||||
* @deprecated as of 5.0, in favor of {@link #setUseRegisteredExtensionsOnly(boolean)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUseJaf(boolean useJaf) {
|
||||
setUseRegisteredExtensionsOnly(!useJaf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to only use the registered mappings to look up file extensions, or also refer to
|
||||
* defaults.
|
||||
* <p>By default this is set to {@code false}, meaning that defaults are used.
|
||||
*/
|
||||
public void setUseRegisteredExtensionsOnly(boolean useRegisteredExtensionsOnly) {
|
||||
this.useRegisteredExtensionsOnly = useRegisteredExtensionsOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,9 +125,11 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont
|
||||
protected MediaType handleNoMatch(NativeWebRequest webRequest, String extension)
|
||||
throws HttpMediaTypeNotAcceptableException {
|
||||
|
||||
Optional<MediaType> mediaType = MediaTypeFactory.getMediaType("file." + extension);
|
||||
if (mediaType.isPresent()) {
|
||||
return mediaType.get();
|
||||
if (!this.useRegisteredExtensionsOnly) {
|
||||
Optional<MediaType> mediaType = MediaTypeFactory.getMediaType("file." + extension);
|
||||
if (mediaType.isPresent()) {
|
||||
return mediaType.get();
|
||||
}
|
||||
}
|
||||
if (this.ignoreUnknownExtensions) {
|
||||
return null;
|
||||
|
||||
@@ -93,6 +93,7 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio
|
||||
* @return the MediaType for the extension or {@code null}.
|
||||
* @since 4.3
|
||||
*/
|
||||
@Override
|
||||
public MediaType getMediaTypeForResource(Resource resource) {
|
||||
MediaType mediaType = null;
|
||||
if (this.servletContext != null) {
|
||||
|
||||
@@ -42,6 +42,8 @@ import org.springframework.web.util.UriUtils;
|
||||
*/
|
||||
public class PathExtensionContentTypeResolver extends AbstractMappingContentTypeResolver {
|
||||
|
||||
private boolean useRegisteredExtensionsOnly = false;
|
||||
|
||||
private boolean ignoreUnknownExtensions = true;
|
||||
|
||||
|
||||
@@ -61,6 +63,15 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether to only use the registered mappings to look up file extensions, or also refer to
|
||||
* defaults.
|
||||
* <p>By default this is set to {@code false}, meaning that defaults are used.
|
||||
*/
|
||||
public void setUseRegisteredExtensionsOnly(boolean useRegisteredExtensionsOnly) {
|
||||
this.useRegisteredExtensionsOnly = useRegisteredExtensionsOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to ignore requests with unknown file extension. Setting this to
|
||||
* {@code false} results in {@code HttpMediaTypeNotAcceptableException}.
|
||||
@@ -80,14 +91,16 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType
|
||||
|
||||
@Override
|
||||
protected MediaType handleNoMatch(String key) throws NotAcceptableStatusException {
|
||||
Optional<MediaType> mediaType = MediaTypeFactory.getMediaType("file." + key);
|
||||
if (mediaType.isPresent()) {
|
||||
return mediaType.get();
|
||||
if (!this.useRegisteredExtensionsOnly) {
|
||||
Optional<MediaType> mediaType = MediaTypeFactory.getMediaType("file." + key);
|
||||
if (mediaType.isPresent()) {
|
||||
return mediaType.get();
|
||||
}
|
||||
}
|
||||
if (!this.ignoreUnknownExtensions) {
|
||||
throw new NotAcceptableStatusException(getAllMediaTypes());
|
||||
if (this.ignoreUnknownExtensions) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
throw new NotAcceptableStatusException(getAllMediaTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -93,6 +93,8 @@ public class RequestedContentTypeResolverBuilder {
|
||||
|
||||
private boolean ignoreUnknownPathExtensions = true;
|
||||
|
||||
private Boolean useRegisteredExtensionsOnly;
|
||||
|
||||
private String parameterName = "format";
|
||||
|
||||
private RequestedContentTypeResolver contentTypeResolver;
|
||||
@@ -152,6 +154,18 @@ public class RequestedContentTypeResolverBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link #favorPathExtension favorPathExtension} is set, this
|
||||
* property determines whether to use only registered {@code MediaType} mappings
|
||||
* to resolve a path extension to a specific MediaType.
|
||||
* <p>By default this is not set in which case
|
||||
* {@code PathExtensionContentNegotiationStrategy} will use defaults if available.
|
||||
*/
|
||||
public RequestedContentTypeResolverBuilder useRegisteredExtensionsOnly(boolean useRegisteredExtensionsOnly) {
|
||||
this.useRegisteredExtensionsOnly = useRegisteredExtensionsOnly;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a request parameter ("format" by default) should be used to
|
||||
* determine the requested media type. For this option to work you must
|
||||
@@ -211,6 +225,9 @@ public class RequestedContentTypeResolverBuilder {
|
||||
if (this.favorPathExtension) {
|
||||
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver(this.mediaTypes);
|
||||
resolver.setIgnoreUnknownExtensions(this.ignoreUnknownPathExtensions);
|
||||
if (this.useRegisteredExtensionsOnly != null) {
|
||||
resolver.setUseRegisteredExtensionsOnly(this.useRegisteredExtensionsOnly);
|
||||
}
|
||||
resolvers.add(resolver);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ public class ContentNegotiationConfigurer {
|
||||
* attack protection).
|
||||
* <p>The path extension strategy will also try to use
|
||||
* {@link ServletContext#getMimeType} and {@link MediaTypeFactory} to resolve path
|
||||
* extensions.
|
||||
* extensions. To change this behavior see the {@link #useRegisteredExtensionsOnly} property.
|
||||
* @param extension the key to look up
|
||||
* @param mediaType the media type
|
||||
* @see #mediaTypes(Map)
|
||||
@@ -166,10 +166,23 @@ public class ContentNegotiationConfigurer {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated as 5.0, in favor of {@link MediaTypeFactory}, which has no JAF dependency.
|
||||
* @deprecated as of 5.0, in favor of {@link #useRegisteredExtensionsOnly(boolean)}, which
|
||||
* has reverse behavior.
|
||||
*/
|
||||
@Deprecated
|
||||
public ContentNegotiationConfigurer useJaf(boolean useJaf) {
|
||||
return this.useRegisteredExtensionsOnly(!useJaf);
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link #favorPathExtension favorPathExtension} is set, this
|
||||
* property determines whether to use only registered {@code MediaType} mappings
|
||||
* to resolve a path extension to a specific MediaType.
|
||||
* <p>By default this is not set in which case
|
||||
* {@code PathExtensionContentNegotiationStrategy} will use defaults if available.
|
||||
*/
|
||||
public ContentNegotiationConfigurer useRegisteredExtensionsOnly(boolean useRegisteredExtensionsOnly) {
|
||||
this.factory.setUseRegisteredExtensionsOnly(useRegisteredExtensionsOnly);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user