From 6cabb79f0fb165d9dc4706ba46f25f4e8e6ceb57 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 5 Apr 2019 16:23:20 -0400 Subject: [PATCH] Decode resourcePath for classpath locations Closes gh-22272 --- .../http/server/PathContainer.java | 4 ++-- .../resource/PathResourceResolver.java | 7 ++++++- .../reactive/resource/ResourceResolver.java | 9 ++++++--- .../resource/PathResourceResolverTests.java | 19 ++++++++++++++++++- .../web/reactive/resource/test/foo foo.txt | 1 + 5 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 spring-webflux/src/test/resources/org/springframework/web/reactive/resource/test/foo foo.txt diff --git a/spring-web/src/main/java/org/springframework/http/server/PathContainer.java b/spring-web/src/main/java/org/springframework/http/server/PathContainer.java index 40bdaedaf31..93599a78c7a 100644 --- a/spring-web/src/main/java/org/springframework/http/server/PathContainer.java +++ b/spring-web/src/main/java/org/springframework/http/server/PathContainer.java @@ -36,7 +36,7 @@ import org.springframework.util.MultiValueMap; public interface PathContainer { /** - * The original path that was parsed. + * The original (raw, encoded) path that this instance was parsed from. */ String value(); @@ -83,7 +83,7 @@ public interface PathContainer { interface Element { /** - * Return the original, raw (encoded) value for the path component. + * Return the original (raw, encoded) value of this path element. */ String value(); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/PathResourceResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/PathResourceResolver.java index e46678de940..17cda85be2a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/PathResourceResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/PathResourceResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -19,6 +19,7 @@ package org.springframework.web.reactive.resource; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; @@ -31,6 +32,7 @@ import org.springframework.core.io.UrlResource; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.util.UriUtils; /** * A simple {@code ResourceResolver} that tries to find a resource under the given @@ -108,6 +110,9 @@ public class PathResourceResolver extends AbstractResourceResolver { */ protected Mono getResource(String resourcePath, Resource location) { try { + if (location instanceof ClassPathResource) { + resourcePath = UriUtils.decode(resourcePath, StandardCharsets.UTF_8); + } Resource resource = location.createRelative(resourcePath); if (resource.isReadable()) { if (checkResource(resource, location)) { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceResolver.java index c79882749e1..610e052a782 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 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. @@ -21,6 +21,7 @@ import java.util.List; import reactor.core.publisher.Mono; import org.springframework.core.io.Resource; +import org.springframework.http.server.RequestPath; import org.springframework.lang.Nullable; import org.springframework.web.server.ServerWebExchange; @@ -40,7 +41,8 @@ public interface ResourceResolver { * Resolve the supplied request and request path to a {@link Resource} that * exists under one of the given resource locations. * @param exchange the current exchange - * @param requestPath the portion of the request path to use + * @param requestPath the portion of the request path to use. This is + * expected to be the encoded path, i.e. {@link RequestPath#value()}. * @param locations the locations to search in when looking up resources * @param chain the chain of remaining resolvers to delegate to * @return the resolved resource or an empty {@code Mono} if unresolved @@ -53,7 +55,8 @@ public interface ResourceResolver { * to access the resource that is located at the given internal * resource path. *

This is useful when rendering URL links to clients. - * @param resourcePath the internal resource path + * @param resourcePath the "internal" resource path to resolve a path for + * public use. This is expected to be the encoded path. * @param locations the locations to search in when looking up resources * @param chain the chain of resolvers to delegate to * @return the resolved public URL path or an empty {@code Mono} if unresolved diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/PathResourceResolverTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/PathResourceResolverTests.java index 2acc8c67489..4afd4c07659 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/PathResourceResolverTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/PathResourceResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -22,6 +22,7 @@ import java.util.List; import org.junit.Test; import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.FileUrlResource; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; @@ -64,6 +65,22 @@ public class PathResourceResolverTests { assertNotNull(actual); } + @Test // gh-22272 + public void resolveWithEncodedPath() throws IOException { + Resource classpathLocation = new ClassPathResource("test/", PathResourceResolver.class); + testWithEncodedPath(classpathLocation); + testWithEncodedPath(new FileUrlResource(classpathLocation.getURL())); + } + + private void testWithEncodedPath(Resource location) throws IOException { + String path = "foo%20foo.txt"; + List locations = singletonList(location); + Resource actual = this.resolver.resolveResource(null, path, locations, null).block(TIMEOUT); + + assertNotNull(actual); + assertEquals("foo foo.txt", actual.getFile().getName()); + } + @Test public void checkResource() throws IOException { Resource location = new ClassPathResource("test/", PathResourceResolver.class); diff --git a/spring-webflux/src/test/resources/org/springframework/web/reactive/resource/test/foo foo.txt b/spring-webflux/src/test/resources/org/springframework/web/reactive/resource/test/foo foo.txt new file mode 100644 index 00000000000..ba6848666e4 --- /dev/null +++ b/spring-webflux/src/test/resources/org/springframework/web/reactive/resource/test/foo foo.txt @@ -0,0 +1 @@ +Also some text. \ No newline at end of file