ProxyPassReverse to Tomcat adding path to URL - apache

I'm running Railo 3 in Tomcat 6.0.32. The tomcat server is fronted by Apache 2.2.20. Tomcat and Apache are pre built binaries from openCSW. Railo is just the latest build war deployed in tomcat's autodeploy dir webapps.
Everything is working fine when I try to access railo and content on the tomcat server.
It fails however, when railo on tomcat redirects me to itself. Mostly, when a cfm script uses the CGI.script_name, it will be returned wrong.
On the Apache side, the content is available on www.hostname.com. Apache redirects the user to tomcat through AJP on www.hostname.com:8009/railo/content.
A script on tomcat (taken from open OAuth example) is available at:
/opt/csw/share/tomcat6/webapps/railo/content/oauth_test/examples/admin_consumers.cfm
When I access it and try to perform some action, it calls itself with a few parameters, but at that point, railo dumps out an error, complaining that the file can not be found:
Page /content/railo/content/oauth_test/examples/admin_consumers.cfm [/opt/csw/share/tomcat6/webapps/railo/content/railo/content/oauth_test/examples/admin_consumers.cfm] not found
As you can see railo added twice the relative path from tomcat: /railo/content/railo/content
This is my configuration for the virtual host in Apache:
<VirtualHost *:443>
ServerName www.hostname.com
DocumentRoot "/opt/www/hostname/htdocs/"
ProxyRequests Off
<proxy *="">
Order deny,allow
Allow from all
</proxy>
ProxyPass / ajp://www.hostname.com:8009/railo/content/
ProxyPassReverse / http://www.hostname.com:8888/railo/content/
</VirtualHost>
I tried several variant for the ProxyPassReverse directive, but with no luck so far. Based on extensive searches on the web (The Mystery of ProxyPassReverse), I tried this for the proxypassreverse:
ProxyPassReverse / ajp://www.hostname.com:8009/railo/content/
ProxyPassReverse / http://www.hostname.com:8888/railo/content/
ProxyPassReverse / http://localhost:8888/railo/content/
ProxyPassReverse / https://www.hostname.com
The tomcat server also has a virtual host defined like this:
<Host name="www.hostname.com">
<Context path="" docBase="/opt/csw/share/tomcat6/webapps/railo/content" />
</Host>
But everytime, I always get the error from Railo.
Has anyone ever seen this problem with Railo, or CGI, and has an idea how to fix it?

You are specifying "/railo/content" twice. Once in your "docBase" attribute and again in your Proxy attributes. So, requests being proxied through Apache are going to have "railo/content/" twice in their request paths because you have it listed twice: once in Apache, another time in Tomcat.
Try leaving off the /railo/content/ in your ProxyPassReverse attribute:
ProxyPassReverse / http://www.hostname.com:8888/
This will let the Tomcat config add the /railo/content/ bit all by itself.

Related

Apache ProxyPass to 2 different tomcat servers with same URI

