Отправка перенаправления в веб-приложении Tomcat за прокси-сервером Apache 2 (Mod proxy)

у меня есть веб-приложение на Tomcat http://localhost:8080/WebApp/

Я сконфигурировал Apache 2 (mod_proy) так, чтобы веб-приложение было напрямую доступно localhost без порта и имени: e.g http://localhost

<VirtualHost localhost:80>
    ProxyPreserveHost On
    ProxyPass / http://localhost:8080/WebApp/
    ProxyPassReverse / http://localhost:8080/WebApp/
</VirtualHost>

индекс.html отображается правильно на http://localhost. Но если сервлет перенаправляет:

@WebServlet(description = "...", urlPatterns = { "/login" })
public class LoginServlet extends HttpServlet
{    
    @Override
    protected void doGet(HttpServletRequest request,
                     HttpServletResponse response) throws IOException
    {
        response.sendRedirect("a.html");
    }
 }

и я использую URL http://localhost/login - Я перенаправлен на http://localhost/WebApp/a.html

как получить правильное перенаправление на http://localhost/a.html?

5 ответов


благодаря Стюарту и его ссылке на этот блог я нашел решение: Обратное Проксирование Веб-Приложений Tomcat За Apache

решение: ProxyPreserveHost должен быть выключен!

причина: если он включен, заголовки ответов, возвращаемые прокси-сервером, будут содержать "localhost" или реальный домен без номера порта (или 80). Таким образом, шаблон ProxyPassReverse не соответствует (из-за другого порта и если другое доменное имя используется, также доменное имя не будет совпадать).

Config:

<VirtualHost localhost:80>

   ProxyPreserveHost Off
   ProxyPass /  http://localhost:8080/WebApp/
   ProxyPassReverse / http://localhost:8080/WebApp/

</VirtualHost>

но это работает только через http, а не через ajp (я не знаю, почему). Если вы все еще хотите использовать ajp, вы можете использовать следующий обходной путь-пусть Apache сделает еще один редирект после неправильного редиректа:

<VirtualHost localhost:80>

   ProxyPass /WebApp !
   ProxyPass /  ajp://localhost:8009/WebApp/
   ProxyPassReverse / ajp://localhost:8009/WebApp/

   RedirectMatch 301 ^/WebApp/(.*)$ /
   RedirectMatch 301 ^/WebApp$ /

</VirtualHost>

The ProxyPass /WebApp ! директива необходима для исключения пути из дальнейшей обработки в mod_proxy (потому что директивы прокси оцениваются перед директивами перенаправления)

затем the RedirectMatch директивы перенаправляют все, что говорится с /WebApp/... соответственно /WebApp к URL без /WebApp в начале.

единственным недостатком является то, что у вас не должно быть никакой подпапки с именем WebApp в веб-приложении


у меня также была эта проблема, и я потратил на нее некоторое время. Я считаю, что если вы измените конфигурацию Apache httpd на следующую, ваше перенаправление будет работать:

<VirtualHost localhost:80>
    ProxyPreserveHost On

    ProxyPass / http://localhost:8080/WebApp/
    ProxyPassReverse / http://localhost/WebApp/

    ProxyPassReverseCookiePath /WebApp /
</VirtualHost>

это потому, что заголовки ответов tomcat будут содержать заголовки прокси (т. е. заголовок местоположения http://localhost/WebApp, а не http://localhost:8080/WebApp), потому что включен ProxyPreserveHost.

в качестве сноски: это также работает с вы хотите изменить контекст webapps. Скажи, что хочешь изменить общедоступный контекстах можно использовать следующие:

<VirtualHost localhost:80>
    ProxyPreserveHost On

    ProxyPass /context/ http://localhost:8080/WebApp/
    ProxyPassReverse /context/ http://localhost/WebApp/

    ProxyPassReverseCookiePath /WebApp /context
</VirtualHost>

для справки, я нашел это сообщение в блоге очень полезным:Обратное Проксирование Веб-Приложений Tomcat За Apache


вы используете разъем AJP для подключения apache2 & tomcat, это будет идеальное решение для этого.

Если вам нужно как настроить это, скажите мне, я объясню это подробно


используйте переадресацию вместо перенаправления

Я думаю, что ваша проблема заключается в использовании sendRedirect. Вызов sendRedirect фактически должен показать браузеру, что URL-адрес был перенаправлен. Если вы хотите скрыть, что вам нужно использовать переадресацию.В вашем сервлете попробуйте это вместо 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 );
} 

внутри своего контекста.xml set crossContext = "true", чтобы вы могли пересылать запросы другим веб-приложениям.

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

у меня была та же проблема при попытке перенаправить запрос apache2(работает на порту 80) на tomcat(сервер приложений работает на порту 8080).

это конфигурация, которая работает отлично.

на /etc/apache2/sites-available/000-default.conf и добавьте следующую конфигурацию:

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

сделано. Теперь goto terminal и нажмите следующую команду.

  1. sudo a2enmod proxy_http (для перенаправления http).
  2. sudo a2enmod proxy_wstunnel (для websocket перенаправление)
  3. и sudo service apache2 restart
  4. запустите сервер приложений на порту 8080