Summary
-------
Introduce an API on `java.net.http.HttpClient.Builder` interface to allow users to specify a particular local address to bind to.
Problem
-------
Applications use `java.net.http.HttpClient`, typically built using a `HttpClient.newBuilder()` to issue HTTP requests. Such requests internally create instance(s) of `java.nio.channels.SocketChannel` to communicate with the target server(s). The sockets of such `SocketChannel` instances currently bind to automatically assigned socket address. Applications do not have control over which address will be chosen to bind to on multi-homed systems. This enhancement proposes to allow applications to optionally choose which address to bind to.
Solution
--------
A new API is introduced on `HttpClient.Builder`:
public interface Builder {
...
+ /**
+ * Binds the socket to this local address when creating
+ * connections for sending requests.
+ *
+ * <p> If no local address is set or {@code null} is passed
+ * to this method then sockets created by the
+ * HTTP client will be bound to an automatically
+ * assigned socket address.
+ *
+ * <p> Common usages of the {@code HttpClient} do not require
+ * this method to be called. Setting a local address, through this
+ * method, is only for advanced usages where users of the {@code HttpClient}
+ * require specific control on which network interface gets used
+ * for the HTTP communication. Callers of this method are expected to
+ * be aware of the networking configurations of the system where the
+ * {@code HttpClient} will be used and care should be taken to ensure the
+ * correct {@code localAddr} is passed. Failure to do so can result in
+ * requests sent through the {@code HttpClient} to fail.
+ *
+ * @implSpec The default implementation of this method throws
+ * {@code UnsupportedOperationException}. {@code Builder}s obtained
+ * through {@link HttpClient#newBuilder()} provide an implementation
+ * of this method that allows setting the local address.
+ *
+ * @param localAddr The local address of the socket. Can be null.
+ * @return this builder
+ * @throws UnsupportedOperationException if this builder doesn't support
+ * configuring a local address or if the passed {@code localAddr}
+ * is not supported by this {@code HttpClient} implementation.
+ * @since 19
+ */
+ default Builder localAddress(InetAddress localAddr) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Returns a new {@link HttpClient} built from the current state of this
* builder.
*
+ * @implSpec If the {@link #localAddress(InetAddress) local address} is
+ * a non-null address and a security manager is installed, then
+ * this method calls {@link SecurityManager#checkListen checkListen} to
+ * check that the caller has necessary permission to bind to that local address.
+ *
* @return a new {@code HttpClient}
*
* @throws UncheckedIOException may be thrown if underlying IO resources
* required by the implementation cannot be allocated. For instance,
* if the implementation requires a {@link Selector}, and opening
* one fails due to {@linkplain Selector#open() lack of necessary resources}.
+ * @throws SecurityException If a security manager has been installed and the
+ * security manager's {@link SecurityManager#checkListen checkListen}
+ * method disallows binding to the given address.
*/
public HttpClient build();
Specification
-------------
See solution section also the auto-generated webrev for this enhancement, details the exact changes https://openjdk.github.io/cr/?repo=jdk&pr=6690&range=18#udiff-1-src/java.net.http/share/classes/java/net/http/HttpClient.java