Search code examples
apache.htaccesstomcat9

Configure Apache for Angular and Tomcat on the same host


I am trying to serve my application on a Centos 7 host, where I have deployed an Angular app for the frontend and Java Spring Boot app for the backend. My versions are Apache 2.4.6, Tomcat 9 and Angular 7.

Let's say my domain is example.com. I want the user to write the following on the browser to access the Angular app routes, i.e. the frontend:

example.com/**

Also I would like to be able to write the following on the browser to access the Java app routes, i.e. the backend:

example.com/api/**

I tried to do it using Apache's mod_proxy, after reading this post: https://stackoverflow.com/a/33095758/350061. However, I only managed to serve Angular through example.com, while my API is only served on its original endpoint, that is example.com:8080/my-api and not through example.com/api.

These are my Apache settings:

/etc/httpd/conf.d/example.conf

<VirtualHost *:80>
   ServerName example.com
   ProxyPreserveHost On
   DocumentRoot "/var/www/my-ng-app/dist/my-ng-app"

   RewriteRule ^/api/(.*)     http://localhost:8080/$1 [P,L,QSA]
   ProxyPassReverse /api/     http://localhost:8080/
</VirtualHost>

/var/www/my-ng-app/.htaccess

RewriteEngine On

RewriteRule ^api/(.*)      http://localhost:8080/my-api/$1 [P,L,QSA]

# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html

I have configured .htaccess to be read from that folder and verified that it is actually read. Also even if I remove the last part of .htaccess that redirects non-existing resources to index.html, the api does not get served from example.com/api, as I wish. It only gets served from example.com:8080/my-api

Any ideas on how to configure it?


Solution

  • After a long time of googling and trial and error, my solution consists of these changes:

    1. I edited Tomcat's server.xml connector to serve requests through localhost. This made possible for rewrite settings to access my Java app through localhost:8080, but made impossible for me to access remotely my Java app through example.com:8080, which is fine.
    2. I configured SELinux to allow Apache (httpd) to initiate outbound connections, in my case connections to localhost
    3. I applied some fixes on my original VirtualHost and .htaccess configuration

    More specifically:

    1. sudo nano /opt/tomcat/latest/conf/server.xml
      

      Find the connector for port 8080 and add address attribute as such:

      <Connector port="8080" protocol="HTTP/1.1"
                 address="127.0.0.1"
                 connectionTimeout="20000"
                 redirectPort="8443" />
      
    2. /usr/sbin/setsebool -P httpd_can_network_connect 1
      

      The -P persist the setting for future reboots

    3. /etc/httpd/conf.d/example.conf

      <VirtualHost *:80>
         ServerName example.com
         ProxyPreserveHost On
         DocumentRoot "/var/www/my-ng-app/dist/my-ng-app"
      
         RewriteRule ^/api/(.*)     http://localhost:8080/my-api/$1 [P,L,QSA]
         ProxyPassReverse /api/     http://localhost:8080/my-api/
      </VirtualHost>
      

      /var/www/my-ng-app/.htaccess

      # If an existing asset or directory is requested go to it as it is
      RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
      RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
      RewriteRule ^ - [L]
      
      # If the requested resource doesn't exist, use index.html
      RewriteRule ^ /index.html
      

    After these changes just restart Tomcat and Apache and you will be able to access your API through example.com/api