-1

I've been tinkering with Apache + Tomcat so that I can serve multiple tomcat apps (in different machines) through apache (clean & crisp urls rock). I've succesfully configured mod_proxy_ajp & mod_rewrite to the point where I can serve two tomcat apps in different machines with almost no troubles.

The only issue I've found is that one of the apps (which I'm developing in Struts2) has a lot of links and forms, which are generated with <s:a />, <s:url /> and <s:form /> tags. The urls generated by these tags generally are like this:

/WebApp/path/to/some.action

Thanks to the magic of ModRewrite, this is generally not a big issue and hyperlinks poiting to such urls are quickly rewriten & redirected to /app/path/to/some.action (although I do get tons of 302 responses).

The real problem occurs when performing POST requests. As you all might know, I cannot redirect POST requests with mod_rewrite... so in the end... all of my POST requests don't work because mod_rewrite redirects to the correct url but as a GET request.

I have already read a bit about mod_proxy_html and how it can help me rewrite the urls returned by the Tomcat web application... but it feels troublesome.

This is my current apache configuration:

## HACKING BEGINS RIGHT HERE

# cookies
ProxyPassReverseCookiePath /WebApp /app
# this is for CSS, IMGs, JS and redirecting urls with /WebApp*
RewriteRule ^/WebApp(.*)$ /app$1 [R,L]
<Location /app>
    ProxyPass ajp://localhost:8009/WebApp
    ProxyPassReverse ajp://localhost:8009/WebApp
    Order allow,deny
    Allow from all
</Location>

# the other app
ProxyPassReverseCookiePath /WebApp2 /other
<Location /other>
    ProxyPass ajp://200.9.4.6:8009/WebApp2
    ProxyPassReverse ajp://200.9.4.6:8009/WebApp2
    Order allow,deny
    Allow from all
</Location>

There must be a solution to my POST requests problem... Any ideas? Can I somehow configure something that will allow Struts2 to output correct urls?

Thanks for your help.

Federico Cáceres
  • 1,216
  • 12
  • 19

3 Answers3

0

This is a problem with the webapp setup; there may be a way to work around it in httpd config, but it's cleaner to fix the original inconsistency vs. hacking around it.

Also worth mentioning that Struts is trying to help you by giving you context-aware, non-relative URLs; if you just make the paths match, you can rely on that (instead of fighting it...).