I have 2 servers with apache http server (2.4.9) on them. I have 2 servers with tomcat 7.0.39 running on them. Ultimately I need to load balance between the 2, but right now am simply trying to get this ProxyPass configuration to work.
I have one url on the 2 apache servers- example.com. They are load balanced. The load balancing is in place and there is no issue.
I have 2 applications, 1 on each tomcat server. Each tomcat server has 2 instances of tomcat running- each on a different port. They are running a very similar application with the exact same uri.
I need to redirect:
example.com/site1 to example.com/app (for app1)
example.com/site2 to example.com/app (for app2)
I can redirect this easily enough for 1 application only:
ProxyPass /app/ AppSrv:8080/app/
ProxyPassReverse /app/ http://example.com/app/
I can get to the page, log in, no problem. For a singe application only.
When I set up a configuration for both applications, I can get to the login page of both applications as well when configured as such:
ProxyPass /site1/ AppSrv:8080/app
ProxyPassReserve /app/
ProxyPass /site2/ AppSrv:8081/app
ProxyPassReverse /app/
Both urls come up with the tomcat application login page. But neither work after this- they fail. The uri reads 'site1' (or 'site2') not 'app'. I cannot log in.
The application requires the uri '/app/' as the base uri in order to function.
The applications are listening on different ports, but have the same uri. How do I keep the uri in the url, but change it so the application responds?
Ultimately I have to balance this, but I've done that before. This is the part I'm having a hard time with.
Ok, I finally solved this. I had to modify the header.
ProxyPass /site1/ balancer://example.com/app/
ProxyPass /site2/ balancer://example.com/app/
<Location /site1>
ProxyPassReverse /app
ProxyPassReverseCookiePath /app /site1
Header edit Location ^(https?://)?example.com/app/ /site1/
</Location>
<Location /site2>
ProxyPassReverse /app
ProxyPassReverseCookiePath /app /site2
Header edit Location ^(https?://)?example.com/app/ /site2/
</Location>

JSF 2 / RichFaces 4 webapp with Apache and Tomcat not finding webapp resources library

I'm implementing a JSF2/RichFaces 4 web application running under Tomcat 7. I developed it under Eclipse using MyEclipse with Tomcat 7, everything works fine. When I deploy the application to the full production environment, the resource library images/css/js files get 404 from Apache. The production environment is Apache 2 with SSL and mod_proxy front-ending Tomcat 7. I'm suspecting the proxy setup is wrong and that, while the tomcat webapp runs, the Apache GET requests aren't being proxied properly, but I don't think I know enough to understand why.
Starting from the top, here's my apache virtual host with proxies (note *:443 for ssh):
NameVirtualHost *:443
<VirtualHost *:443>
ServerName testapp.xxx.org
SSLEngine on
SSLProxyEngine on
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLCertificateFile /etc/pki/tls/certs/testapp.xxx.org.crt
SSLCertificateKeyFile /etc/pki/tls/private/testapp.xxx.org.key
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
# Proxy everything to tomcat.
ProxyPass / http://localhost:8080/testapp/
ProxyPassReverse / http://localhost:8080/testapp/
</VirtualHost>
When I go to https://testapp.xxx.org, the application starts and displays the JSF but with no CSS, no js, and no images. The HTML for one such image resource looks like this, which is correct (same under Eclipse):
<img src="/testapp/javax.faces.resource/images/tairlogo.png.xhtml?ln=default" alt="TAIR web site" />
which should be starting at the webapp context root and looking for the resource library. The corresponding Apache access log GET is here:
"GET /testapp/javax.faces.resource/images/tairlogo.png.xhtml?ln=default HTTP/1.1" 404 12500
The actual JSF code for this image is:
<h:outputLink value="http://www.arabidopsis.org">
<h:graphicImage library="default" name="images/tairlogo.png"
alt="TAIR web site"></h:graphicImage>
</h:outputLink>
I think the problem is that your reverse proxy rule is assuming that the context name (testapp) is not present in the URL, while in the HTML you are assuming it is present (as in the src attribute of your img tag). You should either remove the context name in both the path and the target URL to proxy everything to Tomcat, e.g.:
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
Or keep it in both to only proxy that webapp to Tomcat:
ProxyPass /testapp/ http://localhost:8080/testapp/
ProxyPassReverse /testapp/ http://localhost:8080/testapp/
This will make your webapp available at https://testapp.xxx.org/testapp/. If you don't want the context name part in the URL, you can deploy the webapp in the Tomcat root.

Apache - Tomcat ProxyPass VirtualHost - Context Path

I have a problem configuring apache tomcat ProxyPass directive for two applications that have two different Context Paths in tomcat. The tomcat is running behind an apache and I use the apache to proxy path the requests to tomcat. In apache I want to access both application via a hostname instead of a context path.
Scenario:
tomcat
https://domain:8443/app1
https://domain:8443/app2
in tomcat the applications have the context path app1 and app2
in apache I want to enable both application as follow:
https://app1.host/
https://app2.host/
In apache I have created a configuration for each domain:
ProxyPass / https://localhost:8443/app1
ProxyPassReverse / https://localhost:/8443/app1
The strange thing is app1 is only available through apache using the context path:
https://app1.host/app1
Is it possible to realize such a setup with apache ProxyPass module?
Thx for your help.
You should be able to achieve the result you want by using virtual hosting. Also it's a good idea to pass the requests to tomcat via the AJP protocol instead of HTTPS. Try adding this to the Apache configuration
NameVirtualHost *:443
<VirtualHost *:443>
ServerName app1.host
ProxyPass / ajp://localhost:8009/app1/
</VirtualHost>
<VirtualHost *:443>
ServerName app2.host
ProxyPass / ajp://localhost:8009/app2/
</VirtualHost>
If you haven't changed the default server settings for Tomcat this should work just as it is. Otherwise make sure to specify the AJP port that is configured in Tomcat's conf/server.xml file. There should be a line similar to this:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
Make sure that you have the mod_proxy and mod_proxy_ajp modules loaded in Apache configuration, this may vary depending on your Apache installation. Also remove any previously configured 'ProxyPass / ...' lines as they will interfere with the new configuration. Hope this works for you.
you can try
ProxyPass / https://localhost:8443/app1/
ProxyPassReverse / https://localhost:8443/app1/
with the final /

AJP proxy that maps internal servlet name to a different external name

Using apache2 I want to set up an AJP proxy for a Tomcat server that maps an internal servlet URL to a completely different URL externally. Currently I am using the following configurations:
Apache2 configuration:
<IfModule mod_proxy.c>
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name ajp://192.168.1.30:8009/servlet_name
</IfModule>
Note that external_name and servlet_name are different.
Tomcat 6 configuration:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
This however does not work. Apache seems to forward http requests to Tomcat.
However the URLs and redirects returned by Tomcat are still using the original servlet_name and Apache does not map them to external_name.
Is this possible at all with AJP? If not can it be done using a plain http proxy instead?
Mapping different names between Apache and Tomcat can be quite tricky and depends much on how the web application builds its urls for the response.
Basically your setup is correct, but if your application uses its own servlet_name for redirects and urls ProxyPassReverse won't map them.
If you need this kind of setup have a look at mod_proxy_html (Apache 3rd party module) which will parse and rewrite also the contents, not only the url and response headers as mod_proxy.
( A late answer, but I just ran into this problem myself. )
It appears that ProxyPassReverse using ajp: doesn't work because the headers returned from a redirect don't have an ajp: URL in Location:, they have a http: URL. ProxyPassReverse just causes a rewrite of matching headers, and
that string doesn't match what's being returned.
This should work (provided the Location: field uses that numerical address
and not a host name.)
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name http://192.168.1.30/servlet_name
( You can use 'curl -I' to inspect the redirect headers and debug. )
See this note, or a more involved solution here using mod_proxy_html
for rewriting the URLs in web pages as well.
Additionally to the answer from Steven D. Majewski there is one more problem. If the target application uses the request host name to create a redirect (302 Moved Temporarily), it won't work with multiple host names. One must create multiple configurations for every name, like this:
ProxyPassReverse /external_name http://server.com/servlet_name
ProxyPassReverse /external_name http://server.org/servlet_name
ProxyPassReverse /external_name http://server.co.uk/servlet_name
Actually the ProxyPreserveHost on must solve this issue and replace the HOST header in the incoming requests with the address or IP specified in ProxyPass. Unfortunately it seems to be the ProxyPreserveHost doesn't work with ajp connectors. The tomcat in my configuration still received the host name got from browser instead replacing it with 192.168.1.30. As result the browser based redirects still didn't work for every name.
Following configuration didn't work as well :-(
# NOT WORKING !!!
ProxyPassReverse /external_name http://%{HTTP_HOST}/servlet_name
The workaround was using http instead of ajp.
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name http://192.168.1.30/servlet_name
Did somebody investigate it deeply?
For me, this seemed to cause problems:
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name http://192.168.1.30/servlet_name
While this seemed to work:
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name ajp://192.168.1.30:8009/servlet_name
I don't know why but it just did.

How do I connect my tomcat app to apache 2 so the paths aren't lame?

I've got a tomcat instance with several apps running on it... I want the root of my new domain to go to one of these apps (context path of blah).. so I have the following set up:
<Location />
ProxyPass ajp://localhost:8025/blah
ProxyPassReverse ajp://localhost:8025/blah
</Location>
it kinda works... going to mydomain.com/index.jsp works except the app still thinks it needs to add the /blah/ to everything like css and js.. is there something I can do without deploying the app to ROOT or changing the tomcat server config? I'd like to keep all this kind of thing on the apache side, if it's possible.
I'm thinking I may not be understanding the proxypassreverse directive..
If you're wanting to server the app the /, Tomcat expects the app to be mounted at /, and have the name of ROOT. At least that's how I've always handled the situation personally. Even if you just symlink the app into ROOT, that should mitigate your problems. If you have an app placed in ${tomcat_home}/webapps/newapp, then Tomcat deploys it with a context of /newapp. At least, that's been the case in my history. Also, not sure if it matters but I've always used:
ProxyPass / ajp://localhost:8025/blah
ProxyPassReverse / ajp://localhost:8025/blah
it looks like this is kind of a pain in the rear.
apache is literally rewriting pages as it serves them...
I think I'll go a different route.
If you configure hosts on the Tomcat side as well then you can proxy to them and eliminate the context path for non-root webapps--in Tomcat server.xml:
<Host name="myhost">
<Context path="" docBase="/path/to/files" />
</Host>
And on the Apache side:
<VirtualHost *:80>
ServerName myhost
ProxyPass / ajp://myhost:8009/
ProxyPassReverse / ajp://myhost:8009/
</VirtualHost>
Hope that helps.