3

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
  • 1
    Since you only have one app that can be hosted at the root path, why not just host it on the ROOT context? – Andrew M. Jul 13 '12 at 17:09
  • I don't have control over the where the tomcat app is deployed and the end goal is to serve multiple tomcat apps from a single host. – Matthew Schmitt Jul 13 '12 at 22:35
  • Do you need to use mod_ajp? – Shane Madden Jul 14 '12 at 21:43
  • @ShaneMadden - I've switched it up to mod_proxy_ajp with the same results. I edited my post to indicate the change. Thanks for any assistance. – Matthew Schmitt Jul 17 '12 at 21:56
  • @MatthewSchmitt Can you clarify what behavior you're seeing? Is the client getting a `30x` response code? Or is it just that the URLs in HTML content include the `/app/` path? – Shane Madden Jul 18 '12 at 02:01
  • @ShaneMadden - It's just that the URL includes the /app/ path, both in HTML content and the browser. If I could deploy the war at the root, I would. But our developers wish the ability to deploy any number of Tomcat webapps at any context path and then have apache rewrite and obscure the context path. – Matthew Schmitt Jul 18 '12 at 03:14
  • @MatthewSchmitt Right, but is the browser actually getting a redirection response, or are you just following a link to `/app/`? `mod_proxy_html` is pretty hackish - if this application is internally developed, can your developers put proper relative paths in their HTML? – Shane Madden Jul 18 '12 at 03:19
  • @ShaneMadden - I've added snippets from my rewrite_log and access_log file. The browser seems to get a 302. As far as paths in the app, I'll have to follow up with them on whether they're using relative paths or not. – Matthew Schmitt Jul 18 '12 at 03:35

1 Answers1

1

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.

user207421
  • 1,010
  • 6
  • 16
  • I've reworked the config to utilize mod_proxy_ajp and yet I'm still getting the context path in the URL string. I'm missing something here, but I can't for the life of me figure out what. I've attempted to play around with the rewrite rules to no avail and so I'm grasping at straws atm. – Matthew Schmitt Jul 17 '12 at 21:55