- Requested URI Discovery
Control how Helidon uses
ForwardedandX-Forwarded-*headers on incoming requests and write application code to obtain consistent and trusted information from those headers.
Requested URI Discovery
Proxies and reverse proxies between an HTTP client and your Helidon application mask important information (for example Host header, originating IP address, protocol) about the request the client sent. Fortunately, many of these intermediary network nodes set or update either the standard HTTP Forwarded header or the non-standard X-Forwarded-* family of headers to preserve information about the original client request.
Helidon’s requested URI discovery feature allows your application—and Helidon itself—to reconstruct information about the original request using the Forwarded header and the X-Forwarded-* family of headers.
When you prepare the sockets in your server you can include the following optional requested URI discovery settings:
enabled or disabled
which type or types of requested URI discovery to use:
FORWARDED- uses theForwardedheaderX_FORWARDED- uses theX-Forwarded-*headersHOST- uses theHostheader
what intermediate nodes to trust
When your application invokes request.requestedUri() Helidon iterates through the discovery types you set up for the receiving socket, gathering information from the corresponding header(s) for that type. If the request does not have the corresponding header(s), or your settings do not trust the intermediate nodes reflected in those headers, then Helidon tries the next discovery type you set up. Helidon uses the HOST discovery type if you do not set up discovery yourself or if, for a particular request, it cannot assemble the request information using any discovery type you did set up for the socket.
Setting Up Requested URI Discovery Programmatically
To set up requested URI discovery on the default socket for your server, use the WebServer.Builder:
import io.helidon.common.configurable.AllowList;
import static io.helidon.webserver.SocketConfiguration.RequestedUriDiscoveryType.FORWARDED;
import static io.helidon.webserver.SocketConfiguration.RequestedUriDiscoveryType.X_FORWARDED;
AllowList trustedProxies = AllowList.builder()
.addAllowedPattern(Pattern.compile("lb.+\\.mycorp\\.com"))
.addDenied("lbtest.mycorp.com")
.build();
WebServer.Builder builder = WebServer.builder()
.defaultSocket(s -> s
.host("localhost")
.port(0)
.requestedUriDiscoveryTypes(List.of(FORWARDED, X_FORWARDED))
.trustedProxies(trustedProxies))
.addRouting(yourRouting)
.config(serverConfig);- Create the
AllowListdescribing the intermediate networks nodes to trust and not trust. Presumably thelbxxx.mycorp.comnodes are trusted load balancers except for the test load balancerlbtest, and no other nodes are trusted.AllowListaccepts prefixes, suffixes, predicates, regex patterns, and exact matches. See theAllowListJavaDoc for complete information. - Use
Forwardedfirst, then tryX-Forwarded-*on each request. - Set the
AllowListfor trusted intermediaries.
If you build your server with additional sockets, you can control requested URI discovery separately for each.
Setting Up Requested URI Discovery using Configuration
You can also use configuration to set up the requested URI discovery behavior. The following example replicates the settings assigned programmatically in the earlier code example:
server:
port: 0
requested-uri-discovery:
types: FORWARDED,X_FORWARDED
trusted-proxies:
allow:
pattern: "lb.*\\.mycorp\\.com"
deny:
exact: "lbtest.mycorp.com""Obtaining the Requested URI Information
Your code obtains the requested URI information from the Helidon server request object:
import io.helidon.common.http.UriInfo;
public class MyHandler implements Handler {
@Override
public void accept(ServerRequest req, ServerResponse res) {
UriInfo uriInfo = req.requestedUri();
// ...
}
}See the UriInfo JavaDoc for more information.