2022-05-13

Tomcat RewriteValve usage

(An occasional technical note for future self, and others)

Suppose you have a Tomcat based servlet container with webapps directory name "ORIGINAL", and then you have a reason to rename it as "MOVED":

  • /ORIGINAL/servlet/path
  • /MOVED/servlet/path

You have a few ways to handle this, but simplest turned out to be rewriting the HTTP URL path in front-end of the server.  (Assuming you have at least Tomcat 8.5)

The Tomcat servlet container software has a tool for rewriting request URL paths in same style rules as Apache HTTPD does them.  This mechanism is called "RewriteValve".

Simplest way to achieve this is to create a ROOT webapp - create following directory and file structure inside your Tomcat webapps.  The "ROOT" name in all uppercase is special allowing this mapping to affect full HTTP URL path, instead of only inside a given servlet.

  • server/webapps/ROOT/
  • server/webapps/ROOT/META-INF/context.xml
  • server/webapps/ROOT/WEB-INF/rewrite.config
The context.xml contains following:

<?xml version="1.0" encoding="UTF-8"?>
<!-- This goes to /META-INF/context.xml -->
<Context reloadable="false"
         swallowOutput="true"
         unpackWAR="false"
         processTlds="false">

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

And the rewrite.config  define URL mappings:

##
## This runs in ROOT context path 
##    (  = "/" ) of the URL
## 

RewriteCond  %{REQUEST_PATH}  ^/ORIGINAL/.*
RewriteRule ^/ORIGINAL/(.*)$  /MOVED/$1 [L,NE]


The mechanism has complicated capability for mapping and regular expression rewriting of the URL paths. Those are simpler thing to master once you get the configuration in place.


What happens if you try to do this in your webapp that is not named "ROOT"?  The rewrite works, but receives only paths with the webapp path prefix removed, and rewriting will not be able to direct the caller to other webapp context.

What you can use this for includes:
  • Aliasing web service URL paths (give service without reporting redirect)
  • Moving web service URL paths (report a redirect to the caller)
  • "Fixing" an URL bug in popular 3rd party client library
  • Creating URL compatibility mappings against older version of the service, or different implementations

In theory this rewritter should also work in server.xml in <Host> context, but it is easier to create special "ROOT" webapp, or use it inside your webapp's directory structure without rewriting the "WEBAPP" of "server/webapps/WEBAPP/" directory.


Hint: If you are uncertain regarding the configuration file being read, you can put there a line starting with unknown keyword ( like "break-it" ), then your Tomcat will not restart, and it will hopefully mutter some error. Now you will see evidence that the configuration file is being read - it is in correct location.

Hint: Use of logging.properties  works better if you do not have   swallowOutput="true"  in any of your context.xml  files defining the <Context ..> elements.