Support charset config by (static) resource location

This commit adds support for configuring static resource locations
with a charset to be applied to relative paths.
This commit is contained in:
Rossen Stoyanchev
2017-11-01 03:52:32 -04:00
parent db00669197
commit 369d33c3d0
13 changed files with 378 additions and 34 deletions

View File

@@ -20,7 +20,6 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
@@ -418,10 +417,14 @@ public class MvcNamespaceTests {
SimpleUrlHandlerMapping mapping = appContext.getBean(SimpleUrlHandlerMapping.class);
assertNotNull(mapping);
assertNotNull(mapping.getUrlMap().get("/resources/**"));
ResourceHttpRequestHandler handler = appContext.getBean((String) mapping.getUrlMap().get("/resources/**"),
ResourceHttpRequestHandler.class);
String beanName = (String) mapping.getUrlMap().get("/resources/**");
ResourceHttpRequestHandler handler = appContext.getBean(beanName, ResourceHttpRequestHandler.class);
assertNotNull(handler);
assertNotNull(handler.getUrlPathHelper());
assertEquals(1, handler.getLocationCharsets().size());
assertEquals(StandardCharsets.ISO_8859_1, handler.getLocationCharsets().values().iterator().next());
List<ResourceResolver> resolvers = handler.getResourceResolvers();
assertThat(resolvers, Matchers.hasSize(4));
assertThat(resolvers.get(0), Matchers.instanceOf(CachingResourceResolver.class));
@@ -439,6 +442,10 @@ public class MvcNamespaceTests {
assertThat(versionResolver.getStrategyMap().get("/**"),
Matchers.instanceOf(ContentVersionStrategy.class));
PathResourceResolver pathResolver = (PathResourceResolver) resolvers.get(3);
assertEquals(1, pathResolver.getLocationCharsets().size());
assertEquals(StandardCharsets.ISO_8859_1, handler.getLocationCharsets().values().iterator().next());
List<ResourceTransformer> transformers = handler.getResourceTransformers();
assertThat(transformers, Matchers.hasSize(3));
assertThat(transformers.get(0), Matchers.instanceOf(CachingResourceTransformer.class));

View File

@@ -16,6 +16,7 @@
package org.springframework.web.servlet.config.annotation;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.hamcrest.Matchers;
@@ -24,10 +25,12 @@ import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.core.io.UrlResource;
import org.springframework.http.CacheControl;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.http.CacheControl;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
@@ -41,8 +44,14 @@ import org.springframework.web.servlet.resource.ResourceResolver;
import org.springframework.web.servlet.resource.ResourceTransformer;
import org.springframework.web.servlet.resource.VersionResourceResolver;
import org.springframework.web.servlet.resource.WebJarsResourceResolver;
import org.springframework.web.util.UrlPathHelper;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Unit tests for {@link ResourceHandlerRegistry}.
@@ -60,8 +69,10 @@ public class ResourceHandlerRegistryTests {
@Before
public void setUp() {
this.registry = new ResourceHandlerRegistry(new GenericWebApplicationContext(), new MockServletContext());
this.registration = registry.addResourceHandler("/resources/**");
this.registry = new ResourceHandlerRegistry(new GenericWebApplicationContext(),
new MockServletContext(), new ContentNegotiationManager(), new UrlPathHelper());
this.registration = this.registry.addResourceHandler("/resources/**");
this.registration.addResourceLocations("classpath:org/springframework/web/servlet/config/annotation/");
this.response = new MockHttpServletResponse();
}
@@ -211,9 +222,27 @@ public class ResourceHandlerRegistryTests {
assertThat(transformers.get(2), Matchers.sameInstance(cssLinkTransformer));
}
@Test
public void urlResourceWithCharset() throws Exception {
this.registration.addResourceLocations("[charset=ISO-8859-1]file:///tmp");
this.registration.resourceChain(true);
ResourceHttpRequestHandler handler = getHandler("/resources/**");
UrlResource resource = (UrlResource) handler.getLocations().get(1);
assertEquals("file:/tmp", resource.getURL().toString());
assertNotNull(handler.getUrlPathHelper());
assertEquals(1, handler.getLocationCharsets().size());
assertEquals(StandardCharsets.ISO_8859_1, handler.getLocationCharsets().get(resource));
List<ResourceResolver> resolvers = handler.getResourceResolvers();
PathResourceResolver resolver = (PathResourceResolver) resolvers.get(resolvers.size()-1);
assertEquals(1, resolver.getLocationCharsets().size());
assertEquals(StandardCharsets.ISO_8859_1, handler.getLocationCharsets().values().iterator().next());
}
private ResourceHttpRequestHandler getHandler(String pathPattern) {
SimpleUrlHandlerMapping handlerMapping = (SimpleUrlHandlerMapping) this.registry.getHandlerMapping();
return (ResourceHttpRequestHandler) handlerMapping.getUrlMap().get(pathPattern);
SimpleUrlHandlerMapping hm = (SimpleUrlHandlerMapping) this.registry.getHandlerMapping();
return (ResourceHttpRequestHandler) hm.getUrlMap().get(pathPattern);
}
}

View File

@@ -16,17 +16,28 @@
package org.springframework.web.servlet.resource;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.web.context.support.ServletContextResource;
import org.springframework.web.util.UrlPathHelper;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Unit tests for
@@ -132,4 +143,52 @@ public class PathResourceResolverTests {
assertNull(path);
}
@Test
public void relativePathEncodedForUrlResource() throws Exception {
TestUrlResource location = new TestUrlResource("file:///tmp");
List<TestUrlResource> locations = Collections.singletonList(location);
// ISO-8859-1
this.resolver.setUrlPathHelper(new UrlPathHelper());
this.resolver.setLocationCharsets(Collections.singletonMap(location, StandardCharsets.ISO_8859_1));
this.resolver.resolveResource(new MockHttpServletRequest(), "/Ä ;ä.txt", locations, null);
assertEquals("%C4%20%3B%E4.txt", location.getSavedRelativePath());
// UTF-8
this.resolver.setLocationCharsets(Collections.singletonMap(location, StandardCharsets.UTF_8));
this.resolver.resolveResource(new MockHttpServletRequest(), "/Ä ;ä.txt", locations, null);
assertEquals("%C3%84%20%3B%C3%A4.txt", location.getSavedRelativePath());
// UTF-8 by default
this.resolver.setLocationCharsets(Collections.emptyMap());
this.resolver.resolveResource(new MockHttpServletRequest(), "/Ä ;ä.txt", locations, null);
assertEquals("%C3%84%20%3B%C3%A4.txt", location.getSavedRelativePath());
}
private static class TestUrlResource extends UrlResource {
private String relativePath;
public TestUrlResource(String path) throws MalformedURLException {
super(path);
}
public String getSavedRelativePath() {
return this.relativePath;
}
@Override
public Resource createRelative(String relativePath) throws MalformedURLException {
this.relativePath = relativePath;
return this;
}
}
}