Отправка перенаправления в веб-приложении 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 и нажмите следующую команду.
-
sudo a2enmod proxy_http
(для перенаправления http). -
sudo a2enmod proxy_wstunnel
(для websocket перенаправление) - и
sudo service apache2 restart
- запустите сервер приложений на порту 8080