Merge pull request #1356 from poutsma/SPR-14908
This commit is contained in:
@@ -29,7 +29,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterRegistration;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
@@ -47,9 +46,12 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MediaTypeFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
@@ -136,6 +138,8 @@ public class MockServletContext implements ServletContext {
|
||||
|
||||
private String responseCharacterEncoding;
|
||||
|
||||
private final Map<String, MediaType> mimeTypes = new LinkedHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code MockServletContext}, using no base path and a
|
||||
@@ -256,29 +260,27 @@ public class MockServletContext implements ServletContext {
|
||||
return this.effectiveMinorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method uses the default
|
||||
* {@link javax.activation.FileTypeMap#getDefaultFileTypeMap() FileTypeMap}
|
||||
* from the Java Activation Framework to resolve MIME types.
|
||||
* <p>The Java Activation Framework returns {@code "application/octet-stream"}
|
||||
* if the MIME type is unknown (i.e., it never returns {@code null}). Thus, in
|
||||
* order to honor the {@link ServletContext#getMimeType(String)} contract,
|
||||
* this method returns {@code null} if the MIME type is
|
||||
* {@code "application/octet-stream"}.
|
||||
* <p>{@code MockServletContext} does not provide a direct mechanism for
|
||||
* setting a custom MIME type; however, if the default {@code FileTypeMap}
|
||||
* is an instance of {@code javax.activation.MimetypesFileTypeMap}, a custom
|
||||
* MIME type named {@code text/enigma} can be registered for a custom
|
||||
* {@code .puzzle} file extension in the following manner:
|
||||
* <pre style="code">
|
||||
* MimetypesFileTypeMap mimetypesFileTypeMap = (MimetypesFileTypeMap) FileTypeMap.getDefaultFileTypeMap();
|
||||
* mimetypesFileTypeMap.addMimeTypes("text/enigma puzzle");
|
||||
* </pre>
|
||||
*/
|
||||
@Override
|
||||
public String getMimeType(String filePath) {
|
||||
String mimeType = FileTypeMap.getDefaultFileTypeMap().getContentType(filePath);
|
||||
return ("application/octet-stream".equals(mimeType) ? null : mimeType);
|
||||
String extension = StringUtils.getFilenameExtension(filePath);
|
||||
MediaType result;
|
||||
if (this.mimeTypes.containsKey(extension)) {
|
||||
result = this.mimeTypes.get(extension);
|
||||
}
|
||||
else {
|
||||
result = MediaTypeFactory.getMediaType(filePath);
|
||||
}
|
||||
return result != null ? result.toString() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a mime type mapping for use by {@link #getMimeType(String)}.
|
||||
* @param fileExtension a file extension, such as {@code txt}, {@code gif}
|
||||
* @param mimeType the mime type
|
||||
*/
|
||||
public void addMimeType(String fileExtension, MediaType mimeType) {
|
||||
Assert.notNull(fileExtension, "'fileExtension' must not be null");
|
||||
this.mimeTypes.put(fileExtension, mimeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,16 +18,19 @@ package org.springframework.mock.web;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import javax.servlet.FilterRegistration;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletRegistration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
@@ -87,10 +90,7 @@ public class MockServletContextTests {
|
||||
*/
|
||||
@Test
|
||||
public void getMimeTypeWithCustomConfiguredType() {
|
||||
FileTypeMap defaultFileTypeMap = FileTypeMap.getDefaultFileTypeMap();
|
||||
assertThat(defaultFileTypeMap, instanceOf(MimetypesFileTypeMap.class));
|
||||
MimetypesFileTypeMap mimetypesFileTypeMap = (MimetypesFileTypeMap) defaultFileTypeMap;
|
||||
mimetypesFileTypeMap.addMimeTypes("text/enigma enigma");
|
||||
sc.addMimeType("enigma", new MediaType("text", "enigma"));
|
||||
assertEquals("text/enigma", sc.getMimeType("filename.enigma"));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -30,9 +30,12 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.handler;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Tests dependent on access to resources under the web application root directory.
|
||||
@@ -70,7 +73,7 @@ public class WebAppResourceTests {
|
||||
@Test
|
||||
public void resourceRequest() throws Exception {
|
||||
this.mockMvc.perform(get("/resources/Spring.js"))
|
||||
.andExpect(content().contentType("text/javascript"))
|
||||
.andExpect(content().contentType("application/javascript"))
|
||||
.andExpect(content().string(containsString("Spring={};")));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -16,62 +16,88 @@
|
||||
|
||||
package org.springframework.http;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A factory delegate for resolving {@link MediaType} objects
|
||||
* from {@link Resource} handles or filenames.
|
||||
*
|
||||
* <p>This implementation is based on the Java Activation Framework,
|
||||
* sharing the MIME type definitions with Spring's JavaMail support.
|
||||
* However, JAF is an implementation detail and not leaking out.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MediaTypeFactory {
|
||||
|
||||
private static final FileTypeMap fileTypeMap;
|
||||
private static final String MIME_TYPES_FILE_NAME = "/org/springframework/http/mime.types";
|
||||
|
||||
private static final MultiValueMap<String, MediaType> fileExtensionToMediaTypes;
|
||||
|
||||
static {
|
||||
fileTypeMap = loadFileTypeMapFromContextSupportModule();
|
||||
fileExtensionToMediaTypes = parseMimeTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the {@code mime.types} file found in the resources. Format is:
|
||||
* <code>
|
||||
* # comments begin with a '#'<br>
|
||||
* # the format is <mime type> <space separated file extensions><br>
|
||||
* # for example:<br>
|
||||
* text/plain txt text<br>
|
||||
* # this would map file.txt and file.text to<br>
|
||||
* # the mime type "text/plain"<br>
|
||||
* </code>
|
||||
* @return a multi-value map, mapping media types to file extensions.
|
||||
*/
|
||||
private static MultiValueMap<String, MediaType> parseMimeTypes() {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = MediaTypeFactory.class.getResourceAsStream(MIME_TYPES_FILE_NAME);
|
||||
BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(is, StandardCharsets.US_ASCII));
|
||||
|
||||
private static FileTypeMap loadFileTypeMapFromContextSupportModule() {
|
||||
// See if we can find the extended mime.types from the context-support module...
|
||||
Resource mappingLocation = new ClassPathResource("org/springframework/mail/javamail/mime.types");
|
||||
if (mappingLocation.exists()) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = mappingLocation.getInputStream();
|
||||
return new MimetypesFileTypeMap(inputStream);
|
||||
MultiValueMap<String, MediaType> result = new LinkedMultiValueMap<>();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.isEmpty() || line.charAt(0) == '#') {
|
||||
continue;
|
||||
}
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(line, " \t\n\r\f");
|
||||
MediaType mediaType = MediaType.parseMediaType(tokens[0]);
|
||||
|
||||
for (int i = 1; i < tokens.length; i++) {
|
||||
String fileExtension = tokens[i].toLowerCase(Locale.ENGLISH);
|
||||
result.add(fileExtension, mediaType);
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Could not load '" + MIME_TYPES_FILE_NAME + "'", ex);
|
||||
}
|
||||
finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
}
|
||||
catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return FileTypeMap.getDefaultFileTypeMap();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine a media type for the given resource, if possible.
|
||||
* @param resource the resource to introspect
|
||||
@@ -88,8 +114,20 @@ public class MediaTypeFactory {
|
||||
* @return the corresponding media type, or {@code null} if none found
|
||||
*/
|
||||
public static MediaType getMediaType(String filename) {
|
||||
String mediaType = fileTypeMap.getContentType(filename);
|
||||
return (StringUtils.hasText(mediaType) ? MediaType.parseMediaType(mediaType) : null);
|
||||
List<MediaType> mediaTypes = getMediaTypes(filename);
|
||||
return (!mediaTypes.isEmpty() ? mediaTypes.get(0) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the media types for the given file name, if possible.
|
||||
* @param filename the file name plus extension
|
||||
* @return the corresponding media types, or an empty list if none found
|
||||
*/
|
||||
public static List<MediaType> getMediaTypes(String filename) {
|
||||
return Optional.ofNullable(StringUtils.getFilenameExtension(filename))
|
||||
.map(s -> s.toLowerCase(Locale.ENGLISH))
|
||||
.map(fileExtensionToMediaTypes::get)
|
||||
.orElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,16 +27,14 @@ import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MediaTypeFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
/**
|
||||
* Implementation of {@link HttpMessageConverter} that can read/write {@link Resource Resources}
|
||||
* and supports byte range requests.
|
||||
*
|
||||
* <p>By default, this converter can read all media types. The Java Activation Framework (JAF) -
|
||||
* if available - is used to determine the {@code Content-Type} of written resources.
|
||||
* If JAF is not available, {@code application/octet-stream} is used.
|
||||
* <p>By default, this converter can read all media types. The {@link MediaTypeFactory} is used
|
||||
* to determine the {@code Content-Type} of written resources.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
@@ -45,9 +43,6 @@ import org.springframework.util.StreamUtils;
|
||||
*/
|
||||
public class ResourceHttpMessageConverter extends AbstractHttpMessageConverter<Resource> {
|
||||
|
||||
private static final boolean jafPresent = ClassUtils.isPresent(
|
||||
"javax.activation.FileTypeMap", ResourceHttpMessageConverter.class.getClassLoader());
|
||||
|
||||
private final boolean supportsReadStreaming;
|
||||
|
||||
|
||||
@@ -107,12 +102,8 @@ public class ResourceHttpMessageConverter extends AbstractHttpMessageConverter<R
|
||||
|
||||
@Override
|
||||
protected MediaType getDefaultContentType(Resource resource) {
|
||||
if (jafPresent) {
|
||||
return MediaTypeFactory.getMediaType(resource);
|
||||
}
|
||||
else {
|
||||
return MediaType.APPLICATION_OCTET_STREAM;
|
||||
}
|
||||
MediaType mediaType = MediaTypeFactory.getMediaType(resource);
|
||||
return mediaType != null ? mediaType : MediaType.APPLICATION_OCTET_STREAM;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourceRegion;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
@@ -31,7 +32,6 @@ import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MediaTypeFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
@@ -44,9 +44,6 @@ import org.springframework.util.StreamUtils;
|
||||
*/
|
||||
public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
|
||||
|
||||
private static final boolean jafPresent = ClassUtils.isPresent(
|
||||
"javax.activation.FileTypeMap", ResourceHttpMessageConverter.class.getClassLoader());
|
||||
|
||||
public ResourceRegionHttpMessageConverter() {
|
||||
super(MediaType.ALL);
|
||||
}
|
||||
@@ -80,18 +77,24 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected MediaType getDefaultContentType(Object object) {
|
||||
if (jafPresent) {
|
||||
if(object instanceof ResourceRegion) {
|
||||
return MediaTypeFactory.getMediaType(((ResourceRegion) object).getResource());
|
||||
}
|
||||
else {
|
||||
Collection<ResourceRegion> regions = (Collection<ResourceRegion>) object;
|
||||
if(regions.size() > 0) {
|
||||
return MediaTypeFactory.getMediaType(regions.iterator().next().getResource());
|
||||
}
|
||||
Resource resource = null;
|
||||
if (object instanceof ResourceRegion) {
|
||||
resource = ((ResourceRegion) object).getResource();
|
||||
}
|
||||
else {
|
||||
Collection<ResourceRegion> regions = (Collection<ResourceRegion>) object;
|
||||
if (regions.size() > 0) {
|
||||
resource = regions.iterator().next().getResource();
|
||||
}
|
||||
}
|
||||
return MediaType.APPLICATION_OCTET_STREAM;
|
||||
MediaType result = null;
|
||||
if (resource != null) {
|
||||
result = MediaTypeFactory.getMediaType(resource);
|
||||
}
|
||||
if (result == null) {
|
||||
return MediaType.APPLICATION_OCTET_STREAM;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -143,10 +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 and its
|
||||
* {@link PathExtensionContentNegotiationStrategy#setUseJaf(boolean)
|
||||
* useJaf} property is set to "true", the list of extensions may
|
||||
* increase as file extensions are resolved via JAF and cached.
|
||||
* "path extension" strategy, the list of extensions may
|
||||
* increase as file extensions are resolved via
|
||||
* {@link org.springframework.http.MediaTypeFactory} and cached.
|
||||
*/
|
||||
@Override
|
||||
public List<String> getAllFileExtensions() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -28,6 +28,7 @@ import javax.servlet.ServletContext;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MediaTypeFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
@@ -81,8 +82,7 @@ import org.springframework.web.context.ServletContextAware;
|
||||
* "application/json".
|
||||
*
|
||||
* <p>The path extension strategy will also use {@link ServletContext#getMimeType}
|
||||
* and the Java Activation framework (JAF), if available, to resolve a path
|
||||
* extension to a MediaType. You may {@link #setUseJaf suppress} the use of JAF.
|
||||
* and {@link MediaTypeFactory} to resolve a path extension to a MediaType.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
@@ -100,8 +100,6 @@ public class ContentNegotiationManagerFactoryBean
|
||||
|
||||
private boolean ignoreUnknownPathExtensions = true;
|
||||
|
||||
private Boolean useJaf;
|
||||
|
||||
private String parameterName = "format";
|
||||
|
||||
private ContentNegotiationStrategy defaultNegotiationStrategy;
|
||||
@@ -130,8 +128,8 @@ public class ContentNegotiationManagerFactoryBean
|
||||
* (see Spring Framework reference documentation for more details on RFD
|
||||
* attack protection).
|
||||
* <p>The path extension strategy will also try to use
|
||||
* {@link ServletContext#getMimeType} and JAF (if present) to resolve path
|
||||
* extensions. To change this behavior see the {@link #useJaf} property.
|
||||
* {@link ServletContext#getMimeType} and
|
||||
* {@link org.springframework.http.MediaTypeFactory} to resolve path extensions.
|
||||
* @param mediaTypes media type mappings
|
||||
* @see #addMediaType(String, MediaType)
|
||||
* @see #addMediaTypes(Map)
|
||||
@@ -177,18 +175,10 @@ public class ContentNegotiationManagerFactoryBean
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link #setFavorPathExtension favorPathExtension} is set, this
|
||||
* property determines whether to allow use of JAF (Java Activation Framework)
|
||||
* to resolve a path extension to a specific MediaType.
|
||||
* <p>By default this is not set in which case
|
||||
* {@code PathExtensionContentNegotiationStrategy} will use JAF if available.
|
||||
* @deprecated as 5.0, in favor of {@link MediaTypeFactory}, which has no JAF dependency.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUseJaf(boolean useJaf) {
|
||||
this.useJaf = useJaf;
|
||||
}
|
||||
|
||||
private boolean isUseJafTurnedOff() {
|
||||
return (this.useJaf != null && !this.useJaf);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,7 +244,7 @@ public class ContentNegotiationManagerFactoryBean
|
||||
|
||||
if (this.favorPathExtension) {
|
||||
PathExtensionContentNegotiationStrategy strategy;
|
||||
if (this.servletContext != null && !isUseJafTurnedOff()) {
|
||||
if (this.servletContext != null) {
|
||||
strategy = new ServletPathExtensionContentNegotiationStrategy(
|
||||
this.servletContext, this.mediaTypes);
|
||||
}
|
||||
@@ -262,9 +252,6 @@ public class ContentNegotiationManagerFactoryBean
|
||||
strategy = new PathExtensionContentNegotiationStrategy(this.mediaTypes);
|
||||
}
|
||||
strategy.setIgnoreUnknownExtensions(this.ignoreUnknownPathExtensions);
|
||||
if (this.useJaf != null) {
|
||||
strategy.setUseJaf(this.useJaf);
|
||||
}
|
||||
strategies.add(strategy);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MediaTypeFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
@@ -39,26 +38,18 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
* request path to a key to be used to look up a media type.
|
||||
*
|
||||
* <p>If the file extension is not found in the explicit registrations provided
|
||||
* to the constructor, the Java Activation Framework (JAF) is used as a fallback
|
||||
* to the constructor, the {@link MediaTypeFactory} is used as a fallback
|
||||
* mechanism.
|
||||
*
|
||||
* <p>The presence of the JAF is detected and enabled automatically but the
|
||||
* {@link #setUseJaf(boolean)} property may be set to false.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class PathExtensionContentNegotiationStrategy extends AbstractMappingContentNegotiationStrategy {
|
||||
|
||||
private static final boolean JAF_PRESENT = ClassUtils.isPresent("javax.activation.FileTypeMap",
|
||||
PathExtensionContentNegotiationStrategy.class.getClassLoader());
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PathExtensionContentNegotiationStrategy.class);
|
||||
|
||||
private UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
|
||||
private boolean useJaf = true;
|
||||
|
||||
private boolean ignoreUnknownExtensions = true;
|
||||
|
||||
|
||||
@@ -89,11 +80,10 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to use the Java Activation Framework to look up file extensions.
|
||||
* <p>By default this is set to "true" but depends on JAF being present.
|
||||
* @deprecated as 5.0, in favor of {@link MediaTypeFactory}, which has no JAF dependency.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUseJaf(boolean useJaf) {
|
||||
this.useJaf = useJaf;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,11 +112,9 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont
|
||||
protected MediaType handleNoMatch(NativeWebRequest webRequest, String extension)
|
||||
throws HttpMediaTypeNotAcceptableException {
|
||||
|
||||
if (this.useJaf && JAF_PRESENT) {
|
||||
MediaType mediaType = MediaTypeFactory.getMediaType("file." + extension);
|
||||
if (mediaType != null && !MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) {
|
||||
return mediaType;
|
||||
}
|
||||
MediaType mediaType = MediaTypeFactory.getMediaType("file." + extension);
|
||||
if (mediaType != null) {
|
||||
return mediaType;
|
||||
}
|
||||
if (this.ignoreUnknownExtensions) {
|
||||
return null;
|
||||
@@ -138,7 +126,7 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont
|
||||
* A public method exposing the knowledge of the path extension strategy to
|
||||
* resolve file extensions to a {@link MediaType} in this case for a given
|
||||
* {@link Resource}. The method first looks up any explicitly registered
|
||||
* file extensions first and then falls back on JAF if available.
|
||||
* file extensions first and then falls back on {@link MediaTypeFactory} if available.
|
||||
* @param resource the resource to look up
|
||||
* @return the MediaType for the extension, or {@code null} if none found
|
||||
* @since 4.3
|
||||
@@ -151,12 +139,9 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont
|
||||
if (extension != null) {
|
||||
mediaType = lookupMediaType(extension);
|
||||
}
|
||||
if (mediaType == null && JAF_PRESENT) {
|
||||
if (mediaType == null) {
|
||||
mediaType = MediaTypeFactory.getMediaType(filename);
|
||||
}
|
||||
if (MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) {
|
||||
mediaType = null;
|
||||
}
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -52,7 +52,8 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio
|
||||
/**
|
||||
* Create an instance without any mappings to start with. Mappings may be
|
||||
* added later when extensions are resolved through
|
||||
* {@link ServletContext#getMimeType(String)} or via JAF.
|
||||
* {@link ServletContext#getMimeType(String)} or via
|
||||
* {@link org.springframework.http.MediaTypeFactory}.
|
||||
*/
|
||||
public ServletPathExtensionContentNegotiationStrategy(ServletContext context) {
|
||||
this(context, null);
|
||||
@@ -61,7 +62,8 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio
|
||||
|
||||
/**
|
||||
* Resolve file extension via {@link ServletContext#getMimeType(String)}
|
||||
* and also delegate to base class for a potential JAF lookup.
|
||||
* and also delegate to base class for a potential
|
||||
* {@link org.springframework.http.MediaTypeFactory} lookup.
|
||||
*/
|
||||
@Override
|
||||
protected MediaType handleNoMatch(NativeWebRequest webRequest, String extension)
|
||||
|
||||
1855
spring-web/src/main/resources/org/springframework/http/mime.types
Normal file
1855
spring-web/src/main/resources/org/springframework/http/mime.types
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.http;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class MediaTypeFactoryTests {
|
||||
|
||||
@Test
|
||||
public void getMediaType() {
|
||||
assertEquals(MediaType.APPLICATION_XML, MediaTypeFactory.getMediaType("file.xml"));
|
||||
assertEquals(MediaType.parseMediaType("application/javascript"), MediaTypeFactory.getMediaType("file.js"));
|
||||
assertEquals(MediaType.parseMediaType("text/css"), MediaTypeFactory.getMediaType("file.css"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterRegistration;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
@@ -47,9 +46,12 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MediaTypeFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
@@ -136,6 +138,7 @@ public class MockServletContext implements ServletContext {
|
||||
|
||||
private String responseCharacterEncoding;
|
||||
|
||||
private final Map<String, MediaType> mimeTypes = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new {@code MockServletContext}, using no base path and a
|
||||
@@ -256,29 +259,27 @@ public class MockServletContext implements ServletContext {
|
||||
return this.effectiveMinorVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method uses the default
|
||||
* {@link javax.activation.FileTypeMap#getDefaultFileTypeMap() FileTypeMap}
|
||||
* from the Java Activation Framework to resolve MIME types.
|
||||
* <p>The Java Activation Framework returns {@code "application/octet-stream"}
|
||||
* if the MIME type is unknown (i.e., it never returns {@code null}). Thus, in
|
||||
* order to honor the {@link ServletContext#getMimeType(String)} contract,
|
||||
* this method returns {@code null} if the MIME type is
|
||||
* {@code "application/octet-stream"}.
|
||||
* <p>{@code MockServletContext} does not provide a direct mechanism for
|
||||
* setting a custom MIME type; however, if the default {@code FileTypeMap}
|
||||
* is an instance of {@code javax.activation.MimetypesFileTypeMap}, a custom
|
||||
* MIME type named {@code text/enigma} can be registered for a custom
|
||||
* {@code .puzzle} file extension in the following manner:
|
||||
* <pre style="code">
|
||||
* MimetypesFileTypeMap mimetypesFileTypeMap = (MimetypesFileTypeMap) FileTypeMap.getDefaultFileTypeMap();
|
||||
* mimetypesFileTypeMap.addMimeTypes("text/enigma puzzle");
|
||||
* </pre>
|
||||
*/
|
||||
@Override
|
||||
public String getMimeType(String filePath) {
|
||||
String mimeType = FileTypeMap.getDefaultFileTypeMap().getContentType(filePath);
|
||||
return ("application/octet-stream".equals(mimeType) ? null : mimeType);
|
||||
String extension = StringUtils.getFilenameExtension(filePath);
|
||||
MediaType result;
|
||||
if (this.mimeTypes.containsKey(extension)) {
|
||||
result = this.mimeTypes.get(extension);
|
||||
}
|
||||
else {
|
||||
result = MediaTypeFactory.getMediaType(filePath);
|
||||
}
|
||||
return result != null ? result.toString() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a mime type mapping for use by {@link #getMimeType(String)}.
|
||||
* @param fileExtension a file extension, such as {@code txt}, {@code gif}
|
||||
* @param mimeType the mime type
|
||||
*/
|
||||
public void addMimeType(String fileExtension, MediaType mimeType) {
|
||||
Assert.notNull(fileExtension, "'fileExtension' must not be null");
|
||||
this.mimeTypes.put(fileExtension, mimeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -31,7 +31,7 @@ import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link ContentNegotiationManagerFactoryBean} tests.
|
||||
@@ -70,7 +70,7 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
||||
assertEquals("Should be able to resolve file extensions by default",
|
||||
Collections.singletonList(MediaType.IMAGE_GIF), manager.resolveMediaTypes(this.webRequest));
|
||||
|
||||
this.servletRequest.setRequestURI("/flower.xyz");
|
||||
this.servletRequest.setRequestURI("/flower.foobarbaz");
|
||||
|
||||
assertEquals("Should ignore unknown extensions by default",
|
||||
Collections.<MediaType>emptyList(), manager.resolveMediaTypes(this.webRequest));
|
||||
@@ -107,20 +107,6 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
||||
assertEquals(Collections.singletonList(MediaType.IMAGE_GIF), manager.resolveMediaTypes(this.webRequest));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void favorPathWithJafTurnedOff() throws Exception {
|
||||
this.factoryBean.setFavorPathExtension(true);
|
||||
this.factoryBean.setUseJaf(false);
|
||||
this.factoryBean.afterPropertiesSet();
|
||||
ContentNegotiationManager manager = this.factoryBean.getObject();
|
||||
|
||||
this.servletRequest.setRequestURI("/flower.foo");
|
||||
assertEquals(Collections.emptyList(), manager.resolveMediaTypes(this.webRequest));
|
||||
|
||||
this.servletRequest.setRequestURI("/flower.gif");
|
||||
assertEquals(Collections.emptyList(), manager.resolveMediaTypes(this.webRequest));
|
||||
}
|
||||
|
||||
@Test(expected = HttpMediaTypeNotAcceptableException.class) // SPR-10170
|
||||
public void favorPathWithIgnoreUnknownPathExtensionTurnedOff() throws Exception {
|
||||
this.factoryBean.setFavorPathExtension(true);
|
||||
@@ -128,7 +114,7 @@ public class ContentNegotiationManagerFactoryBeanTests {
|
||||
this.factoryBean.afterPropertiesSet();
|
||||
ContentNegotiationManager manager = this.factoryBean.getObject();
|
||||
|
||||
this.servletRequest.setRequestURI("/flower.xyz");
|
||||
this.servletRequest.setRequestURI("/flower.foobarbaz");
|
||||
this.servletRequest.addParameter("format", "json");
|
||||
|
||||
manager.resolveMediaTypes(this.webRequest);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -19,7 +19,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -30,7 +29,8 @@ import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* A test fixture for PathExtensionContentNegotiationStrategy.
|
||||
@@ -70,7 +70,7 @@ public class PathExtensionContentNegotiationStrategyTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveMediaTypesFromJaf() throws Exception {
|
||||
public void resolveMediaTypesFromMediaTypeFactory() throws Exception {
|
||||
|
||||
this.servletRequest.setRequestURI("test.xls");
|
||||
|
||||
@@ -80,21 +80,6 @@ public class PathExtensionContentNegotiationStrategyTests {
|
||||
assertEquals(Arrays.asList(new MediaType("application", "vnd.ms-excel")), mediaTypes);
|
||||
}
|
||||
|
||||
// SPR-10334
|
||||
|
||||
@Test
|
||||
public void getMediaTypeFromFilenameNoJaf() throws Exception {
|
||||
|
||||
this.servletRequest.setRequestURI("test.json");
|
||||
|
||||
ServletContext servletCxt = this.servletRequest.getServletContext();
|
||||
PathExtensionContentNegotiationStrategy strategy = new ServletPathExtensionContentNegotiationStrategy(servletCxt);
|
||||
strategy.setUseJaf(false);
|
||||
List<MediaType> mediaTypes = strategy.resolveMediaTypes(this.webRequest);
|
||||
|
||||
assertEquals(Collections.<MediaType>emptyList(), mediaTypes);
|
||||
}
|
||||
|
||||
// SPR-8678
|
||||
|
||||
@Test
|
||||
@@ -128,7 +113,7 @@ public class PathExtensionContentNegotiationStrategyTests {
|
||||
@Test
|
||||
public void resolveMediaTypesIgnoreUnknownExtension() throws Exception {
|
||||
|
||||
this.servletRequest.setRequestURI("test.xyz");
|
||||
this.servletRequest.setRequestURI("test.foobar");
|
||||
|
||||
PathExtensionContentNegotiationStrategy strategy = new PathExtensionContentNegotiationStrategy();
|
||||
List<MediaType> mediaTypes = strategy.resolveMediaTypes(this.webRequest);
|
||||
@@ -139,7 +124,7 @@ public class PathExtensionContentNegotiationStrategyTests {
|
||||
@Test(expected = HttpMediaTypeNotAcceptableException.class)
|
||||
public void resolveMediaTypesDoNotIgnoreUnknownExtension() throws Exception {
|
||||
|
||||
this.servletRequest.setRequestURI("test.xyz");
|
||||
this.servletRequest.setRequestURI("test.foobar");
|
||||
|
||||
PathExtensionContentNegotiationStrategy strategy = new PathExtensionContentNegotiationStrategy();
|
||||
strategy.setIgnoreUnknownExtensions(false);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -33,17 +33,14 @@ import org.springframework.web.util.UriUtils;
|
||||
* the request path and uses that as the media type lookup key.
|
||||
*
|
||||
* <p>If the file extension is not found in the explicit registrations provided
|
||||
* to the constructor, the Java Activation Framework (JAF) is used as a fallback
|
||||
* mechanism. The presence of the JAF is detected and enabled automatically but
|
||||
* the {@link #setUseJaf(boolean)} property may be set to false.
|
||||
* to the constructor, the {@link MediaTypeFactory} is used as a fallback
|
||||
* mechanism.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class PathExtensionContentTypeResolver extends AbstractMappingContentTypeResolver {
|
||||
|
||||
private boolean useJaf = true;
|
||||
|
||||
private boolean ignoreUnknownExtensions = true;
|
||||
|
||||
|
||||
@@ -63,14 +60,6 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether to use the Java Activation Framework to look up file extensions.
|
||||
* <p>By default this is set to "true" but depends on JAF being present.
|
||||
*/
|
||||
public void setUseJaf(boolean useJaf) {
|
||||
this.useJaf = useJaf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to ignore requests with unknown file extension. Setting this to
|
||||
* {@code false} results in {@code HttpMediaTypeNotAcceptableException}.
|
||||
@@ -90,11 +79,9 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType
|
||||
|
||||
@Override
|
||||
protected MediaType handleNoMatch(String key) throws NotAcceptableStatusException {
|
||||
if (this.useJaf) {
|
||||
MediaType mediaType = MediaTypeFactory.getMediaType("file." + key);
|
||||
if (mediaType != null && !MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) {
|
||||
return mediaType;
|
||||
}
|
||||
MediaType mediaType = MediaTypeFactory.getMediaType("file." + key);
|
||||
if (mediaType != null) {
|
||||
return mediaType;
|
||||
}
|
||||
if (!this.ignoreUnknownExtensions) {
|
||||
throw new NotAcceptableStatusException(getAllMediaTypes());
|
||||
@@ -105,7 +92,7 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType
|
||||
/**
|
||||
* A public method exposing the knowledge of the path extension resolver to
|
||||
* determine the media type for a given {@link Resource}. First it checks
|
||||
* the explicitly registered mappings and then falls back on JAF.
|
||||
* the explicitly registered mappings and then falls back on {@link MediaTypeFactory}.
|
||||
* @param resource the resource
|
||||
* @return the MediaType for the extension, or {@code null} if none determined
|
||||
*/
|
||||
@@ -120,9 +107,6 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType
|
||||
if (mediaType == null) {
|
||||
mediaType = MediaTypeFactory.getMediaType(filename);
|
||||
}
|
||||
if (MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) {
|
||||
mediaType = null;
|
||||
}
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -74,9 +74,9 @@ import org.springframework.util.CollectionUtils;
|
||||
* {@link #mediaTypes(Map)}. This will be used to resolve path extensions or a
|
||||
* parameter value such as "json" to a media type such as "application/json".
|
||||
*
|
||||
* <p>The path extension strategy will also use the Java Activation framework
|
||||
* (JAF), if available, to resolve a path extension to a MediaType. You may
|
||||
* {@link #useJaf suppress} the use of JAF.
|
||||
* <p>The path extension strategy will also use
|
||||
* {@link org.springframework.http.MediaTypeFactory} to resolve a path extension
|
||||
* to a MediaType.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
@@ -93,8 +93,6 @@ public class RequestedContentTypeResolverBuilder {
|
||||
|
||||
private boolean ignoreUnknownPathExtensions = true;
|
||||
|
||||
private Boolean useJaf;
|
||||
|
||||
private String parameterName = "format";
|
||||
|
||||
private RequestedContentTypeResolver contentTypeResolver;
|
||||
@@ -119,8 +117,9 @@ public class RequestedContentTypeResolverBuilder {
|
||||
* 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 JAF (if present) to
|
||||
* resolve path extensions. To change this behavior see {@link #useJaf}.
|
||||
* <p>The path extension strategy will also use the
|
||||
* {@link org.springframework.http.MediaTypeFactory} to resolve path
|
||||
* extensions.
|
||||
* @param mediaTypes media type mappings
|
||||
*/
|
||||
public RequestedContentTypeResolverBuilder mediaTypes(Map<String, MediaType> mediaTypes) {
|
||||
@@ -153,18 +152,6 @@ public class RequestedContentTypeResolverBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link #favorPathExtension favorPathExtension} is set, this
|
||||
* property determines whether to allow use of JAF (Java Activation Framework)
|
||||
* to resolve a path extension to a specific MediaType.
|
||||
* <p>By default this is not set in which case
|
||||
* {@code PathExtensionContentNegotiationStrategy} will use JAF if available.
|
||||
*/
|
||||
public RequestedContentTypeResolverBuilder useJaf(boolean useJaf) {
|
||||
this.useJaf = useJaf;
|
||||
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
|
||||
@@ -224,9 +211,6 @@ public class RequestedContentTypeResolverBuilder {
|
||||
if (this.favorPathExtension) {
|
||||
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver(this.mediaTypes);
|
||||
resolver.setIgnoreUnknownExtensions(this.ignoreUnknownPathExtensions);
|
||||
if (this.useJaf != null) {
|
||||
resolver.setUseJaf(this.useJaf);
|
||||
}
|
||||
resolvers.add(resolver);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -44,7 +44,7 @@ public class CompositeContentTypeResolverBuilderTests {
|
||||
assertEquals("Should be able to resolve file extensions by default",
|
||||
Collections.singletonList(MediaType.IMAGE_GIF), resolver.resolveMediaTypes(exchange));
|
||||
|
||||
exchange = MockServerHttpRequest.get("/flower.xyz").toExchange();
|
||||
exchange = MockServerHttpRequest.get("/flower.foobar").toExchange();
|
||||
|
||||
assertEquals("Should ignore unknown extensions by default",
|
||||
Collections.<MediaType>emptyList(), resolver.resolveMediaTypes(exchange));
|
||||
@@ -80,20 +80,6 @@ public class CompositeContentTypeResolverBuilderTests {
|
||||
assertEquals(Collections.singletonList(MediaType.IMAGE_GIF), resolver.resolveMediaTypes(exchange));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void favorPathWithJafTurnedOff() throws Exception {
|
||||
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder()
|
||||
.favorPathExtension(true)
|
||||
.useJaf(false)
|
||||
.build();
|
||||
|
||||
ServerWebExchange exchange = MockServerHttpRequest.get("/flower.foo").toExchange();
|
||||
assertEquals(Collections.emptyList(), resolver.resolveMediaTypes(exchange));
|
||||
|
||||
exchange = MockServerHttpRequest.get("/flower.gif").toExchange();
|
||||
assertEquals(Collections.emptyList(), resolver.resolveMediaTypes(exchange));
|
||||
}
|
||||
|
||||
@Test(expected = NotAcceptableStatusException.class) // SPR-10170
|
||||
public void favorPathWithIgnoreUnknownPathExtensionTurnedOff() throws Exception {
|
||||
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder()
|
||||
@@ -101,7 +87,7 @@ public class CompositeContentTypeResolverBuilderTests {
|
||||
.ignoreUnknownPathExtensions(false)
|
||||
.build();
|
||||
|
||||
ServerWebExchange exchange = MockServerHttpRequest.get("/flower.xyz?format=json").toExchange();
|
||||
ServerWebExchange exchange = MockServerHttpRequest.get("/flower.foobar?format=json").toExchange();
|
||||
resolver.resolveMediaTypes(exchange);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -59,18 +59,6 @@ public class PathExtensionContentTypeResolverTests {
|
||||
assertEquals(Collections.singletonList(new MediaType("application", "vnd.ms-excel")), mediaTypes);
|
||||
}
|
||||
|
||||
// SPR-10334
|
||||
|
||||
@Test
|
||||
public void getMediaTypeFromFilenameNoJaf() throws Exception {
|
||||
ServerWebExchange exchange = MockServerHttpRequest.get("test.json").toExchange();
|
||||
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver();
|
||||
resolver.setUseJaf(false);
|
||||
List<MediaType> mediaTypes = resolver.resolveMediaTypes(exchange);
|
||||
|
||||
assertEquals(Collections.<MediaType>emptyList(), mediaTypes);
|
||||
}
|
||||
|
||||
// SPR-9390
|
||||
|
||||
@Test
|
||||
@@ -86,7 +74,7 @@ public class PathExtensionContentTypeResolverTests {
|
||||
|
||||
@Test
|
||||
public void resolveMediaTypesIgnoreUnknownExtension() throws Exception {
|
||||
ServerWebExchange exchange = MockServerHttpRequest.get("test.xyz").toExchange();
|
||||
ServerWebExchange exchange = MockServerHttpRequest.get("test.foobar").toExchange();
|
||||
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver();
|
||||
List<MediaType> mediaTypes = resolver.resolveMediaTypes(exchange);
|
||||
|
||||
@@ -95,7 +83,7 @@ public class PathExtensionContentTypeResolverTests {
|
||||
|
||||
@Test(expected = NotAcceptableStatusException.class)
|
||||
public void resolveMediaTypesDoNotIgnoreUnknownExtension() throws Exception {
|
||||
ServerWebExchange exchange = MockServerHttpRequest.get("test.xyz").toExchange();
|
||||
ServerWebExchange exchange = MockServerHttpRequest.get("test.foobar").toExchange();
|
||||
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver();
|
||||
resolver.setIgnoreUnknownExtensions(false);
|
||||
resolver.resolveMediaTypes(exchange);
|
||||
|
||||
@@ -103,7 +103,7 @@ public class WebFluxConfigurationSupportTests {
|
||||
List<MediaType> list = Collections.singletonList(MediaType.APPLICATION_JSON);
|
||||
assertEquals(list, resolver.resolveMediaTypes(exchange));
|
||||
|
||||
exchange = MockServerHttpRequest.get("/path.xml").toExchange();
|
||||
exchange = MockServerHttpRequest.get("/path.foobar").toExchange();
|
||||
assertEquals(Collections.emptyList(), resolver.resolveMediaTypes(exchange));
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.reactive.accept.CompositeContentTypeResolver;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
import org.springframework.web.server.MethodNotAllowedException;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -209,7 +208,7 @@ public class ResourceWebHandlerTests {
|
||||
setPathWithinHandlerMapping(exchange, "js/foo.js");
|
||||
this.handler.handle(exchange).block(TIMEOUT);
|
||||
|
||||
assertEquals(MediaType.parseMediaType("text/javascript"), exchange.getResponse().getHeaders().getContentType());
|
||||
assertEquals(MediaType.parseMediaType("application/javascript"), exchange.getResponse().getHeaders().getContentType());
|
||||
assertResponseBody(exchange, "function foo() { console.log(\"hello world\"); }");
|
||||
}
|
||||
|
||||
@@ -219,7 +218,7 @@ public class ResourceWebHandlerTests {
|
||||
setPathWithinHandlerMapping(exchange, "js/baz.js");
|
||||
this.handler.handle(exchange).block(TIMEOUT);
|
||||
|
||||
assertEquals(MediaType.parseMediaType("text/javascript"), exchange.getResponse().getHeaders().getContentType());
|
||||
assertEquals(MediaType.parseMediaType("application/javascript"), exchange.getResponse().getHeaders().getContentType());
|
||||
assertResponseBody(exchange, "function foo() { console.log(\"hello world\"); }");
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ public class MessageWriterResultHandlerTests {
|
||||
MethodParameter type = on(TestController.class).resolveReturnType(Resource.class);
|
||||
this.resultHandler.writeBody(body, type, this.exchange).block(Duration.ofSeconds(5));
|
||||
|
||||
assertEquals("image/x-png", this.exchange.getResponse().getHeaders().getFirst("Content-Type"));
|
||||
assertEquals("image/png", this.exchange.getResponse().getHeaders().getFirst("Content-Type"));
|
||||
}
|
||||
|
||||
@Test // SPR-13631
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -181,7 +181,7 @@ public class RequestMappingMessageConversionIntegrationTests extends AbstractReq
|
||||
assertTrue(response.hasBody());
|
||||
assertEquals(951, response.getHeaders().getContentLength());
|
||||
assertEquals(951, response.getBody().length);
|
||||
assertEquals(new MediaType("image", "x-png"), response.getHeaders().getContentType());
|
||||
assertEquals(new MediaType("image", "png"), response.getHeaders().getContentType());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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,6 +20,7 @@ import java.util.Map;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MediaTypeFactory;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.accept.ContentNegotiationManagerFactoryBean;
|
||||
import org.springframework.web.accept.ContentNegotiationStrategy;
|
||||
@@ -76,9 +77,8 @@ import org.springframework.web.accept.PathExtensionContentNegotiationStrategy;
|
||||
* type such as "application/json".
|
||||
*
|
||||
* <p>The path extension strategy will also use {@link ServletContext#getMimeType}
|
||||
* and the Java Activation framework (JAF), if available, to resolve a path
|
||||
* extension to a MediaType. You may however {@link #useJaf suppress} the use
|
||||
* of JAF.
|
||||
* and the {@link MediaTypeFactory} to resolve a path
|
||||
* extension to a MediaType.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
@@ -119,8 +119,8 @@ public class ContentNegotiationConfigurer {
|
||||
* (see Spring Framework reference documentation for more details on RFD
|
||||
* attack protection).
|
||||
* <p>The path extension strategy will also try to use
|
||||
* {@link ServletContext#getMimeType} and JAF (if present) to resolve path
|
||||
* extensions. To change this behavior see the {@link #useJaf} property.
|
||||
* {@link ServletContext#getMimeType} and {@link MediaTypeFactory} to resolve path
|
||||
* extensions.
|
||||
* @param extension the key to look up
|
||||
* @param mediaType the media type
|
||||
* @see #mediaTypes(Map)
|
||||
@@ -166,14 +166,10 @@ public class ContentNegotiationConfigurer {
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link #favorPathExtension} is set, this property determines whether
|
||||
* to allow use of JAF (Java Activation Framework) to resolve a path
|
||||
* extension to a specific MediaType.
|
||||
* <p>By default this is not set in which case
|
||||
* {@code PathExtensionContentNegotiationStrategy} will use JAF if available.
|
||||
* @deprecated as 5.0, in favor of {@link MediaTypeFactory}, which has no JAF dependency.
|
||||
*/
|
||||
@Deprecated
|
||||
public ContentNegotiationConfigurer useJaf(boolean useJaf) {
|
||||
this.factory.setUseJaf(useJaf);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -45,7 +45,11 @@ import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.accept.ContentNegotiationManagerFactoryBean;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Unit tests for ResourceHttpRequestHandler.
|
||||
@@ -243,7 +247,7 @@ public class ResourceHttpRequestHandlerTests {
|
||||
@Test // SPR-13658
|
||||
public void getResourceWithRegisteredMediaType() throws Exception {
|
||||
ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean();
|
||||
factory.addMediaType("css", new MediaType("foo", "bar"));
|
||||
factory.addMediaType("bar", new MediaType("foo", "bar"));
|
||||
factory.afterPropertiesSet();
|
||||
ContentNegotiationManager manager = factory.getObject();
|
||||
|
||||
@@ -254,7 +258,7 @@ public class ResourceHttpRequestHandlerTests {
|
||||
handler.setContentNegotiationManager(manager);
|
||||
handler.afterPropertiesSet();
|
||||
|
||||
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css");
|
||||
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.bar");
|
||||
handler.handleRequest(this.request, this.response);
|
||||
|
||||
assertEquals("foo/bar", this.response.getContentType());
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
h1 { color:red; }
|
||||
Reference in New Issue
Block a user