So, just deploy the Struts webapp to /app and /other, instead of /WebApp and /WebApp2. (There might be some reason this isn't possible -- like if you don't actually control those other servers -- but it sounds like that doesn't apply).

Rob Whelan
  • 1,281
  • 13
  • 15
0

There may be a couple ways to go about this.

If you are able to deploy your app to Tomcat under the same name that you are using in the URL, that would be the easiest. So your application app would be /webapps/app[.war] instead of /webapps/WebApp, this would avoid the rewrite altogether.

Otherwise, the following should work, and should go before your current rewrite rule. The [PT] should allow Apache to still proxy the request (this works when using mod_jk, not sure I've used/tested it with mod_proxy_ajp):

RewriteCond %{REQUEST_METHOD} POST
RewriteRule ^/WebApp(.*)$ /app$1 [PT,L]

Once your bean has processed the POST request, you could then send the request to a URL that would be redirected. In the end, the POST URL doesn't matter to the user, so it doesn't have to be a pretty URL.

Edits Below:

I saw on the Apache mod_proxy, that ProxyPassReverse should work with the [PT] flag. And I was able to replicate the issue you're having, and the below config worked for me with a basic JSP page with a form that posted to another JSP page.

<VirtualHost *:80>
    ServerName localhost
    RewriteEngine On

    RewriteCond %{REQUEST_METHOD} !POST
    RewriteRule /WebApp/(.*) /app/$1 [R,L] 

    RewriteCond %{REQUEST_METHOD} POST
    RewriteRule /WebApp/(.*) /app/$1 [PT,L]

    <Location /app>
        ProxyPass ajp://localhost:8109/WebApp
        ProxyPassReverse ajp://localhost:8109/WebApp
    </Location>
</VirtualHost>
clmarquart
  • 4,721
  • 1
  • 27
  • 23
  • Unfortunately... it's not working... I'm still getting a 302 redirect response for my `POST` requests. I read that [PT] will pass the request through to some uri-to-file mapper... In this case I'm not using virtualhosts or anything like that... do you think this could affect the rule? – Federico Cáceres Mar 31 '11 at 13:24
  • I have always used a VirtualHost, even it is just localhost, but I don't think that should matter in this case. Are you using relative paths for the rewrite? I know your example is, but thought I'd ask since mod_rewrite will force a 302 redirect on rules that change domains. – clmarquart Mar 31 '11 at 16:01
  • I'm using the same configuration as I pasted up in my question... In any case... Maybe `JkMount` works in a different way vs `mod_proxy` and that's why `[PT,L]` worked for you? – Federico Cáceres Mar 31 '11 at 18:26
  • I added a config that worked for me with 2 basic JSP pages, hopefully it helps out, I think the only real difference is the RewriteCond on your original RewriteRule along with my original suggestion. – clmarquart Mar 31 '11 at 20:11
  • Hmm... unfortunately using your exact same configuration, everything works like a charm *but* POST requests still do not work :(. These post requests are to actions and not JSP files... so maybe there's a difference there... who knows... – Federico Cáceres Apr 01 '11 at 15:10
  • What exactly is happening to your POST requests, are the they still being redirected, are they making it to Tomcat as `/WebApp/*`, any errors? As far as Apache is concerned, it doesn't matter what the URL that it's forwarding/redirecting too, it will just forward the request (which in this case the request, when it gets to Tomcat, should have a content-length > 0). Also, something to check would be that your WebApp can accept POST requests, while by-passing Apache altogether.. http://localhost:[PORT]/WebApp/, as Tomcat is configurable to deny POST requests, although not by default. – clmarquart Apr 01 '11 at 15:30
  • Ok... bug tracked IT DOES WORK... the problem is with cookies (particuarly, session cookies). I have an interceptor that checks for certain data inside the session, I have mapped my session using `ProxyPassReverseCookiePath` to the new URL. So the cookie that exists when accecing the app through `/app` does not exist when accessing it *directly* through `/WebApp`... Now I **only** need to make my cookies work on both paths... maybe making it work for the root `/` path? – Federico Cáceres Apr 01 '11 at 16:54
  • So... I benchmarked mod_proxy_html (rewriting HTML - yes, I got it working yesterday out of desperation) vs mod_proxy_ajp (redirecting requests). Rewriting the HTML is a little bit slower (running on localhost mod_proxy_ajp is 30% faster). But I fear that all those 302 redirects for all my urls could become *quite unperformant* on the internet... – Federico Cáceres Apr 01 '11 at 17:43
  • I would agree that 302 redirects are best to avoid...do you have the option of deploying your WebApp to Tomcat under a different context name (`app`), should allow struts to build the same URLs that you are expecting in Apache? Otherwise, I'd suggest trying `mod_jk` so you can stick to using AJP for better performance. Also mod_jk has built-in handling of sessions, which should help with your cookie problem. – clmarquart Apr 01 '11 at 17:47
  • I fixed the cookie issue by setting the cookie path to `/` instead of `/app` (which was the path used by the app when being served though apache). Doesn't `mod_proxy_ajp` already use the ajp protocol to speed up communication with tomcat, why use `mod_jk`? And changing contexts could be a problem, because we would like to deploy this using subdomains in one installation and using folders in another installation. I cannot even imagine how to change all contexts to `/` when deploying with subdomains :D. Besides, setting up all the magic on Apache is very convenient. – Federico Cáceres Apr 01 '11 at 18:13
  • Sorry, I didn't mean for deployment to `/`, that would get messy as you mention. I meant deploying to `/app` so your app can be accessed via `http://localhost/app` or `http://localhost:8080/app`, then you wouldn't need the extra config. Yes, `mod_proxy_ajp` is using `AJP`, but it's been my experience that `mod_jk` works better with Rewrites & Session handling between Apache/Tomcat and has a lot more versatility in its configuration. But that by no means makes it the best solution here. I just mention it as another option if you continue to encounter problems with performance and sessions. – clmarquart Apr 01 '11 at 18:53
-1

I would avoid URL rewriting. It just opens cans of worms like this, makes you look into mod_proxy_html, etc, which of course are just yet more worms. Instead just deploy your apps in Tomcat with real URLs you can live with as being visible externally.

user207421
  • 305,947
  • 44
  • 307
  • 483