Search code examples
javaapachetomcathttp-redirectmod-proxy

Sending redirect in Tomcat web application behind a Apache 2 proxy (mod_proxy)


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 to http://localhost/WebApp/a.html

How do I get the correct redirect to http://localhost/a.html?


Solution

  • 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