adding a global URI prefix for Tomcat web apps

13,783

For the benefit of others, I'll answer my own question. Actually, Tomcat (since version 6) provides a quite easy solution for adding URI prefixes to webapps, by prefixing the webapp folder or WAR file name with that prefix (or those prefixes), separated by a hash. So, e.g.:

${catalina.base}/webapps/apps#my_app
${catalina.base}/webapps/apps#my_app2.war

...would make both accessible via http://localhost:8082/apps/my_app/ and http://localhost:8080/apps/my_app2/, respectively, without any further configuration in ${catalina.base}/conf/server.xml.

It is explained somewhat cryptically in the Tomcat Context Container reference, but see this kind message on the Tomcat-users mailing list helped me a lot.

Unfortunately, there's a catch: apparently, Cocoon (up to 2.1.11, haven't tested with 2.2 apps) chokes on webapps whose paths contain a hash (see https://issues.apache.org/jira/browse/COCOON-2270).

Yet, there is a workaround for those Cocoon-based webapps, as shown in following configuration steps:

  1. move the folder or WAR file containing the webapp outside of the host's appBase path, e.g.: F:\cocoonApps\my_CocoonApp
  2. add a file ${catalina.base}\conf\Catalina[host name][prefix]#[app name].xml, e.g.: ${catalina.base}\conf\Catalina\localhost\apps#my_CocoonApp.xml, with following content:

    <Context docBase="F:/cocoonApps/my_CocoonApp"/>

Using this workaround, even Cocoon webapps are happy when accessed at e.g. http://localhost:8082/apps/my_CocoonApp/. This could allow for quite flexible managment overhead of Tomcat webapps:

  • non-Cocoon-based webapps: just add them in the Host's appBase, prefixing the name of the folder or WAR file with the desired prefix(es), separated with a hash (#). Adding new non-Cocoon webapps requires no further steps than storing them with the desired URI prefix.
  • Cocoon-based webapps: store them outside of the Host's appBase, with just the unprefixed webapp name. Additionally, add a context file for each Cocoon-based webapp, specifying the of the webapp as explained above. This additional step then is only needed for Cocoon-based webapps.

With the Apache proxy settings explained in my original question, this makes it possible to flexibly add Tomcat apps and have them reverse proxied behind Apache using the /apps/ URI prefix.

Share:
13,783

Related videos on Youtube

rvdb
Author by

rvdb

Updated on September 18, 2022

Comments

  • rvdb
    rvdb over 1 year

    I am setting up a reverse proxy configuration where all requests whose path starts with '/apps/' should be proxied by Apache to Tomcat. This IMO has 2 benefits: it makes it possible to reserve proxying to only the '/apps/' part of the URI space, and to use only a single proxy rule for all Tomcat apps (i.e. requests for any Tomcat app should just start with '/apps/').

    For example, requests for http://mydomain/apps/my_app/ should be proxied to http://localhost:8082/my_app/. Note the absence of the '/apps/' prefix in the Tomcat URI: 'my_app' lives in the regular location at ${CATALINA_HOME}/webapps/my_app.

    I have achieved this using following Proxy rules in an Apache vhost.conf file:

    ProxyPreserveHost    on
    ProxyPass            /apps/    http://localhost:8082/
    ProxyPassReverse    /apps/    http://mydomain/
    

    (Note: I have used ProxyPreserveHost since my Tomcat app needs access to the original host to generate further links). All goes well, except for absolute links that are generated by one part of my Tomcat app. Given above configuration, my Tomcat app will 'see' this request: http://mydomain/my_app, and hence generate links without the '/apps/' prefix that should trigger proxying for those links.

    It took me some time, but I understand now that this is essential characteristic of proxying, and that there's no 'standard' way to pass on that '/apps/' prefix of the original request to the proxied app. Hence, I started to investigate another possibility, namely defining a global prefix for all Tomcat apps, and proxy the Tomcat apps with following settings:

    ProxyPreserveHost    on
    ProxyPass            /apps/    http://localhost:8082/apps/
    ProxyPassReverse    /apps/    http://mydomain/apps/
    

    This would proxy requests for http://mydomain/apps/my_app/ to http://localhost:8082/apps/my_app/. Since all apps on the Tomcat server will be accessed behind a proxy, I have no problem that this '/apps/' prefix will be required for all Tomcat apps.

    So far, so good. Yet, I am struggling with the Tomcat side of this approach: finding a way to add a global path prefix for requests to Tomcat apps. The closest I got was this: 1. don't touch the physical location of the Tomcat apps: leave them at ${CATALINA.HOME}/webapps 2. change ${CATALINA.HOME}/conf/server.xml as follows:

    <Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="false" deployOnStartup="false">
      <Context path="/apps/my_app" docBase="/my_app/" reloadable="true"/>
    </Host>
    

    While this makes the my_app Tomcat app accessible at http://localhost:8082/apps/my_app/, it also suggests that all Tomcat apps should be defined manually in a separate element. This makes it less flexible to add new Tomcat web apps (and would actually mean more configuration work than declaring separate proxy rules for each app in the Apache configuration, without the '/apps/' prefix). I tried this:

    <Context path="/apps" docBase="/" reloadable="true"/>
    

    (and @docBase variants such as "", or "."), but this doesn't work: no indication of any webapps being deployed in the Tomcat console output, and all requests return a 404 error.

    Hence my question: is there a simple(r) way of 'declaring' a global URI prefix for Tomcat webapps?

    Any advice much appreciated!

    Ron