Bug 64593 - Rewrites incorrectly 404 when there is no source context
Summary: Rewrites incorrectly 404 when there is no source context
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 8.5.57
Hardware: PC All
: P2 normal (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
Depends on:
Reported: 2020-07-10 18:30 UTC by Nic Doye
Modified: 2020-07-13 16:36 UTC (History)
0 users


Note You need to log in before you can comment on or make changes to this bug.
Description Nic Doye 2020-07-10 18:30:48 UTC
If you enable rewrites, and put a rewrite.config in, where the source
location does not match a valid context, the server issues a 404. The
server then logs a 404 in the access log for the target location.

I would argue that the server should perform the rewrite and return the target's content. However, if that is not what is meant to happen, then
the logged 404 should be for the source URL, not the target.

In "Bonus Step 8." below, you can see that the server _thinks_ the rewrite rule is present and that it has rewritten the request.

Step 1. Enable Rewrite valve via

<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />

Step 2. Add a rewrite.config to conf/Catalina/localhost containing:

RewriteRule ^/source/(.*)$ /target/$1 [L]

Step 3. Delete all webapps

rm -rf webapps/*

Step 4. Create webapps/target/index.html

Step 5. Start server

Step 6. Test Rewrite

curl -I http://localhost:8080/source/index.html
HTTP/1.1 404

Step 7. Observe rewritten path in logs:

0:0:0:0:0:0:0:1 - - [10/Jul/2020:18:44:06 +0100] "HEAD /target/index.html HTTP/1.1" 404 -

Bonus Step 8. Enable FINE logging, and we get the following lines:

10-Jul-2020 19:27:36.803 FINE [Catalina-startStop-1] org.apache.catalina.valves.rewrite.RewriteValve.parse Add rule with pattern ^/source/(.*)$ and substitution /target/$1

org.apache.catalina.valves.rewrite.RewriteValve.invoke Rewrote /source/index.html as /target/index.html with rule pattern ^/source/(.*)$
Comment 1 Mark Thomas 2020-07-13 10:28:18 UTC
I am able to reproduce this using the steps provided. Thank you for providing a simple test case for this issue. It saves a considerable amount of time.

I'll note at this point that creating webapps/ROOT is sufficient to resolve the issue. Generally, running without a ROOT web application is not recommended. However, unless the fix complex, I still think this should be fixed.
Comment 2 Remy Maucherat 2020-07-13 10:33:56 UTC
Yes, Catalina never likes unmapped requests, it's kind of a lost cause and an empty "ROOT" folder will usually solve all the problems at no cost.

Mark, I can look at this issue if you don't have time [I was planning to try later today].
Comment 3 Mark Thomas 2020-07-13 11:05:02 UTC
Thanks for the offer. I've tracked down the root cause. The missing ROOT context puts the response into the error state which then doesn't get cleared in the RewriteValve. What I haven't figured out is the best way to handle this. Suggestions welcome.
Comment 4 Remy Maucherat 2020-07-13 14:30:14 UTC
It could be possible to remove the sendError(404) here:
And move it to StandardHostValve (if request.getContext() == null) and StandardEngineValve (if request.getHost() == null).
Comment 5 Mark Thomas 2020-07-13 15:08:39 UTC
I think that could be a better option that the one I was looking at. Undoing the effects of calling sendError() gets messy rather quickly. I'll experiment.
Comment 6 Remy Maucherat 2020-07-13 15:20:00 UTC
(In reply to Mark Thomas from comment #5)
> I think that could be a better option that the one I was looking at. Undoing
> the effects of calling sendError() gets messy rather quickly. I'll
> experiment.

I agree reverting the error is a problem, since it could be set for another legitimate reason (although since there is also context == null this is less likely).
Comment 7 Mark Thomas 2020-07-13 16:36:53 UTC
I've fixed this using Rémy's suggested fix. I also back-ported the fix for bug 53411 to 8.5.x.

Fixed in:
- master for 10.0.0-M8 onwards
- 9.0.x for 9.0.38 onwards
- 8.5.x for 8.5.58 onwards

7.0.x is not affected.