diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolver.java index d374ac831c..1d58d0d221 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolver.java @@ -20,11 +20,9 @@ import java.util.Locale; import java.util.Map; import java.util.Optional; -import org.springframework.core.io.Resource; import org.springframework.http.MediaType; import org.springframework.http.MediaTypeFactory; import org.springframework.lang.Nullable; -import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; @@ -104,26 +102,4 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType throw new NotAcceptableStatusException(getAllMediaTypes()); } - /** - * 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 {@link MediaTypeFactory}. - * @param resource the resource - * @return the MediaType for the extension, or {@code null} if none determined - */ - @Nullable - public MediaType resolveMediaTypeForResource(Resource resource) { - Assert.notNull(resource, "Resource must not be null"); - MediaType mediaType = null; - String filename = resource.getFilename(); - String extension = StringUtils.getFilenameExtension(filename); - if (extension != null) { - mediaType = getMediaType(extension); - } - if (mediaType == null) { - mediaType = MediaTypeFactory.getMediaType(filename).orElse(null); - } - return mediaType; - } - } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/ResourceHandlerRegistry.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/ResourceHandlerRegistry.java index 0b0b52bdb2..83d0fcdf87 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/ResourceHandlerRegistry.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/ResourceHandlerRegistry.java @@ -26,7 +26,6 @@ import org.springframework.beans.factory.BeanInitializationException; import org.springframework.context.ApplicationContext; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import org.springframework.web.reactive.accept.CompositeContentTypeResolver; import org.springframework.web.reactive.handler.AbstractHandlerMapping; import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; import org.springframework.web.reactive.resource.ResourceWebHandler; @@ -56,8 +55,6 @@ public class ResourceHandlerRegistry { private final ApplicationContext applicationContext; - private final CompositeContentTypeResolver contentTypeResolver; - private final List registrations = new ArrayList<>(); private int order = Integer.MAX_VALUE -1; @@ -68,20 +65,9 @@ public class ResourceHandlerRegistry { * @param applicationContext the Spring application context */ public ResourceHandlerRegistry(ApplicationContext applicationContext) { - this(applicationContext, null); - } - - /** - * Create a new resource handler registry for the given application context. - * @param applicationContext the Spring application context - * @param contentTypeResolver the content type resolver to use - */ - public ResourceHandlerRegistry(ApplicationContext applicationContext, - @Nullable CompositeContentTypeResolver contentTypeResolver) { Assert.notNull(applicationContext, "ApplicationContext is required"); this.applicationContext = applicationContext; - this.contentTypeResolver = contentTypeResolver; } @@ -133,15 +119,12 @@ public class ResourceHandlerRegistry { if (this.registrations.isEmpty()) { return null; } - Map urlMap = new LinkedHashMap<>(); for (ResourceHandlerRegistration registration : this.registrations) { for (String pathPattern : registration.getPathPatterns()) { ResourceWebHandler handler = registration.getRequestHandler(); - handler.setContentTypeResolver(this.contentTypeResolver); try { handler.afterPropertiesSet(); - handler.afterSingletonsInstantiated(); } catch (Exception ex) { throw new BeanInitializationException("Failed to init ResourceHttpRequestHandler", ex); @@ -149,7 +132,6 @@ public class ResourceHandlerRegistry { urlMap.put(pathPattern, handler); } } - SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); handlerMapping.setOrder(this.order); handlerMapping.setUrlMap(urlMap); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java index e3b5b71953..6c48f69720 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java @@ -235,8 +235,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware { */ @Bean public HandlerMapping resourceHandlerMapping() { - ResourceHandlerRegistry registry = - new ResourceHandlerRegistry(this.applicationContext, webFluxContentTypeResolver()); + ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext); addResourceHandlers(registry); AbstractHandlerMapping handlerMapping = registry.getHandlerMapping(); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java index 0170984e09..6251ba904e 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java @@ -23,9 +23,7 @@ import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; @@ -35,7 +33,6 @@ import reactor.core.Exceptions; import reactor.core.publisher.Mono; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.core.ResolvableType; import org.springframework.core.io.Resource; import org.springframework.http.CacheControl; @@ -43,6 +40,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.MediaTypeFactory; import org.springframework.http.codec.ResourceHttpMessageWriter; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -51,8 +49,6 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; import org.springframework.web.reactive.HandlerMapping; -import org.springframework.web.reactive.accept.CompositeContentTypeResolver; -import org.springframework.web.reactive.accept.PathExtensionContentTypeResolver; import org.springframework.web.server.MethodNotAllowedException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebHandler; @@ -85,7 +81,7 @@ import org.springframework.web.server.WebHandler; * @author Brian Clozel * @since 5.0 */ -public class ResourceWebHandler implements WebHandler, InitializingBean, SmartInitializingSingleton { +public class ResourceWebHandler implements WebHandler, InitializingBean { /** Set of supported HTTP methods */ private static final Set SUPPORTED_METHODS = EnumSet.of(HttpMethod.GET, HttpMethod.HEAD); @@ -103,10 +99,6 @@ public class ResourceWebHandler implements WebHandler, InitializingBean, SmartIn private ResourceHttpMessageWriter resourceHttpMessageWriter; - private CompositeContentTypeResolver contentTypeResolver; - - private PathExtensionContentTypeResolver pathExtensionResolver; - /** * Set the {@code List} of {@code Resource} paths to use as sources @@ -197,23 +189,6 @@ public class ResourceWebHandler implements WebHandler, InitializingBean, SmartIn return this.resourceHttpMessageWriter; } - /** - * Configure a {@link CompositeContentTypeResolver} to help determine the - * media types for resources being served. If the manager contains a path - * extension resolver it will be checked for registered file extension. - * @param contentTypeResolver the resolver in use - */ - public void setContentTypeResolver(CompositeContentTypeResolver contentTypeResolver) { - this.contentTypeResolver = contentTypeResolver; - } - - /** - * Return the configured {@link CompositeContentTypeResolver}. - */ - @Nullable - public CompositeContentTypeResolver getContentTypeResolver() { - return this.contentTypeResolver; - } @Override public void afterPropertiesSet() throws Exception { @@ -250,23 +225,6 @@ public class ResourceWebHandler implements WebHandler, InitializingBean, SmartIn } } - @Override - public void afterSingletonsInstantiated() { - this.pathExtensionResolver = initContentNegotiationStrategy(); - } - - protected PathExtensionContentTypeResolver initContentNegotiationStrategy() { - Map mediaTypes = null; - if (getContentTypeResolver() != null) { - PathExtensionContentTypeResolver strategy = - getContentTypeResolver().findResolver(PathExtensionContentTypeResolver.class); - if (strategy != null) { - mediaTypes = new HashMap<>(strategy.getMediaTypes()); - } - } - return new PathExtensionContentTypeResolver(mediaTypes); - } - /** * Processes a resource request. @@ -317,7 +275,7 @@ public class ResourceWebHandler implements WebHandler, InitializingBean, SmartIn } // Check the media type for the resource - MediaType mediaType = getMediaType(exchange, resource); + MediaType mediaType = MediaTypeFactory.getMediaType(resource).orElse(null); if (mediaType != null) { if (logger.isTraceEnabled()) { logger.trace("Determined media type '" + mediaType + "' for " + resource); @@ -474,20 +432,6 @@ public class ResourceWebHandler implements WebHandler, InitializingBean, SmartIn return new DefaultResourceTransformerChain(resolverChain, getResourceTransformers()); } - /** - * Determine the media type for the given request and the resource matched - * to it. This implementation tries to determine the MediaType based on the - * file extension of the Resource via - * {@link PathExtensionContentTypeResolver#resolveMediaTypeForResource(Resource)}. - * @param exchange the current exchange - * @param resource the resource to check - * @return the corresponding media type, or {@code null} if none found - */ - @Nullable - protected MediaType getMediaType(ServerWebExchange exchange, Resource resource) { - return this.pathExtensionResolver.resolveMediaTypeForResource(resource); - } - /** * Set headers on the response. Called for both GET and HEAD requests. * @param exchange current exchange diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java index 77b84a8f03..54f0d6c0df 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceWebHandlerTests.java @@ -49,8 +49,6 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse import org.springframework.mock.http.server.reactive.test.MockServerWebExchange; import org.springframework.util.StringUtils; 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.ServerWebExchange; @@ -86,7 +84,6 @@ public class ResourceWebHandlerTests { this.handler.setLocations(paths); this.handler.setCacheControl(CacheControl.maxAge(3600, TimeUnit.SECONDS)); this.handler.afterPropertiesSet(); - this.handler.afterSingletonsInstantiated(); } @@ -159,7 +156,6 @@ public class ResourceWebHandlerTests { versionResolver.addFixedVersionStrategy("versionString", "/**"); this.handler.setResourceResolvers(Arrays.asList(versionResolver, new PathResourceResolver())); this.handler.afterPropertiesSet(); - this.handler.afterSingletonsInstantiated(); MockServerWebExchange exchange = MockServerHttpRequest.get("").toExchange(); setPathWithinHandlerMapping(exchange, "versionString/foo.css"); @@ -222,39 +218,12 @@ public class ResourceWebHandlerTests { assertResponseBody(exchange, "function foo() { console.log(\"hello world\"); }"); } - @Test // SPR-13658 - public void getResourceWithRegisteredMediaType() throws Exception { - CompositeContentTypeResolver contentTypeResolver = new RequestedContentTypeResolverBuilder() - .mediaType("css", new MediaType("foo", "bar")) - .build(); - - List paths = Collections.singletonList(new ClassPathResource("test/", getClass())); - ResourceWebHandler handler = new ResourceWebHandler(); - handler.setLocations(paths); - handler.setContentTypeResolver(contentTypeResolver); - handler.afterPropertiesSet(); - handler.afterSingletonsInstantiated(); - - MockServerWebExchange exchange = MockServerHttpRequest.get("").toExchange(); - setPathWithinHandlerMapping(exchange, "foo.css"); - handler.handle(exchange).block(TIMEOUT); - - assertEquals(MediaType.parseMediaType("foo/bar"), exchange.getResponse().getHeaders().getContentType()); - assertResponseBody(exchange, "h1 { color:red; }"); - } - @Test // SPR-14577 public void getMediaTypeWithFavorPathExtensionOff() throws Exception { - CompositeContentTypeResolver contentTypeResolver = new RequestedContentTypeResolverBuilder() - .favorPathExtension(false) - .build(); - List paths = Collections.singletonList(new ClassPathResource("test/", getClass())); ResourceWebHandler handler = new ResourceWebHandler(); handler.setLocations(paths); - handler.setContentTypeResolver(contentTypeResolver); handler.afterPropertiesSet(); - handler.afterSingletonsInstantiated(); MockServerWebExchange exchange = MockServerHttpRequest.get("") .header("Accept", "application/json,text/plain,*/*").toExchange(); @@ -367,7 +336,6 @@ public class ResourceWebHandlerTests { handler.setResourceResolvers(Collections.singletonList(pathResolver)); handler.setLocations(Arrays.asList(location1, location2)); handler.afterPropertiesSet(); - handler.afterSingletonsInstantiated(); Resource[] locations = pathResolver.getAllowedLocations(); assertEquals(1, locations.length);