Background
I am working on a Java EE project using Wildfly 8.x that will be deployed to Amazon Web Services behind an Elastic Load Balancer (ELB) instance. Additionally, the ELB will handle the SSL encryption/decryption i.e. SSL offload.
Used in this manner, the ELB adds useful information to the HTTP request in the form of “X-Forwarded-*” headers – see the ELB documentation for full details.
Of particular note is the “X-Forwarded-Proto” header which identifies the originating protocol (scheme), in our case this contains “https” for all requests where the ELB is providing the SSL offload.
Issue
The issue here is how to make the Wildfly (actually Undertow) environment aware that it should use the header to determine the originating protocol. As of Wildfly 8.0.0.CR1 this is included, but finding documentation about how to configure it was non-trivial.
Solution
Essentially, what you need to do is to enable “proxy-address-forwarding” for your (undertow) server in the Wildfly configuration. Note: I’ll be considering the “default server” here only.
There are multiple ways to achieve this, but the simplest is just to add the proxy-address-forwarding="true" attribute to the http-listener in your standalone.xml or domain.xml, as below:
<server name="default-server">
<http-listener name="default" socket-binding="http" proxy-address-forwarding="true"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<access-log prefix="access"/>
</host>
</server>
Or, for a bit of automation, you could use the the CLI against your running instance:
$JBOSS_HOME/bin/jboss-cli.sh --connect --command="/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=proxy-address-forwarding, value=true)"
For those interested in understanding the source code, check out the io.undertow.server.handlers.ProxyPeerAddressHandler class here.
Outcome
The result of this is that calls to HttpServletRequest.getScheme() will return “https” for requests that have had the SSL offloaded by the ELB. Nice.
And now HttpServletRequest.isSecure() returns as expected as well.