Correctly setup Tomcat behind Apache with mod_proxy_ajp - apache

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.

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>

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).

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.

Related

I can't pass URL Parameters with Vue-Router and Apache2?

I am deploying an Vue3 Applikation with Vue-Router 4 on an Apache2 Server.
I observed some obstacles while doing it.
So my main problem is, that I can't pass Url Params to Vue via the Apache2 Server.
While developing the app and debugging it at localhost, everything worked perfectly.
e.g localhost:8080/myParam
Matches and redirects me to the index.html and passes the myParam to vue-router and the correct view is displayed.
So far so good.
Now I am deploying on an apache2 server and exactly that redirecting doesnt work.
I have read the docu and found this description:
https://router.vuejs.org/guide/essentials/history-mode.html#apache
The redirect works. But when I type in example.org/browse/myParam it redirects me to example.org/browse/index.html and my myParam is gone.
My Setup:
Apache 2.4, Vue3, Vue-Router4
The App is a Subapplication of a bigger project (thatswhy the app is not served in the root folder).
At the moment my App is running in a docker-container on the Server at port 8895, so I needed to create a proxypass in the apache.conf.
Because the files were not actually accessible at the server I also couldnt just use {REQUEST_FILE} (as shown in the vue-router example), so I solved it kind of hacky via the request uri and a pattern matching. But in my view that shouldn't be the problem, right?
#------------#
# BROWSER #
#------------#
ProxyPass /browse/ http://localhost:8895/
ProxyPassReverse /browse/ http://localhost:8895/
RewriteEngine On
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteRule ^/browse/index\.html$ - [L]
RewriteCond %{REQUEST_URI} !/browse/js/.*.js(.map)?$
RewriteCond %{REQUEST_URI} !/browse/css/.*.css$
RewriteRule ^/browse/ https://example.org/browse/index.html [L]
</IfModule>
Conclusion: I can visit my website, but only the homepage. I can't visit https://example.org/browse/Person/Sebastian directly. I can only go to https://example.org/browse/index.html and the click myself through the application.
I can't imagine that there are not many other people who had a similar problem, but I couldn't find any.

redirect from subdomain to different host without 301

I need to point from someSub.somedomain.com to mysub.mydomain.com, and I need the url of the site to continue reading someSub.somedomain.com
I've tried many variations of:
RewriteCond %{HTTP_HOST} ^DomainA.com
RewriteRule ^(.*) http://DomainB.com/$1 [P]
But I can't seem to get anything to work. Any advice?
This answer kind of already answers this question:
https://serverfault.com/questions/506623/masking-the-url-in-a-mod-rewrite
But it appears to me what you are looking for is a reverse proxy.
In the virtual host for your server:
ServerName somesub.somedomain.com
ProxyPass "/" http://mysub.mydomain.com/
ProxyPassReverse "/" http://mysub.somedomain.com/
Now when you go to your http://somesub.somedomain.com all the requests will behind the scenes actually be going to http://mysub.mydomain.com but the browser user won't see that.
There are various customizations to this you can make.
Don't forget to enable mod_proxy

Issue with RewriteCond

Ive got an issue with apache's rewrite module. This is what im trying to do:
Ive got confluence(tomcat) running on a server with apache as reverse proxy in front.
Also, im using authentification in apache (form auth). So if ure trying to access [server]/confluence, you get redirected to a file login.php containing the authentification routine. If login succeeds, proxy lets u access tomcat.
Every other request is blocked. This works easily for every request except for [server]/login.php as this file exists indeed in htdocs. Every other request is handled with
FallbackResource wrong_url.shtml
Now i want to block direct access to login.php as you would get stuck in a dead end.
I tried to do this by using a RewriteCond with ${REQUEST_URI} as phpinfo() gave me this:
<server>/confluence (you automatically get redirected to login.php by apache): php says REQUEST_URI = /confluence
<server>/login.php: php says REQUEST_URI = /login.php
makes sense, though. Now what i did is:
<VirtualHost *:80>
ServerName 192.168.2.237
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/login.php$
RewriteRule ^/login.php$ wrong_url.shtml [L]
</VirtualHost>
But this doesnt work properly. It either wont work at all or it crashes everything.
Pls forgive me if this is obvious, but im quite a beginner to rewriting. Can anybody tell me wheres my fault oder provide me a way to do this (propably, this is really easy)?
Have you checked the server logs ? Enable and set RewriteLogLevel (to 9) and debug the request flow.
Although you don't really need mod_rewrite for such a basic task, use mod_alias instead.
<VirtualHost *:80>
ServerName 192.168.2.237
Alias /login.php /wrong_url.shtml
</VirtualHost>

