Skip to content

Commit

Permalink
Add efficient existence check to ClassPathResource.isReadable()
Browse files Browse the repository at this point in the history
Includes reduced isReadable() check in PathResourceLookupFunction, aligned with PathResourceResolver.

Closes gh-27538
See gh-21372
  • Loading branch information
jhoeller committed Oct 12, 2021
1 parent 6d4dfed commit 3a166ea
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 14 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 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.
Expand Down Expand Up @@ -88,7 +88,15 @@ else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
@Override
public boolean isReadable() {
try {
URL url = getURL();
return checkReadable(getURL());
}
catch (IOException ex) {
return false;
}
}

boolean checkReadable(URL url) {
try {
if (ResourceUtils.isFileURL(url)) {
// Proceed with file system resolution
File file = getFile();
Expand Down
Expand Up @@ -142,6 +142,18 @@ public boolean exists() {
return (resolveURL() != null);
}

/**
* This implementation checks for the resolution of a resource URL upfront,
* then proceeding with {@link AbstractFileResolvingResource}'s length check.
* @see java.lang.ClassLoader#getResource(String)
* @see java.lang.Class#getResource(String)
*/
@Override
public boolean isReadable() {
URL url = resolveURL();
return (url != null && checkReadable(url));
}

/**
* Resolves a URL for the underlying class path resource.
* @return the resolved URL, or {@code null} if not resolvable
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
Expand Down Expand Up @@ -72,7 +72,7 @@ public Mono<Resource> apply(ServerRequest request) {

try {
Resource resource = this.location.createRelative(path);
if (resource.exists() && resource.isReadable() && isResourceUnderLocation(resource)) {
if (resource.isReadable() && isResourceUnderLocation(resource)) {
return Mono.just(resource);
}
else {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
Expand Down Expand Up @@ -71,7 +71,7 @@ public Optional<Resource> apply(ServerRequest request) {

try {
Resource resource = this.location.createRelative(path);
if (resource.exists() && resource.isReadable() && isResourceUnderLocation(resource)) {
if (resource.isReadable() && isResourceUnderLocation(resource)) {
return Optional.of(resource);
}
else {
Expand Down Expand Up @@ -110,10 +110,7 @@ private boolean isInvalidPath(String path) {
return true;
}
}
if (path.contains("..") && StringUtils.cleanPath(path).contains("../")) {
return true;
}
return false;
return path.contains("..") && StringUtils.cleanPath(path).contains("../");
}

private boolean isResourceUnderLocation(Resource resource) throws IOException {
Expand Down Expand Up @@ -144,10 +141,8 @@ else if (resource instanceof ClassPathResource) {
if (!resourcePath.startsWith(locationPath)) {
return false;
}
if (resourcePath.contains("%") && StringUtils.uriDecode(resourcePath, StandardCharsets.UTF_8).contains("../")) {
return false;
}
return true;
return !resourcePath.contains("%") ||
!StringUtils.uriDecode(resourcePath, StandardCharsets.UTF_8).contains("../");
}


Expand Down

0 comments on commit 3a166ea

Please sign in to comment.