Sending redirect in Tomcat web application behind a Apache 2 proxy (mod_proxy)
Solution 1
Thanks to Stuart and his link to this blog I found a solution: Reverse Proxying Tomcat Web Applications Behind Apache
Solution: ProxyPreserveHost must be turned off!
Reason: If it is switched on, the response headers returned by the proxy backend will contain “localhost” or the real domain without the port number (or 80). So the ProxyPassReverse pattern does not match (because of the different port and if another domain name is used, also the domain name will not match).
Config:
<VirtualHost localhost:80>
ProxyPreserveHost Off
ProxyPass / http://localhost:8080/WebApp/
ProxyPassReverse / http://localhost:8080/WebApp/
</VirtualHost>
But this works only via http, not via ajp (I don’t know why). If you still want to use ajp you could use the following workaround - Let Apache do another redirect after the wrong redirect:
<VirtualHost localhost:80>
ProxyPass /WebApp !
ProxyPass / ajp://localhost:8009/WebApp/
ProxyPassReverse / ajp://localhost:8009/WebApp/
RedirectMatch 301 ^/WebApp/(.*)$ /$1
RedirectMatch 301 ^/WebApp$ /
</VirtualHost>
The ProxyPass /WebApp !
directive is needed to exclude the path from further processing in mod_proxy (because proxy directives are evaluated before redirect directives)
Then the RedirectMatch
directives redirect everything stating with /WebApp/...
respectively /WebApp
to the URL without /WebApp
at the beginning.
The only drawback is that you must not have any sub folder named WebApp
in your web application
Solution 2
I also had this problem and spent some time on it. I believe that if you change your apache httpd configuration to the following your redirect will work:
<VirtualHost localhost:80>
ProxyPreserveHost On
ProxyPass / http://localhost:8080/WebApp/
ProxyPassReverse / http://localhost/WebApp/
ProxyPassReverseCookiePath /WebApp /
</VirtualHost>
This is because the tomcat response headers will contain the proxy headers (i.e. the Location header is http://localhost/WebApp
rather than http://localhost:8080/WebApp
) because ProxyPreserveHost is switched On.
As a footnote: This also works with you want to change your webapps context. Say you wanted to change the publicly visible context to context you can use the following:
<VirtualHost localhost:80>
ProxyPreserveHost On
ProxyPass /context/ http://localhost:8080/WebApp/
ProxyPassReverse /context/ http://localhost/WebApp/
ProxyPassReverseCookiePath /WebApp /context
</VirtualHost>
For reference, I found this blog post extremely helpful: Reverse Proxying Tomcat Web Applications Behind Apache
Mahe
Updated on May 20, 2020Comments
-
Mahe almost 4 years
I have a web application on tomcat
http://localhost:8080/WebApp/
The I have configrued Apache 2 (mod_proy) so that the web application is directly accessible by localhost with out port and name: e.g
http://localhost
<VirtualHost localhost:80> ProxyPreserveHost On ProxyPass / http://localhost:8080/WebApp/ ProxyPassReverse / http://localhost:8080/WebApp/ </VirtualHost>
The index.html is shown correctly on
http://localhost
. But if a servlet redirects:@WebServlet(description = "...", urlPatterns = { "/login" }) public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.sendRedirect("a.html"); } }
and I use the URL
http://localhost/login
- I am redirected tohttp://localhost/WebApp/a.html
How do I get the correct redirect to
http://localhost/a.html
? -
Mahe over 10 yearsWith
ProxyPreserveHost On ProxyPass / ajp://localhost:8009/MobikatWebApp/ ProxyPassReverse / ajp://localhost:8009/MobikatWebApp/
it is still the same issue... -
Mahe over 10 yearsHm, that's a pitty... I planned to have several subdomains pointing do different web apps. So the ROOT context is not an option.
-
Usman Mutawakil over 10 yearsI don't understand what you mean by several sub domains. Do you mean for example
/login1
redirects to/a.html
,/login2
redirects to/b.html
,/login3
redirects to/c.html
all being redirected by the same servlet? -
Mahe over 10 yearsNo the problem I have described, is just a sub problem. I have a Tomcat server with several apps. I now want
app1.domain.net
point tolocalhost:8080/app1/
andapp2.domain.net
tolocalhost:8080/app2
on my server. I prefer the sub domains because, it makes it easier to distribute the apps later on several servers (if needed) -
Usman Mutawakil over 10 yearsI see. Try the new method I just added. If you use forwarding instead of redirection then the browser will not get the new URL. It will remain
/app1
and/app1/app1.html
will stay hidden. -
Mahe over 10 yearsNice possibility of Tomcat. I did not know it before! But this is not really applicable to my problem...
-
Mahe over 10 yearsThanks, but this did not solve the problem. But the link to the blog post was very helpful. See my updated solution.
-
Stuart over 10 yearsHi @Mahe, I'm glad this helped you find a solution. I think this is a missing part of the apache httpd online documentation for the ProxyPassReverse and ProxyPreserveHost directives wrt acting as a reverse proxy. Apache httpd is often used as a reverse proxy and the web apps that it acts as reverse proxy for are often not on the same server. All examples I could find assumed the proxy and proxied machines ran on the same machine. For anyone else looking at this post see documentation at apache httpd as reverse proxy
-
Bhavik Shah over 8 yearsHey thanks for the footnote on changing the context of webapp. it really helped