Removing Tomcat context from URLs for a virtual host (mod_jk, mod_rewrite)

17,823

Solution 1

@Josh, I think this solution won't work if tomcat performs any redirects. This is the typical case for example in an application demanding a login. When the user is not authenticated the app will redirect to something like /login however tomcat will append the current context like in /context/login so at the end the context does show in the URL.

As you mentioned in your other question/response using just mod-jk plus tomcat virtual hosts is an option but there you will need to deploy your applications as ROOT.war which might not be that straightforward. There is a workaround so your application can be just dropped into tomcat webapps folder but as I described here the server will deploy the app at least twice.

It would be great if RewriteRule[P] plus JkOptions +ForwardURICompat could work but it doesn't. BTW I have tested this and I know mod_proxy does work as I proxied my site to cnn.com and I got their page under my site URL. Below are the logs BTW for the requests where you can see a proxy is being used:

127.0.0.1 - - [15/Dec/2011:12:56:34 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/
127.0.0.1 - - [15/Dec/2011:12:56:34 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/ [OK]
127.0.0.1 - - [15/Dec/2011:12:56:49 --0500] [localhost/sid#1008ef278][rid#1009aaca8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/login
127.0.0.1 - - [15/Dec/2011:12:56:49 --0500] [localhost/sid#1008ef278][rid#1009aaca8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/login [OK]
127.0.0.1 - - [15/Dec/2011:12:57:15 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/j_spring_security_check
127.0.0.1 - - [15/Dec/2011:12:57:15 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/j_spring_security_check [OK]
127.0.0.1 - - [15/Dec/2011:13:08:41 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/
127.0.0.1 - - [15/Dec/2011:13:08:41 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/ [OK]

Solution 2

I've been using this with great success:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/(Context/.*)$
RewriteRule ^/(.*)$ /Context/$1 [P,L]

Notes on your situation:

  • You will need to get mod_proxy working or the [P] will be ignored and the request will be forwarded instead of proxied. There is no way around this.
  • +ForwardURICompat is part of mod_jk and will take effect after the rewriting.
  • mod_jk is ignoring the request because it never gets there. You need a RewriteCond (above) to prevent requests to /Context from being rewritten.

I'm currently looking for a way to do this without mod_rewrite and using, instead, just mod_jk and Tomcat <Host>'s. But I'm having trouble with apache, mod_jk and Tomcat hosts playing nicely together. The above should work fine for you.

Solution 3

I'll leave my original answer up but it is wrong. The proper way to do this would be with a Tomcat VirtualHost:

http://tomcat.apache.org/tomcat-6.0-doc/virtual-hosting-howto.html

The official walk-through in the link above is exactly what I've used several times now. I won't attempt to boil it down here.

The concept is the same as an Apache Vhost. Create a virtual host (eg. for something.yourtdomain.com) and deploy your webapp to the ROOT application (/) for that vhost and you're all set. This way, if you already have a ROOT webapp, you can have another at a different domain and the prior will remain unaffected.

As Nestor mentioned, an Apache rewrite rule will not handle things like tag libs and frameworks that automatically create links/form actions/etc for you based on the context root. In this case they will create the correct context root (/).

Share:
17,823
Richard H
Author by

Richard H

Updated on June 13, 2022

Comments

  • Richard H
    Richard H almost 2 years

    I have a single Tomcat instance containing a number of webapps, each accessible via it's /Context. Tomcat is behind httpd (actually Debian Apache2), configured with virtual hosts to serve each app/Context. Tomcat connectivity is with mod_jk.

    This works fine when I don't care about removing the context from urls: when the root of a virtual domain is requested, the requested is redirected to domain.com/Context.

    However for one app I do want to remove the context. I believe this can be done by using mod_rewrite, and passing the re-written url to mod_jk for passing on to the correct Tomcat context. So my Debian Apache2 sites-available file looks like this:

    NameVirtualHost *
    
    <VirtualHost *>
        ServerName domain.be
    
        DocumentRoot /home/webapp/app/static/domain/
    
        RewriteEngine on
        RewriteRule ^/(.*)$ /Context/$1 [L,PT]
        RewriteLog "/var/log/apache2/domain-rewrite.log"
        RewriteLogLevel 4
    
        JkLogFile     /var/log/apache2/domain-mod_jk.log
        JkLogLevel    debug
        JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
        JkMount /Context w1
        JKMount /Context* w1
        JkOptions +ForwardURICompat
    
        ErrorLog /var/log/apache2/domain_error.log
        CustomLog /var/log/apache2/domain_access.log combined
        LogLevel warn
    
    </VirtualHost>
    

    According to the docs, the [PT] flag and +ForwardURICompat options should result in the rewritten URL being passed to jk_mod. However that doesn't seem to be happening.

    The URL is being re-written, but it seems as if mod_jk is ignoring it: A request for domain.be/Context for example gets rewritten as /Context/Context - but is still handed to mod_jk as /Context.

    Any ideas? Incidentally, I cannot use mod_proxy at the moment.

    Thanks

  • Josh Johnson
    Josh Johnson almost 12 years
    You are correct that my original solution is not the best way and fraught with peril. But since posting that, I have used Tomcat VirtualHosts with much success. Despite not hearing about people using it much, it is definitely what one would want to use in this situation and not at all hard after creating one.
  • skel625
    skel625 over 11 years
    In case you were not aware, you can actually leave your applications within the webapps directory and just set the appBase to the full path of the application. --- Example: <Host name="www.app1.com" appBase="C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\app1"> <Context path="" docBase="." /> </Host>
  • user207421
    user207421 over 11 years
    That still won't work if Tomcat performs any redirects. It doesn't actually change the fundamental problem at all. Not an answer.