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

浪子不回头ぞ 提交于 2020-01-21 02:42:06

问题


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?


回答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




回答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




回答3:


you have use to AJP Connector to connect apache2 & tomcat , it will be the perfect solutions for this.

if you need how to configure this, tell me i will explain this detail




回答4:


Use forwarding instead of redirection

I think your problem is the use of sendRedirect. Calling sendRedirect is actually suppose to show the browser that the URL has been redirected. If you want to hide that you need to use forwarding.In your servlet try this instead of sendRedirect.

String servletPath = request.getServletPath();
if(servletPath.equals("/app1")){
     ServletContext ctx = request.getServletContext().getContext("/app1");
     RequestDispatcher dispatcher=ctx.getServletContext().getRequestDispatcher( "/app1/app1.html" ); // or wherever you actually keep app1.html
     dispatcher.forward( request, response );
} 

Inside your context.xml set crossContext = "true" so you can forward requests to other web applications.

<Context crossContext="true" ....../>



回答5:


I had the same problem while tried to redirect the apache2(running on port 80) request to tomcat(application server running on port 8080).

This is the configuration which is working perfectly.

Go to /etc/apache2/sites-available/000-default.conf and add the following config:

<VirtualHost *:80>
    # The ServerName directive sets the request scheme, hostname and port that
    # the server uses to identify itself. This is used when creating
    # redirection URLs. In the context of virtual hosts, the ServerName
    # specifies what hostname must appear in the request's Host: header to
    # match this virtual host. For the default virtual host (this file) this
    # value is not decisive as it is used as a last resort host regardless.
    # However, you must set it for any further virtual host explicitly.
    #ServerName www.example.com

    # for redirecting the websocket requests
    ProxyPass /ws ws://localhost:7681/ 
    #ProxyPass  /ws ws://localhost:7681/

    ProxyPassReverse   /ws ws://localhost:7681/

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
    # error, crit, alert, emerg.
    # It is also possible to configure the loglevel for particular
    # modules, e.g.
    #LogLevel info ssl:warn

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # For most configuration files from conf-available/, which are
    # enabled or disabled at a global level, it is possible to
    # include a line for only one particular virtual host. For example the
    # following line enables the CGI configuration for this host only
    # after it has been globally disabled with "a2disconf".
    #Include conf-available/serve-cgi-bin.conf


# for redirecting the http request 
   ProxyPass /applicationContextUrl                         '  http://localhost:8080/applicationContextUrl

   ProxyPassReverse /applicationContextUrl         http://localhost:8080/applicationContextUrl

   ProxyPassReverseCookiePath /applicationContextUrl / 
   ProxyPassReverseCookieDomain localhost applicationContextUrl
   ProxyRequests off
   ProxyTimeout 15


   ErrorLog ${APACHE_LOG_DIR}/nirad_error.log
   LogLevel debug
CustomLog ${APACHE_LOG_DIR}/nirad_access.log combined
<Proxy *>
       AddDefaultCharset off
       Order deny,allow
       Allow from all
       #Require all denied
       Require all granted
       Require local

</Proxy>
</VirtualHost>

Done. Now goto terminal and hit the following command.

  1. sudo a2enmod proxy_http (for http redirection).
  2. sudo a2enmod proxy_wstunnel (for websocket redirection)
  3. and sudo service apache2 restart
  4. run your application server on port 8080


来源:https://stackoverflow.com/questions/18333252/sending-redirect-in-tomcat-web-application-behind-a-apache-2-proxy-mod-proxy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!