- Amir Boroumand | Software Engineer based in Pittsburgh, PA/
- blog/
- Using Apache as a Reverse Proxy for Spring Boot Embedded Tomcat/
Using Apache as a Reverse Proxy for Spring Boot Embedded Tomcat
Overview #
A common setup for Java web applications is to run Tomcat behind a web server like Apache in a reverse proxy configuration. This allows Apache to handle all incoming and outgoing traffic between users and the Tomcat web application.
In the above diagram, the Tomcat server runs on localhost interface (127.0.0.1) with default port 8080. Communication between Apache and Tomcat processes is unencrypted which is acceptable since they are both running on the same server.
How does the web application know which URL it lives on? It won’t know unless Apache forwards the HTTP headers to Tomcat.
This is valuable in a number of use cases:
- Application needs to e-mail users with links for password resets and account confirmations.
- Multi-tenancy has been implemented and we are using a subdomain to identify the customer.
Spring Boot application.properties #
Here we tell Spring Boot to run on localhost with default port of 8080. We also specify that it should use the headers given to it by Apache which we’ll configure in the next section.
Spring Boot 1.x
server.address=127.0.0.1
server.port=8080
server.use-forward-headers=true
Spring Boot 2.x
server.address=127.0.0.1
server.port=8080
server.forward-headers-strategy=native
Apache VirtualHost #
We add the below directives to our virtual host. This example assumes that all content is served from our Spring application (including static files).
ProxyPreserveHost on
RequestHeader set X-Forwarded-Proto https
RequestHeader set X-Forwarded-Port 443
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
Application #
With Spring Boot, we can add HttpServletRequest request
to any controller method parameter in order to gain the ability to inspect the request.
We can use the following methods to determine our URL:
- getScheme() - returns the protocol (http or https)
- getServerName() - returns the hostname (e.g. cloud.myapp.com)