Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot serve static resources with spaces from "file:" location when using PathPattern and UrlPathHelper is set to not decode #27791

Closed
aaguilera opened this issue Dec 9, 2021 · 4 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Milestone

Comments

@aaguilera
Copy link
Contributor

Description

After upgrading from Spring Boot 2.5.6 to 2.6.1, I've detected a behaviour change affecting access to static files with "special chars" in file names(spaces, accents, etc.)

I believe this is related to the change from AntPathMatcher to PathPattern introduced in Spring Boot 2.6.0-M3.

When I try to serve static files from a custom location from my filesystem (outside the default static paths configured by Spring Boot), I can not access files with spaces (or accents) in file names.

I've prepared a sample project to demonstrate this behavior. My only customization is adding a new resource handler to be able to access static files under the /tmp/repo directory:

@Configuration
public class MyCustomConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/repo/**").addResourceLocations("file:/tmp/repo/");
    }
}

Steps to reproduce

git clone https://github.com/aaguilera/test-static-files.git   
cd test-static-files
cp -r src/main/resources/static /tmp/repo    # copy sample files to external directory
./mvnw spring-boot:run

Once the app is running, try to access the static file foo bar.txt under resources/static and /tmp/repo:

http://localhost:8080/foo%20bar.txt (this works fine)
http://localhost:8080/repo/foo%20bar.txt (this returns error 404)

The only difference is that the first URL is getting a file located at src/main/resources/static/ (this directory is preconfigured by default via Spring Boot to serve static files), and the second URL is trying to get a file located at file:/tmp/repo, configured manually via my @configuration class using addResourcehandler/addResouceLocations.

The interesting thing is that this second URL works perfectly (returns the file) when using Spring Boot 2.5.7 instead of 2.6.1 (you can try changing the version in pom.xml and restarting the app).

Workaround

As a workaround, I can force the old behavior by setting the following property in my application.properties:

spring.mvc.pathmatch.matching-strategy=ant-path-matcher

With this configuration, the second URL works fine again, as it did with Spring Boot 2.5.x.

@wilkinsona
Copy link
Member

Thanks for the report and sample application, I've reproduced the problem. As far as I can tell, this appears to be a bug in Spring Framework. In the case where it works, foo%20bar.txt becomes foo bar.txt and the file is found. In the case were it does not work, foo%20bar.txt comes foo%2520.txt and the file is not found. This decoding or encoding is performed in PathResourceResolver's encodeOrDecodeIfNecessary method.

Could you please take a look, @bclozel?

@aaguilera
Copy link
Contributor Author

Also please note this bug affects not only files with spaces in the name, but files with non-ASCII characters such as foó.txt, etc.

@bclozel
Copy link
Member

bclozel commented May 17, 2022

This almost look like a duplicate of #26775. While this case is in theory covered by ResourceHttpRequestHandlerIntegrationTests in that issue, it looks like a typical Spring Boot setup is a bit different. Spring Boot configures a UrlPathHelper with the urlDecode option with its default value, true. This has been done for optimization purposes in spring-projects/spring-boot#21499.

I think that this last bit is incorrect - in the case of a Spring MVC application using the PathPatternParser matching strategy, Spring Boot should ensure that the configured UrlPathHelper has the urlDecode option set to false: the matching strategy does not decode the path for us beforehand and there is no need to re-encode it for resolving URL resources.

@rstoyanchev do you think this analysis is right? If so, I'm going to move this issue back to Spring Boot update the UrlPathHelper.

@rstoyanchev
Copy link
Contributor

The settings of UrlPathHelper shouldn't matter. It is mutually exclusive with PathPatternParser.

I think I can see the issue in PathResourceResolver where need to differentiate between UrlResource and other resource types and check whether the URL path was decoded or not. For the latter we need to consider whether PathPatternParser is in use in which case the path is encoded. #26775 as a fix along the same lines in shouldDecodeRelativePath but we need the same in shouldEncodeRelativePath as well.

I'll experiment with a test and a fix.

@rstoyanchev rstoyanchev self-assigned this May 23, 2022
@rstoyanchev rstoyanchev added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels May 23, 2022
@rstoyanchev rstoyanchev added this to the 5.3.21 milestone May 23, 2022
@rstoyanchev rstoyanchev changed the title Behavior change serving static files after migration from AntPathMatcher to PathPattern Cannot serve static resources with spaces from "file:" location when using PathPattern and UrlPathHelper is set to not decode May 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants