web-dev-qa-db-fra.com

Envoi de redirection dans une application Web Tomcat derrière un proxy Apache 2 (mod_proxy)

J'ai une application Web sur Tomcat http://localhost:8080/WebApp/

J'ai configuré Apache 2 (mod_proy) de sorte que l'application Web soit directement accessible par localhost avec le port et le nom out: e.g http://localhost

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

Le fichier index.html apparaît correctement sur http://localhost. Mais si un servlet redirige:

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

et j'utilise l'URL http://localhost/login - Je suis redirigé vers http://localhost/WebApp/a.html

Comment puis-je obtenir la redirection correcte vers http://localhost/a.html?

14
Mahe

Grâce à Stuart et à son lien vers ce blog, j'ai trouvé une solution: Proxy inverse des applications Web Tomcat derrière Apache

Solution: ProxyPreserveHost doit être désactivé!

Raison: s'il est activé, les en-têtes de réponse renvoyés par le serveur proxy contiendront "localhost" ou le domaine réel sans le numéro de port (ou 80). Ainsi, le modèle ProxyPassReverse ne correspond pas (en raison du port différent et si un autre nom de domaine est utilisé, le nom de domaine ne correspond pas non plus).

Config: 

<VirtualHost localhost:80>

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

</VirtualHost>

Mais cela ne fonctionne que via http, pas via ajp (je ne sais pas pourquoi). Si vous souhaitez toujours utiliser ajp, vous pouvez utiliser la solution de contournement suivante - Laissez Apache effectuer une autre redirection après la mauvaise redirection:

<VirtualHost localhost:80>

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

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

</VirtualHost>

La directive ProxyPass /WebApp ! est nécessaire pour exclure le chemin d'accès du traitement ultérieur dans mod_proxy (car les directives proxy sont évaluées avant les directives de redirection)

Ensuite, les directives RedirectMatch redirigent tout ce qui est écrit avec /WebApp/... respectivement /WebApp vers l'URL sans /WebApp au début.

Le seul inconvénient est que vous ne devez pas avoir de sous-dossier nommé WebApp dans votre application Web.

14
Mahe

J'ai aussi eu ce problème et passé du temps dessus. Je crois que si vous modifiez votre configuration Apache httpd comme suit, votre redirection fonctionnera:

<VirtualHost localhost:80>
    ProxyPreserveHost On

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

    ProxyPassReverseCookiePath /WebApp /
</VirtualHost>

Cela est dû au fait que les en-têtes de réponse Tomcat contiendront les en-têtes de proxy (c'est-à-dire que l'en-tête Location est http://localhost/WebApp au lieu de http://localhost:8080/WebApp) car ProxyPreserveHost est activé.

En tant que note de bas de page: Ceci fonctionne également avec vous souhaitez modifier le contexte de votre application Web. Supposons que vous souhaitiez modifier le contexte visible publiquement en contexte, vous pouvez utiliser les éléments suivants:

<VirtualHost localhost:80>
    ProxyPreserveHost On

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

    ProxyPassReverseCookiePath /WebApp /context
</VirtualHost>

Pour référence, cet article de blog m'a été extrêmement utile: Proxy inverse des applications Web Tomcat derrière Apache

3
Stuart

Utilisez le transfert au lieu de la redirection

Je pense que votre problème est l'utilisation de sendRedirect. L'appel à sendRedirect est en fait supposé montrer au navigateur que l'URL a été redirigée. Si vous souhaitez masquer ce que vous devez utiliser le transfert. Dans votre servlet, essayez ceci au lieu de 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 );
} 

Dans votre fichier context.xml, définissez crossContext = "true" pour pouvoir transférer les demandes vers d'autres applications Web. 

<Context crossContext="true" ....../>
0
Usman Mutawakil

J'ai eu le même problème alors que j'essayais de rediriger la demande Apache2 (s'exécutant sur le port 80) à Tomcat (serveur d'applications s'exécutant sur le port 8080).

C'est la configuration qui fonctionne parfaitement.

Allez à /etc/Apache2/sites-available/000-default.conf et ajoutez la configuration suivante:

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

Fait. Maintenant, allez au terminal et appuyez sur la commande suivante.

  1. Sudo a2enmod proxy_http (pour la redirection http).
  2. Sudo a2enmod proxy_wstunnel (pour la redirection websocket)
  3. et Sudo service Apache2 restart
  4. exécutez votre serveur d'applications sur le port 8080
0
Manik Maurya

vous avez utilisé AJP Connector pour connecter Apache2 et Tomcat, ce seront les solutions parfaites pour cela.

si vous avez besoin de savoir comment configurer cela, dites-moi que je vais expliquer ce détail

0
Ramnath