Bug 63964

Summary: Null returned when opening resource URL stream
Product: Tomcat 9 Reporter: Ján Michalica <jan.michalica>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Severity: major    
Priority: P2    
Version: 9.0.29   
Target Milestone: -----   
Hardware: PC   
OS: All   
Attachments: Sample project to reproduce the issue

Description Ján Michalica 2019-11-26 13:43:47 UTC
Created attachment 36902 [details]
Sample project to reproduce the issue

When opening web app resource's URL for reading, null is returned if the URL was obtained in a specific way.
See attached sample project:

URL dir = servletContext.getResource("/WEB-INF/dir/");
URL file = new URL(dir, "file");
InputStream in = file.openStream(); // null returned even if the "/WEB-INF/dir/file" exists.

The issue seems to be in CachedResourceURLStreamHandler, where opening the URLConnection ignores provided URL:

protected URLConnection openConnection(URL u) throws IOException {
    return new CachedResourceURLConnection(resourceURL, root, webAppPath, usesClassLoaderResources);

The "resourceUrl" points to the parent directory, so null is answered as the input stream.
Comment 1 Remy Maucherat 2019-11-26 15:10:41 UTC
Given this and other posts in the user list, I think there's an issue with the URL resolution that was added.

Trying to have a full implementation may lead up to the Tomcat 7 resources complexity it seems (except without JNDI and the custom protocol, but this strategy had its own benefits if you want a full implementation that worked in all cases), because next time we'll have someone asking "oh and if I do servletContext.getResource("/WEB-INF/dir/").toString() + "/myPath" I have an inconsistent result", which is basically what people spent months spamming me about during the Tomcat 5 days. Maybe the URL stream handler should be reverted and the JSP recompilation "issue" (a 100% brain dead use case) and other similar possible inconsistencies should be documented as wontfix instead of venturing again into that nest of spiders.
Comment 2 Mark Thomas 2019-11-26 16:33:57 UTC
Just to join up the dots as I suspect we'll be pointing lots of folks to this bug.

The currently suspect commits are (9.0.x, 8.5.x. has similar commits):

These were intended to address this bug from the users list:

I share Rémy's lack of enthusiasm for a full 7.0.x style solution to this but I do want to look to see if there is a way to make the current solution sufficiently robust rather than revert the fix.
Comment 3 Mark Thomas 2019-11-26 18:54:21 UTC
Fixed in:
- master for 9.0.30 onwards
- 8.5.x for 8.5.50 onwards

7.0.x was not affected.

Generally, the solution I am aiming for is not as comprehensive as the 7.0.x custom handler solution. The intention is if you use a URL obtained from WebResourceRoot then what you see will always be consistent (i.e. if will use the cache if present). If you obtain a URL directly or manipulate a URL obtained from WebResoureRoot you are accessing the resource directly, bypassing the cache and may see inconsistent results.