Browse Source

Fix MediaType lookup for ResourceHttpRequestHandler

As of 4.3 ResourceHttpRequestHandler delegates to the configured
ContentNegotiationManager, or one created internally, to look up
the media type for are resource.

This commit ensures the internally created ContentNegotiationManager is
correctly injected with the ServletContext through which it can perform
lookups as before.

Also the ServletPathContentNegotiationStrategy now checks the
ServletContext first and then delegates to its parent the
PathContentNegotiationStrategy and not vice versa. This is
consistent with how handleNoMatch (also in the same class) works
and also matches how ResourceHttpRequestHandler worked before 4.3.

Issue: SPR-14368
pull/1092/head
Rossen Stoyanchev 10 years ago
parent
commit
e38623df87
  1. 11
      spring-web/src/main/java/org/springframework/web/accept/ServletPathExtensionContentNegotiationStrategy.java
  2. 23
      spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java
  3. 28
      spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java

11
spring-web/src/main/java/org/springframework/web/accept/ServletPathExtensionContentNegotiationStrategy.java

@ -92,15 +92,18 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio @@ -92,15 +92,18 @@ public class ServletPathExtensionContentNegotiationStrategy extends PathExtensio
* @since 4.3
*/
public MediaType getMediaTypeForResource(Resource resource) {
MediaType mediaType = super.getMediaTypeForResource(resource);
if (mediaType == null) {
MediaType mediaType = null;
if (this.servletContext != 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;
if (mediaType == null || MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) {
MediaType superMediaType = super.getMediaTypeForResource(resource);
if (superMediaType != null) {
mediaType = superMediaType;
}
}
return mediaType;
}

23
spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java

@ -20,6 +20,7 @@ import java.io.IOException; @@ -20,6 +20,7 @@ import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
@ -110,6 +111,8 @@ public class ResourceHttpRequestHandler extends WebContentGenerator @@ -110,6 +111,8 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
private ContentNegotiationManager contentNegotiationManager;
private final ContentNegotiationManagerFactoryBean cnmFactoryBean = new ContentNegotiationManagerFactoryBean();
private CorsConfiguration corsConfiguration;
@ -249,6 +252,11 @@ public class ResourceHttpRequestHandler extends WebContentGenerator @@ -249,6 +252,11 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
return this.corsConfiguration;
}
@Override
protected void initServletContext(ServletContext servletContext) {
this.cnmFactoryBean.setServletContext(servletContext);
}
@Override
public void afterPropertiesSet() throws Exception {
@ -261,7 +269,8 @@ public class ResourceHttpRequestHandler extends WebContentGenerator @@ -261,7 +269,8 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
}
initAllowedLocations();
if (this.contentNegotiationManager == null) {
this.contentNegotiationManager = initContentNegotiationManager();
this.cnmFactoryBean.afterPropertiesSet();
this.contentNegotiationManager = this.cnmFactoryBean.getObject();
}
if (this.resourceHttpMessageConverter == null) {
this.resourceHttpMessageConverter = new ResourceHttpMessageConverter();
@ -291,18 +300,6 @@ public class ResourceHttpRequestHandler extends WebContentGenerator @@ -291,18 +300,6 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
}
}
/**
* Create the {@code ContentNegotiationManager} to use to resolve the
* {@link MediaType} for requests. This implementation delegates to
* {@link ContentNegotiationManagerFactoryBean} with default settings.
*/
protected ContentNegotiationManager initContentNegotiationManager() {
ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean();
factory.afterPropertiesSet();
return factory.getObject();
}
/**
* Processes a resource request.
* <p>Checks for the existence of the requested resource in the configured list of locations.

28
spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java

@ -281,6 +281,34 @@ public class ResourceHttpRequestHandlerTests { @@ -281,6 +281,34 @@ public class ResourceHttpRequestHandlerTests {
assertEquals("h1 { color:red; }", this.response.getContentAsString());
}
@Test // SPR-14368
public void getResourceWithMediaTypeResolvedThroughServletContext() throws Exception {
MockServletContext servletContext = new MockServletContext() {
@Override
public String getMimeType(String filePath) {
return "foo/bar";
}
@Override
public String getVirtualServerName() {
return null;
}
};
List<Resource> paths = Collections.singletonList(new ClassPathResource("test/", getClass()));
this.handler = new ResourceHttpRequestHandler();
this.handler.setServletContext(servletContext);
this.handler.setLocations(paths);
this.handler.afterPropertiesSet();
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css");
this.handler.handleRequest(this.request, this.response);
assertEquals("foo/bar", this.response.getContentType());
assertEquals("h1 { color:red; }", this.response.getContentAsString());
}
@Test
public void invalidPath() throws Exception {
for (HttpMethod method : HttpMethod.values()) {

Loading…
Cancel
Save