ProxyPass and RewriteRule [P] acting differently in regard to http/https

I have a working configuration that looks like
ProxyPass /roundcube protocol://127.0.0.1:8080/roundcube
ProxyPassReverse /roundcube protocol://127.0.0.1:8080/roundcube
when I go to
http://www.example.com/roundcube
or
https://www.example.com/roundcube
both or properly proxied to the server on 127.0.0.1:8080, as expected.
However, I would like to have more control over when the proxying happens, so I would like to use mod_rewrite's [P] option rather than the ProxyPass directive shown above. I tried the following:
RewriteEngine On
RewriteRule ^/roundcube$ /roundcube/ [R]
RewriteRule ^/roundcube/(.*) protocol://127.0.0.1:8080/roundcube/$1 [P]
ProxyPassReverse /roundcube protocol://127.0.0.1:8080/roundcube
With that configuration, when I go to
http://www.example.com/roundcube
the request proxies correctly as expected.
BUT when I go to
https://www.example.com/roundcube
the request 404's.
So my question is, why does the mod_rewrite proxy not work the same way as the ProxyPass version, in regard to both http and https requests? My two examples above should be functionally equivalent based on my understanding, but that does not seem to be the case. What am I missing? I haven't been able to track down any documentation that would explain this. Thanks!
Although it might be too late, I'm posting this answer in case someone comes to this page with the same problem.
The syntax for ProxyPass is different from that of RewriteRule. In RewriteRule, in order to refer to the protocol, you should use %{SERVER_PROTOCOL} as explained at http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html

Configuring mod_rewrite and mod_jk for Apache 2.2 and JBoss 4.2.3

My problem is as follows: I have JBoss 4.2.3 application server with AJP 1.3 connector running on one host under Windows (192.168.1.2 for my test environment) and Apache 2.2.14 running on another FreeBSD box (192.168.1.10). Apache acts as a "front gate" for all requests and sends them to JBoss via mod_jk. Everything was working fine until I had to do some SEO optimizations. These optimizations include SEF urls, so i decided to use mod_rewrite for Apache to alter requests before they are sent to JBoss. Basically, I nedd to implement 2 rules:
Redirect old rules like "http://hostname/directory/" to "http://hostname/" with permanent redirect
Forward urls like "http://hostname/wtf/123/" to "http://hostname/wtf/view.htm?id=123" so that end user doesn't see the "ugly" URL (the actual rewrite).
Here is my Apache config for test virtual host:
<VirtualHost *:80>
ServerAdmin webmaster#dummy-host.example.com
DocumentRoot "/usr/local/www/dummy"
ServerName 192.168.1.10
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule /directory/(.*) /$1 [R=permanent,L]
RewriteRule ^/([^/]+)/([0-9]+)/?$ /$1/view.htm?id=$2
</IfModule>
JkMount /* jsp-hostname
ErrorLog "/var/log/dummy-host.example.com-error_log"
CustomLog "/var/log/dummy-host.example.com-access_log" common
</VirtualHost>
The problem is that second rewrite rule doesn't work. Requests slip through to JBoss unchanged, so I get Tomcat 404 error. But if I add redirect flag to the second rule like
RewriteRule ^/([^/]+)/([0-9]+)/?$ /$1/view.htm?id=$2 [R,L]
it works like a charm. But redirect is not what I need here :) . I suspect that the problem is that requests are forwarded to the another host (192.168.1.2), but I really don't have any idea on how to make it work. Any help would be appreciated :)
The reason your second rewrite rule doesn't work is that you use the '?' in your URI definition and the URI definition never contains the separator '?'.
So simply use the rewrite rules without it. eg.
RewriteRule ^/([^/]+)/([0-9]+)/$ /$1/view.htm?id=$2 [R,L]
Simply, doesn't works because the first RewriteRule has the [L] at the end, which means is the last rule to process.