Use ContentNegotiationManager for static resources

The ResourceHttpRequestHandler now relies on the conifgured
ContentNegotiationManager to determine the content type for resource
requests rather than implementing that internally.

First we check against the matched resource based on the resource file
extension. Then we expand the check against the request with any
configured content negotiation strategy.

Issue: SPR-13658
This commit is contained in:
Rossen Stoyanchev
2016-03-04 13:24:14 -05:00
parent 1a76f7e9c2
commit f162256906
6 changed files with 181 additions and 69 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -96,6 +96,22 @@ public class ContentNegotiationManager implements ContentNegotiationStrategy,
return this.strategies;
}
/**
* Find a {@code ContentNegotiationStrategy} of the given type.
* @param strategyType the strategy type
* @return the first matching strategy or {@code null}.
* @since 4.3
*/
@SuppressWarnings("unchecked")
public <T extends ContentNegotiationStrategy> T getStrategy(Class<T> strategyType) {
for (ContentNegotiationStrategy strategy : getStrategies()) {
if (strategyType.isInstance(strategy)) {
return (T) strategy;
}
}
return null;
}
/**
* Register more {@code MediaTypeFileExtensionResolver} instances in addition
* to those detected at construction.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,6 +30,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
@@ -135,6 +136,32 @@ public class PathExtensionContentNegotiationStrategy
throw new HttpMediaTypeNotAcceptableException(getAllMediaTypes());
}
/**
* A public method exposing the knowledge of the path extension strategy to
* resolve file extensions to a 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.
* @param resource the resource to look up
* @return the MediaType for the extension or {@code null}.
* @since 4.3
*/
public MediaType getMediaTypeForResource(Resource resource) {
Assert.notNull(resource);
MediaType mediaType = null;
String filename = resource.getFilename();
String extension = StringUtils.getFilenameExtension(filename);
if (extension != null) {
mediaType = lookupMediaType(extension);
}
if (mediaType == null && JAF_PRESENT) {
mediaType = JafMediaTypeFactory.getMediaType(filename);
}
if (MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) {
mediaType = null;
}
return mediaType;
}
/**
* Inner class to avoid hard-coded dependency on JAF.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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,6 +18,7 @@ package org.springframework.web.accept;
import java.util.Map;
import javax.servlet.ServletContext;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -82,4 +83,26 @@ public class ServletPathExtensionContentNegotiationStrategy
return mediaType;
}
/**
* Extends the base class
* {@link PathExtensionContentNegotiationStrategy#getMediaTypeForResource}
* with the ability to also look up through the ServletContext.
* @param resource the resource to look up
* @return the MediaType for the extension or {@code null}.
* @since 4.3
*/
public MediaType getMediaTypeForResource(Resource resource) {
MediaType mediaType = super.getMediaTypeForResource(resource);
if (mediaType == null) {
String mimeType = this.servletContext.getMimeType(resource.getFilename());
if (StringUtils.hasText(mimeType)) {
mediaType = MediaType.parseMediaType(mimeType);
}
}
if (MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) {
mediaType = null;
}
return mediaType;
}
}