Skip to content

Commit 789d7ef

Browse files
committed
Assert static resource location
Closes gh-33712
1 parent f204f49 commit 789d7ef

File tree

10 files changed

+92
-9
lines changed

10 files changed

+92
-9
lines changed

Diff for: spring-webflux/src/main/java/org/springframework/web/reactive/function/server/PathResourceLookupFunction.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,11 @@ class PathResourceLookupFunction implements Function<ServerRequest, Mono<Resourc
4444

4545
public PathResourceLookupFunction(String pattern, Resource location) {
4646
Assert.hasLength(pattern, "'pattern' must not be empty");
47-
Assert.notNull(location, "'location' must not be null");
47+
ResourceHandlerUtils.assertResourceLocation(location);
4848
this.pattern = PathPatternParser.defaultInstance.parse(pattern);
4949
this.location = location;
5050
}
5151

52-
5352
@Override
5453
public Mono<Resource> apply(ServerRequest request) {
5554
PathContainer pathContainer = request.requestPath().pathWithinApplication();

Diff for: spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceHandlerUtils.java

+38
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.springframework.core.io.Resource;
2828
import org.springframework.core.io.UrlResource;
2929
import org.springframework.core.log.LogFormatUtils;
30+
import org.springframework.lang.Nullable;
31+
import org.springframework.util.Assert;
3032
import org.springframework.util.ResourceUtils;
3133
import org.springframework.util.StringUtils;
3234
import org.springframework.web.util.UriUtils;
@@ -42,6 +44,42 @@ public abstract class ResourceHandlerUtils {
4244

4345
private static final Log logger = LogFactory.getLog(ResourceHandlerUtils.class);
4446

47+
private static final String FOLDER_SEPARATOR = "/";
48+
49+
private static final String WINDOWS_FOLDER_SEPARATOR = "\\";
50+
51+
52+
/**
53+
* Assert the given location is not null, and its path ends on slash.
54+
*/
55+
public static void assertResourceLocation(@Nullable Resource location) {
56+
Assert.notNull(location, "Resource location must not be null");
57+
try {
58+
String path;
59+
if (location instanceof UrlResource) {
60+
path = location.getURL().toExternalForm();
61+
}
62+
else if (location instanceof ClassPathResource classPathResource) {
63+
path = classPathResource.getPath();
64+
}
65+
else {
66+
path = location.getURL().getPath();
67+
}
68+
assertLocationPath(path);
69+
}
70+
catch (IOException ex) {
71+
// ignore
72+
}
73+
}
74+
75+
/**
76+
* Assert the given location path is a directory and ends on slash.
77+
*/
78+
public static void assertLocationPath(@Nullable String path) {
79+
Assert.notNull(path, "Resource location path must not be null");
80+
Assert.isTrue(path.endsWith(FOLDER_SEPARATOR) || path.endsWith(WINDOWS_FOLDER_SEPARATOR),
81+
"Resource location does not end with slash: " + path);
82+
}
4583

4684
/**
4785
* Normalize the given resource path replacing the following:

Diff for: spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,10 @@ public List<String> getLocationValues() {
160160
public void setLocations(@Nullable List<Resource> locations) {
161161
this.locationResources.clear();
162162
if (locations != null) {
163-
this.locationResources.addAll(locations);
163+
for (Resource location : locations) {
164+
ResourceHandlerUtils.assertResourceLocation(location);
165+
this.locationResources.add(location);
166+
}
164167
}
165168
}
166169

@@ -376,6 +379,7 @@ private void resolveResourceLocations() {
376379
Assert.isTrue(CollectionUtils.isEmpty(this.locationResources), "Please set " +
377380
"either Resource-based \"locations\" or String-based \"locationValues\", but not both.");
378381
for (String location : this.locationValues) {
382+
ResourceHandlerUtils.assertLocationPath(location);
379383
result.add(this.resourceLoader.getResource(location));
380384
}
381385
}

Diff for: spring-webflux/src/test/java/org/springframework/web/reactive/config/DelegatingWebFluxConfigurationTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ void resourceHandlerMapping() {
124124
delegatingConfig.setConfigurers(Collections.singletonList(webFluxConfigurer));
125125
willAnswer(invocation -> {
126126
ResourceHandlerRegistry registry = invocation.getArgument(0);
127-
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static");
127+
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
128128
return null;
129129
}).given(webFluxConfigurer).addResourceHandlers(any(ResourceHandlerRegistry.class));
130130

Diff for: spring-webmvc/src/main/java/org/springframework/web/servlet/function/PathResourceLookupFunction.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class PathResourceLookupFunction implements Function<ServerRequest, Optional<Res
4747

4848
public PathResourceLookupFunction(String pattern, Resource location) {
4949
Assert.hasLength(pattern, "'pattern' must not be empty");
50-
Assert.notNull(location, "'location' must not be null");
50+
ResourceHandlerUtils.assertResourceLocation(location);
5151
this.pattern = PathPatternParser.defaultInstance.parse(pattern);
5252
this.location = location;
5353
}

Diff for: spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHandlerUtils.java

+38
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.springframework.core.io.Resource;
2828
import org.springframework.core.io.UrlResource;
2929
import org.springframework.core.log.LogFormatUtils;
30+
import org.springframework.lang.Nullable;
31+
import org.springframework.util.Assert;
3032
import org.springframework.util.ResourceUtils;
3133
import org.springframework.util.StringUtils;
3234
import org.springframework.web.context.support.ServletContextResource;
@@ -42,6 +44,42 @@ public abstract class ResourceHandlerUtils {
4244

4345
private static final Log logger = LogFactory.getLog(ResourceHandlerUtils.class);
4446

47+
private static final String FOLDER_SEPARATOR = "/";
48+
49+
private static final String WINDOWS_FOLDER_SEPARATOR = "\\";
50+
51+
52+
/**
53+
* Assert the given location is not null, and its path ends on slash.
54+
*/
55+
public static void assertResourceLocation(@Nullable Resource location) {
56+
Assert.notNull(location, "Resource location must not be null");
57+
try {
58+
String path;
59+
if (location instanceof UrlResource) {
60+
path = location.getURL().toExternalForm();
61+
}
62+
else if (location instanceof ClassPathResource classPathResource) {
63+
path = classPathResource.getPath();
64+
}
65+
else {
66+
path = location.getURL().getPath();
67+
}
68+
assertLocationPath(path);
69+
}
70+
catch (IOException ex) {
71+
// ignore
72+
}
73+
}
74+
75+
/**
76+
* Assert the given location path is a directory and ends on slash.
77+
*/
78+
public static void assertLocationPath(@Nullable String path) {
79+
Assert.notNull(path, "Resource location path must not be null");
80+
Assert.isTrue(path.endsWith(FOLDER_SEPARATOR) || path.endsWith(WINDOWS_FOLDER_SEPARATOR),
81+
"Resource location does not end with slash: " + path);
82+
}
4583

4684
/**
4785
* Normalize the given resource path replacing the following:

Diff for: spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,10 @@ public void setLocationValues(List<String> locations) {
180180
public void setLocations(List<Resource> locations) {
181181
Assert.notNull(locations, "Locations list must not be null");
182182
this.locationResources.clear();
183-
this.locationResources.addAll(locations);
183+
for (Resource location : locations) {
184+
ResourceHandlerUtils.assertResourceLocation(location);
185+
this.locationResources.add(location);
186+
}
184187
}
185188

186189
/**
@@ -493,6 +496,7 @@ private void resolveResourceLocations() {
493496
charset = Charset.forName(value);
494497
location = location.substring(endIndex + 1);
495498
}
499+
ResourceHandlerUtils.assertLocationPath(location);
496500
Resource resource = applicationContext.getResource(location);
497501
if (location.equals("/") && !(resource instanceof ServletContextResource)) {
498502
throw new IllegalStateException(

Diff for: spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistryTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ void resourceChainWithOverrides() {
204204

205205
@Test
206206
void urlResourceWithCharset() {
207-
this.registration.addResourceLocations("[charset=ISO-8859-1]file:///tmp");
207+
this.registration.addResourceLocations("[charset=ISO-8859-1]file:///tmp/");
208208
this.registration.resourceChain(true);
209209

210210
ResourceHttpRequestHandler handler = getHandler("/resources/**");

Diff for: spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ public void configureViewResolvers(ViewResolverRegistry registry) {
457457

458458
@Override
459459
public void addResourceHandlers(ResourceHandlerRegistry registry) {
460-
registry.addResourceHandler("/resources/**").addResourceLocations("src/test/java");
460+
registry.addResourceHandler("/resources/**").addResourceLocations("src/test/java/");
461461
}
462462

463463
@Override

Diff for: spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-resources-chain.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
2525
<property name="properties">
26-
<value>location=file:///tmp</value>
26+
<value>location=file:///tmp/</value>
2727
</property>
2828
</bean>
2929

0 commit comments

Comments
 (0)