Configure ResourceUrlProvider in WebFlux
Prior to this commit, no `ResourceUrlProvider` was configured in WebFlux (no bean was contributed by the WebFlux infrastructure). Also, several `ResourceTransformer` instances that extend the `ResourceTransformerSupport` base class need a `ResourceUrlProvider` to resolve absolute URLs when rewriting resource URLs. At this point, no `ResourceUrlProvider` was configured and they could only resolve relative URLs. This commit contributes a new `ResourceUrlProvider` to the WebFlux configuration; this bean can be reused by the WebFlux infrastructure and application code. This also automatically configure this shared `ResourceUrlProvider` instance on the resource chain where needed. Issue: SPR-17433
This commit is contained in:
@@ -28,6 +28,8 @@ import org.springframework.core.io.ResourceLoader;
|
|||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
|
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
|
||||||
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
||||||
|
import org.springframework.web.reactive.resource.ResourceTransformerSupport;
|
||||||
|
import org.springframework.web.reactive.resource.ResourceUrlProvider;
|
||||||
import org.springframework.web.reactive.resource.ResourceWebHandler;
|
import org.springframework.web.reactive.resource.ResourceWebHandler;
|
||||||
import org.springframework.web.server.WebHandler;
|
import org.springframework.web.server.WebHandler;
|
||||||
|
|
||||||
@@ -49,6 +51,7 @@ import org.springframework.web.server.WebHandler;
|
|||||||
* period for served resources.
|
* period for served resources.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Brian Clozel
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public class ResourceHandlerRegistry {
|
public class ResourceHandlerRegistry {
|
||||||
@@ -57,7 +60,10 @@ public class ResourceHandlerRegistry {
|
|||||||
|
|
||||||
private final List<ResourceHandlerRegistration> registrations = new ArrayList<>();
|
private final List<ResourceHandlerRegistration> registrations = new ArrayList<>();
|
||||||
|
|
||||||
private int order = Ordered.LOWEST_PRECEDENCE -1;
|
private int order = Ordered.LOWEST_PRECEDENCE - 1;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private ResourceUrlProvider resourceUrlProvider;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,6 +75,17 @@ public class ResourceHandlerRegistry {
|
|||||||
this.resourceLoader = resourceLoader;
|
this.resourceLoader = resourceLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the {@link ResourceUrlProvider} that can be used by
|
||||||
|
* {@link org.springframework.web.reactive.resource.ResourceTransformer} instances.
|
||||||
|
* @param resourceUrlProvider the resource URL provider to use
|
||||||
|
* @since 5.1.2
|
||||||
|
*/
|
||||||
|
public void setResourceUrlProvider(@Nullable ResourceUrlProvider resourceUrlProvider) {
|
||||||
|
this.resourceUrlProvider = resourceUrlProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a resource handler for serving static resources based on the specified
|
* Add a resource handler for serving static resources based on the specified
|
||||||
@@ -121,6 +138,11 @@ public class ResourceHandlerRegistry {
|
|||||||
for (ResourceHandlerRegistration registration : this.registrations) {
|
for (ResourceHandlerRegistration registration : this.registrations) {
|
||||||
for (String pathPattern : registration.getPathPatterns()) {
|
for (String pathPattern : registration.getPathPatterns()) {
|
||||||
ResourceWebHandler handler = registration.getRequestHandler();
|
ResourceWebHandler handler = registration.getRequestHandler();
|
||||||
|
handler.getResourceTransformers().forEach(transformer -> {
|
||||||
|
if (transformer instanceof ResourceTransformerSupport) {
|
||||||
|
((ResourceTransformerSupport) transformer).setResourceUrlProvider(this.resourceUrlProvider);
|
||||||
|
}
|
||||||
|
});
|
||||||
try {
|
try {
|
||||||
handler.afterPropertiesSet();
|
handler.afterPropertiesSet();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import org.springframework.web.reactive.function.server.support.RouterFunctionMa
|
|||||||
import org.springframework.web.reactive.function.server.support.ServerResponseResultHandler;
|
import org.springframework.web.reactive.function.server.support.ServerResponseResultHandler;
|
||||||
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
|
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
|
||||||
import org.springframework.web.reactive.handler.WebFluxResponseStatusExceptionHandler;
|
import org.springframework.web.reactive.handler.WebFluxResponseStatusExceptionHandler;
|
||||||
|
import org.springframework.web.reactive.resource.ResourceUrlProvider;
|
||||||
import org.springframework.web.reactive.result.SimpleHandlerAdapter;
|
import org.springframework.web.reactive.result.SimpleHandlerAdapter;
|
||||||
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
|
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
|
||||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
|
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
|
||||||
@@ -74,6 +75,7 @@ import org.springframework.web.server.i18n.LocaleContextResolver;
|
|||||||
* <p>Import directly or extend and override protected methods to customize.
|
* <p>Import directly or extend and override protected methods to customize.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Brian Clozel
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public class WebFluxConfigurationSupport implements ApplicationContextAware {
|
public class WebFluxConfigurationSupport implements ApplicationContextAware {
|
||||||
@@ -229,6 +231,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
|
|||||||
resourceLoader = new DefaultResourceLoader();
|
resourceLoader = new DefaultResourceLoader();
|
||||||
}
|
}
|
||||||
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(resourceLoader);
|
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(resourceLoader);
|
||||||
|
registry.setResourceUrlProvider(resourceUrlProvider());
|
||||||
addResourceHandlers(registry);
|
addResourceHandlers(registry);
|
||||||
|
|
||||||
AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
|
AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
|
||||||
@@ -249,6 +252,11 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
|
|||||||
return handlerMapping;
|
return handlerMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ResourceUrlProvider resourceUrlProvider() {
|
||||||
|
return new ResourceUrlProvider();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override this method to add resource handlers for serving static resources.
|
* Override this method to add resource handlers for serving static resources.
|
||||||
* @see ResourceHandlerRegistry
|
* @see ResourceHandlerRegistry
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2017 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -43,6 +43,8 @@ import org.springframework.web.reactive.resource.CssLinkResourceTransformer;
|
|||||||
import org.springframework.web.reactive.resource.PathResourceResolver;
|
import org.springframework.web.reactive.resource.PathResourceResolver;
|
||||||
import org.springframework.web.reactive.resource.ResourceResolver;
|
import org.springframework.web.reactive.resource.ResourceResolver;
|
||||||
import org.springframework.web.reactive.resource.ResourceTransformer;
|
import org.springframework.web.reactive.resource.ResourceTransformer;
|
||||||
|
import org.springframework.web.reactive.resource.ResourceTransformerSupport;
|
||||||
|
import org.springframework.web.reactive.resource.ResourceUrlProvider;
|
||||||
import org.springframework.web.reactive.resource.ResourceWebHandler;
|
import org.springframework.web.reactive.resource.ResourceWebHandler;
|
||||||
import org.springframework.web.reactive.resource.VersionResourceResolver;
|
import org.springframework.web.reactive.resource.VersionResourceResolver;
|
||||||
import org.springframework.web.reactive.resource.WebJarsResourceResolver;
|
import org.springframework.web.reactive.resource.WebJarsResourceResolver;
|
||||||
@@ -120,8 +122,11 @@ public class ResourceHandlerRegistryTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resourceChain() throws Exception {
|
public void resourceChain() throws Exception {
|
||||||
|
ResourceUrlProvider resourceUrlProvider = Mockito.mock(ResourceUrlProvider.class);
|
||||||
|
this.registry.setResourceUrlProvider(resourceUrlProvider);
|
||||||
ResourceResolver mockResolver = Mockito.mock(ResourceResolver.class);
|
ResourceResolver mockResolver = Mockito.mock(ResourceResolver.class);
|
||||||
ResourceTransformer mockTransformer = Mockito.mock(ResourceTransformer.class);
|
ResourceTransformerSupport mockTransformer = Mockito.mock(ResourceTransformerSupport.class);
|
||||||
|
|
||||||
this.registration.resourceChain(true).addResolver(mockResolver).addTransformer(mockTransformer);
|
this.registration.resourceChain(true).addResolver(mockResolver).addTransformer(mockTransformer);
|
||||||
|
|
||||||
ResourceWebHandler handler = getHandler("/resources/**");
|
ResourceWebHandler handler = getHandler("/resources/**");
|
||||||
@@ -138,6 +143,7 @@ public class ResourceHandlerRegistryTests {
|
|||||||
assertThat(transformers, Matchers.hasSize(2));
|
assertThat(transformers, Matchers.hasSize(2));
|
||||||
assertThat(transformers.get(0), Matchers.instanceOf(CachingResourceTransformer.class));
|
assertThat(transformers.get(0), Matchers.instanceOf(CachingResourceTransformer.class));
|
||||||
assertThat(transformers.get(1), Matchers.equalTo(mockTransformer));
|
assertThat(transformers.get(1), Matchers.equalTo(mockTransformer));
|
||||||
|
Mockito.verify(mockTransformer).setResourceUrlProvider(resourceUrlProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ import org.springframework.web.method.HandlerTypePredicate;
|
|||||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
||||||
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
|
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
|
||||||
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
||||||
|
import org.springframework.web.reactive.resource.ResourceUrlProvider;
|
||||||
import org.springframework.web.reactive.result.method.RequestMappingInfo;
|
import org.springframework.web.reactive.result.method.RequestMappingInfo;
|
||||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
|
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
|
||||||
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
|
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
|
||||||
@@ -285,6 +286,15 @@ public class WebFluxConfigurationSupportTests {
|
|||||||
assertNotNull(webHandler);
|
assertNotNull(webHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void resourceUrlProvider() throws Exception {
|
||||||
|
ApplicationContext context = loadConfig(WebFluxConfig.class);
|
||||||
|
|
||||||
|
String name = "resourceUrlProvider";
|
||||||
|
ResourceUrlProvider resourceUrlProvider = context.getBean(name, ResourceUrlProvider.class);
|
||||||
|
assertNotNull(resourceUrlProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void assertHasMessageReader(List<HttpMessageReader<?>> readers, ResolvableType type, MediaType mediaType) {
|
private void assertHasMessageReader(List<HttpMessageReader<?>> readers, ResolvableType type, MediaType mediaType) {
|
||||||
assertTrue(readers.stream().anyMatch(c -> mediaType == null || c.canRead(type, mediaType)));
|
assertTrue(readers.stream().anyMatch(c -> mediaType == null || c.canRead(type, mediaType)));
|
||||||
|
|||||||
Reference in New Issue
Block a user