Reverse Proxying an angular-cli SPA with Apache and Tomcat

Abou Kone
Code d'Ivoire
Published in
3 min readOct 31, 2017
Angular 4

It’s always beneficial to have your development environment closely mirror your production one, and thanks to tools like Docker it’s quite easy to set it up nowadays. In this post we will learn how to set up a dev environment for an Angular 4 application, backed by an api served with Tomcat fronted by Apache. If my production Angular app was served available at http://www.production.com , and the backing api at http://www.production.com/api, my goal would be to replicate the same set up for my local dev environment, so have my front-end being served at http://www.production.dev/app and apiat http://www.production.dev/api. I would want to I will be making the following assumptions:

  • an Apache-2.4 web server running on port 80, configured for the domain http://production.dev/, with the modules mod_proxy and mod_proxy_http enabled
  • a Tomcat-8.5.27 api server running on port 8080 that is accessible on http://production.dev:8080/api.
  • An angular-cli (v1.3.2) Angular 4 application running in dev with ng serve that is normally available by default at http://localhost:4200.

As a developer I wanted both my Angular and API application to be able to be accessible from a production.dev domain when developing locally. There are three separate areas to configure to make it happen.

Custom Domain

In order to be able to access the production.dev address, I set up a custom domain in my Mac’s etc/hosts file. This maps my default localhost address to this custom domain:

127.0.0.1    production.dev

Apache

The first thing you will need is to configure Apache to reverse proxy both the Angular (app)and the Tomcat (api)applications. A representative httpd.conf would look like:

<IfModule mod_proxy.c>
ProxyRequests Off
ProxyVia Off
ProxyPreserveHost On
ProxyStatus On ProxyPass /api http://localhost:8090/api
ProxyPassReverse /api http://localhost:8090/api
ProxyPassReverseCookiePath /api /
ProxyPass /app http://localhost:4200/app/
ProxyPassReverse /app http://localhost:4200/app/
</IfModule>

This sets up Apache to forward requests from /api to our Tomcat api app instance.

In your httpd.conf: make sure to enable mod_proxy

....
LoadModule proxy_module lib/httpd/modules/mod_proxy.so
...
LoadModule proxy_http_module lib/httpd/modules/mod_proxy_http.so
....

You can also set it up in the exact same way if you are using Virtual Hosts. You’ll notice that the Tomcat port is 8090 which is not the default Tomcat port, which leads me to the next configuration.

Tomcat

In my case I wanted my app to have the context path of api since it would be served from the same domain as my front end app. So my server.xml configuration was updated to contain a Context entry. I will not add it here since it was done through configuring my IntelliJ configuration but my app was available after a local deploy at http://production.dev/api. You’ll need to create a new connector for your app for the proxying to work. A sample configuration would be :

<Connector port="8090" 
connectionTimeout="20000"
redirectPort="8443"
maxThreads="48"
minSpareThreads="10"
enableLookups="false"
acceptCount="10"
debug="0"
URIEncoding="UTF-8"
protocol="org.apache.coyote.http11.Http11NioProtocol"
proxyName="production.dev"
proxyPort="80"
scheme="http"/>

proxyPort is the important configuration here, it allows you application to reflect the port being proxied (80) rather than the port it is running on (8090).

Angular

In order for this setup to work locally, I had to set up local proxying made enabled by the proxy feature of the webpack-dev-server that powers the angular-cli. I was getting 404s when using the http://production.dev/app url to access my Angular app when it was served through ng serve — host production.dev. In order to resolve this I had to add to add a proxy configuration for my app like this in a newproxy.conf.json in my app’s root directory :

{"/app/**": {"target": "http://production.dev:4200/","secure":false,"logLevel":"debug","pathRewrite": {        "^/app": ""    }}}

With that configuration in place, i ran my ng serve as

ng serve --host production.dev --proxy-config proxy.conf.json --base-href /app/

The base-href option is important in this case it allows us to specify the base url of the application which is app in this case.

This completes the local setup of a development environment to try and mirror production domain wise using Angular, Apache and Tomcat. In the case of Angular you might need the deploy-url option to be specified with the ng serve to get this to work.

--

--

Abou Kone
Code d'Ivoire

Chief Mercenary @akiltechnologies. @codedivoire founder. African Tech is on my mind.