Tomcat – Obscuring tomcat context path in URL

apache-2.2mod-jkmod-proxymod-rewritetomcat

I've setup an Apache reverse proxy to Tomcat that is working, in that I can load my url and get connection to the Tomcat backend. What I'm attempting to do now is rewrite the URL that a user sees in their browser. Here's my code –

LoadModule      proxy_html_module       modules/mod_proxy_html.so
LoadModule  proxy_ajp_module    modules/mod_proxy_ajp.so

# DON'T TURN ProxyRequests ON!  Bad things will happen
ProxyRequests off

# Enabling mod_proxy_html
ProxyHTMLEnable On
ProxyHTMLLogVerbose On
LogLevel Debug

SSLProxyEngine on

# Setup mod_proxy_ajp load balancer to the 2 happ hosts
<Proxy balancer://happcluster>
BalancerMember ajp://happ01.domain.com:8009 loadfactor=1
BalancerMember ajp://happ02.domain.com:8009 loadfactor=1
ProxySet lbmethod=bytraffic
ProxySet stickysession=JSESSIONID
</Proxy>

# rewrite setup

RewriteEngine   On
RewriteLog      /var/log/httpd/rewrite_log
RewriteLogLevel        8

RewriteCond     %{HTTP_HOST} !^www.* [NC]
RewriteCond     %{HTTP_HOST} ^app\.domain\.com$ [NC]
RewriteCond     %{REQUEST_URI} !^/app1/.*$
RewriteCond     %{REQUEST_URI} !^.*\.ico$ [NC]
RewriteRule     ^(/.*) balancer://happcluster/app$1 [P]

# Necessary to have mod_proxy_html do the rewriting
RequestHeader      unset  Accept-Encoding

# Be prepared to rewrite the HTML/CSS files as they come back
# from Tomcat
SetOutputFilter proxy-html
SetOutputFilter INFLATE;DEFLATE

# Rewrite JavaScript and CSS files in addition to HTML files
ProxyHTMLExtended On

# Output Strict XHTML (add "Legacy" to the end of the line below
# to output Transitional XHTML)
ProxyHTMLDoctype XHTML

# Rewrite HTTP headers and HTML/CSS links for everything else
ProxyPassReverse /app1/ /
ProxyPassReverseCookiePath /app1/ /
ProxyHTMLURLMap /app1/ /

What happens though is that when I type http://app.domain.com into a browser, the URL is re-written to http://app.domain.com/app1/…..

I'm using mod_proxy_ajp to load balance requests to 2 back-end tomcat servers and this appears to be working.

Any ideas?

EDIT

Here's a snippet of my rewrite log that shows the proxy to the backend –

[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d73c0/initial] (2) init rewrite engine with requested uri /
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d73c0/initial] (3) applying pattern '^(/.*)' to uri '/'
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d73c0/initial] (4) RewriteCond: input='app.domain.com' pattern='!^www.*' [NC] => matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d73c0/initial] (4) RewriteCond: input='app.domain.com' pattern='^app\.domain\.com$' [NC] => matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d73c0/initial] (4) RewriteCond: input='/' pattern='!^/app1/.*$' => matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d73c0/initial] (4) RewriteCond: input='/' pattern='!^.*\.ico$' [NC] => matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d73c0/initial] (2) rewrite '/' -> 'balancer://happcluster/app1/'
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d73c0/initial] (2) forcing proxy-throughput with balancer://happcluster/app1/
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d73c0/initial] (1) go-ahead with proxy request proxy:balancer://happcluster/app1/ [OK]
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (2) init rewrite engine with requested uri /app1/login.jsp;jsessionid=F6D9765F6A737DB373D9C3AA60211B68.worker1
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (3) applying pattern '^(/.*)' to uri '/app1/login.jsp;jsessionid=F6D9765F6A737DB373D9C3AA60211B68.worker1'
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (4) RewriteCond: input='app.domain.com' pattern='!^www.*' [NC] => matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (4) RewriteCond: input='app.domain.com' pattern='^app\.domain\.com$' [NC] => matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (4) RewriteCond: input='/app1/login.jsp;jsessionid=F6D9765F6A737DB373D9C3AA60211B68.worker1' pattern='!^/app1/.*$' => not-matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (3) applying pattern '^(/.*)' to uri '/app1/login.jsp;jsessionid=F6D9765F6A737DB373D9C3AA60211B68.worker1'
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (4) RewriteCond: input='app.domain.com' pattern='!^www.*' [NC] => matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (4) RewriteCond: input='app.domain.com' pattern='^app\.domain\.com$' [NC] => matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (4) RewriteCond: input='/app1/login.jsp;jsessionid=F6D9765F6A737DB373D9C3AA60211B68.worker1' pattern='!^/app1/.*$' => not-matched
[app.domain.com/sid#2b0c5d2d4ef0][rid#2b0c5d0d53b0/initial] (1) pass through /app1/login.jsp;jsessionid=F6D9765F6A737DB373D9C3AA60211B68.worker1

And a snippet from my access_log –

"GET /app1/login.jsp HTTP/1.1" 200 607
"GET / HTTP/1.1" 302 -
"GET /app1/login.jsp;jsessionid=F6D9765F6A737DB373D9C3AA60211B68.worker1 HTTP/1.1" 200 607

Best Answer

This sort of thing is doomed to failure, as Tomcat will also embed self-relative URLs in the HTML it produces. There is a third party module to fix that as well, but even the use of rewrite rules is generally a sign that you're doing the wrong thing. The only technique that really works is to use the same URL at both Apache and Tomcat. In this case, just find out what the Tomcat context URLs are, and ProxyPass them all.

I agree with Shane Madden that you should look into mod_proxy_ajp rather than mod_jk. It is miles easier to configure, does exactly the same thing, and is part of Apache, not a separate piece.