Skip to content

Commit 6cabb79

Browse files
committed
Decode resourcePath for classpath locations
Closes gh-22272
1 parent da557e7 commit 6cabb79

File tree

5 files changed

+33
-7
lines changed

5 files changed

+33
-7
lines changed

spring-web/src/main/java/org/springframework/http/server/PathContainer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
public interface PathContainer {
3737

3838
/**
39-
* The original path that was parsed.
39+
* The original (raw, encoded) path that this instance was parsed from.
4040
*/
4141
String value();
4242

@@ -83,7 +83,7 @@ static PathContainer parsePath(String path) {
8383
interface Element {
8484

8585
/**
86-
* Return the original, raw (encoded) value for the path component.
86+
* Return the original (raw, encoded) value of this path element.
8787
*/
8888
String value();
8989
}

spring-webflux/src/main/java/org/springframework/web/reactive/resource/PathResourceResolver.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import java.io.IOException;
2020
import java.io.UnsupportedEncodingException;
2121
import java.net.URLDecoder;
22+
import java.nio.charset.StandardCharsets;
2223
import java.util.Arrays;
2324
import java.util.List;
2425

@@ -31,6 +32,7 @@
3132
import org.springframework.lang.Nullable;
3233
import org.springframework.util.StringUtils;
3334
import org.springframework.web.server.ServerWebExchange;
35+
import org.springframework.web.util.UriUtils;
3436

3537
/**
3638
* A simple {@code ResourceResolver} that tries to find a resource under the given
@@ -108,6 +110,9 @@ private Mono<Resource> getResource(String resourcePath, List<? extends Resource>
108110
*/
109111
protected Mono<Resource> getResource(String resourcePath, Resource location) {
110112
try {
113+
if (location instanceof ClassPathResource) {
114+
resourcePath = UriUtils.decode(resourcePath, StandardCharsets.UTF_8);
115+
}
111116
Resource resource = location.createRelative(resourcePath);
112117
if (resource.isReadable()) {
113118
if (checkResource(resource, location)) {

spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceResolver.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
import reactor.core.publisher.Mono;
2222

2323
import org.springframework.core.io.Resource;
24+
import org.springframework.http.server.RequestPath;
2425
import org.springframework.lang.Nullable;
2526
import org.springframework.web.server.ServerWebExchange;
2627

@@ -40,7 +41,8 @@ public interface ResourceResolver {
4041
* Resolve the supplied request and request path to a {@link Resource} that
4142
* exists under one of the given resource locations.
4243
* @param exchange the current exchange
43-
* @param requestPath the portion of the request path to use
44+
* @param requestPath the portion of the request path to use. This is
45+
* expected to be the encoded path, i.e. {@link RequestPath#value()}.
4446
* @param locations the locations to search in when looking up resources
4547
* @param chain the chain of remaining resolvers to delegate to
4648
* @return the resolved resource or an empty {@code Mono} if unresolved
@@ -53,7 +55,8 @@ Mono<Resource> resolveResource(@Nullable ServerWebExchange exchange, String requ
5355
* to access the resource that is located at the given <em>internal</em>
5456
* resource path.
5557
* <p>This is useful when rendering URL links to clients.
56-
* @param resourcePath the internal resource path
58+
* @param resourcePath the "internal" resource path to resolve a path for
59+
* public use. This is expected to be the encoded path.
5760
* @param locations the locations to search in when looking up resources
5861
* @param chain the chain of resolvers to delegate to
5962
* @return the resolved public URL path or an empty {@code Mono} if unresolved

spring-webflux/src/test/java/org/springframework/web/reactive/resource/PathResourceResolverTests.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
import org.junit.Test;
2323

2424
import org.springframework.core.io.ClassPathResource;
25+
import org.springframework.core.io.FileUrlResource;
2526
import org.springframework.core.io.Resource;
2627
import org.springframework.core.io.UrlResource;
2728

@@ -64,6 +65,22 @@ public void resolveFromClasspathRoot() {
6465
assertNotNull(actual);
6566
}
6667

68+
@Test // gh-22272
69+
public void resolveWithEncodedPath() throws IOException {
70+
Resource classpathLocation = new ClassPathResource("test/", PathResourceResolver.class);
71+
testWithEncodedPath(classpathLocation);
72+
testWithEncodedPath(new FileUrlResource(classpathLocation.getURL()));
73+
}
74+
75+
private void testWithEncodedPath(Resource location) throws IOException {
76+
String path = "foo%20foo.txt";
77+
List<Resource> locations = singletonList(location);
78+
Resource actual = this.resolver.resolveResource(null, path, locations, null).block(TIMEOUT);
79+
80+
assertNotNull(actual);
81+
assertEquals("foo foo.txt", actual.getFile().getName());
82+
}
83+
6784
@Test
6885
public void checkResource() throws IOException {
6986
Resource location = new ClassPathResource("test/", PathResourceResolver.class);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Also some text.

0 commit comments

Comments
 (0)