42 import java.nio.channels.Selector; |
42 import java.nio.channels.Selector; |
43 import java.nio.channels.SocketChannel; |
43 import java.nio.channels.SocketChannel; |
44 import java.security.AccessControlContext; |
44 import java.security.AccessControlContext; |
45 import java.security.AccessController; |
45 import java.security.AccessController; |
46 import java.security.NoSuchAlgorithmException; |
46 import java.security.NoSuchAlgorithmException; |
|
47 import java.security.PrivilegedAction; |
47 import java.time.Instant; |
48 import java.time.Instant; |
48 import java.time.temporal.ChronoUnit; |
49 import java.time.temporal.ChronoUnit; |
49 import java.util.ArrayList; |
50 import java.util.ArrayList; |
50 import java.util.HashSet; |
51 import java.util.HashSet; |
51 import java.util.Iterator; |
52 import java.util.Iterator; |
52 import java.util.List; |
53 import java.util.List; |
53 import java.util.Optional; |
54 import java.util.Optional; |
54 import java.util.Set; |
55 import java.util.Set; |
55 import java.util.TreeSet; |
56 import java.util.TreeSet; |
56 import java.util.concurrent.CompletableFuture; |
57 import java.util.concurrent.CompletableFuture; |
57 import java.util.concurrent.CompletionException; |
|
58 import java.util.concurrent.ExecutionException; |
58 import java.util.concurrent.ExecutionException; |
59 import java.util.concurrent.Executor; |
59 import java.util.concurrent.Executor; |
60 import java.util.concurrent.Executors; |
60 import java.util.concurrent.Executors; |
61 import java.util.concurrent.ThreadFactory; |
61 import java.util.concurrent.ThreadFactory; |
62 import java.util.concurrent.atomic.AtomicInteger; |
62 import java.util.concurrent.atomic.AtomicInteger; |
112 } |
112 } |
113 } |
113 } |
114 |
114 |
115 private final CookieHandler cookieHandler; |
115 private final CookieHandler cookieHandler; |
116 private final Redirect followRedirects; |
116 private final Redirect followRedirects; |
|
117 private final Optional<ProxySelector> userProxySelector; |
117 private final ProxySelector proxySelector; |
118 private final ProxySelector proxySelector; |
118 private final Authenticator authenticator; |
119 private final Authenticator authenticator; |
119 private final Version version; |
120 private final Version version; |
120 private final ConnectionPool connections; |
121 private final ConnectionPool connections; |
121 private final Executor executor; |
122 private final Executor executor; |
229 client2 = new Http2ClientImpl(this); |
230 client2 = new Http2ClientImpl(this); |
230 executor = ex; |
231 executor = ex; |
231 cookieHandler = builder.cookieHandler; |
232 cookieHandler = builder.cookieHandler; |
232 followRedirects = builder.followRedirects == null ? |
233 followRedirects = builder.followRedirects == null ? |
233 Redirect.NEVER : builder.followRedirects; |
234 Redirect.NEVER : builder.followRedirects; |
234 this.proxySelector = builder.proxy; |
235 this.userProxySelector = Optional.ofNullable(builder.proxy); |
|
236 this.proxySelector = userProxySelector |
|
237 .orElseGet(HttpClientImpl::getDefaultProxySelector); |
|
238 debug.log(Level.DEBUG, "proxySelector is %s (user-supplied=%s)", |
|
239 this.proxySelector, userProxySelector.isPresent()); |
235 authenticator = builder.authenticator; |
240 authenticator = builder.authenticator; |
236 if (builder.version == null) { |
241 if (builder.version == null) { |
237 version = HttpClient.Version.HTTP_2; |
242 version = HttpClient.Version.HTTP_2; |
238 } else { |
243 } else { |
239 version = builder.version; |
244 version = builder.version; |
275 |
280 |
276 private static SSLParameters getDefaultParams(SSLContext ctx) { |
281 private static SSLParameters getDefaultParams(SSLContext ctx) { |
277 SSLParameters params = ctx.getSupportedSSLParameters(); |
282 SSLParameters params = ctx.getSupportedSSLParameters(); |
278 params.setProtocols(new String[]{"TLSv1.2"}); |
283 params.setProtocols(new String[]{"TLSv1.2"}); |
279 return params; |
284 return params; |
|
285 } |
|
286 |
|
287 private static ProxySelector getDefaultProxySelector() { |
|
288 PrivilegedAction<ProxySelector> action = ProxySelector::getDefault; |
|
289 return AccessController.doPrivileged(action); |
280 } |
290 } |
281 |
291 |
282 // Returns the facade that was returned to the application code. |
292 // Returns the facade that was returned to the application code. |
283 // May be null if that facade is no longer referenced. |
293 // May be null if that facade is no longer referenced. |
284 final HttpClientFacade facade() { |
294 final HttpClientFacade facade() { |
904 return Optional.ofNullable(cookieHandler); |
914 return Optional.ofNullable(cookieHandler); |
905 } |
915 } |
906 |
916 |
907 @Override |
917 @Override |
908 public Optional<ProxySelector> proxy() { |
918 public Optional<ProxySelector> proxy() { |
909 return Optional.ofNullable(this.proxySelector); |
919 return this.userProxySelector; |
|
920 } |
|
921 |
|
922 // Return the effective proxy that this client uses. |
|
923 ProxySelector proxySelector() { |
|
924 return proxySelector; |
910 } |
925 } |
911 |
926 |
912 @Override |
927 @Override |
913 public WebSocket.Builder newWebSocketBuilder(URI uri, |
928 public WebSocket.Builder newWebSocketBuilder(URI uri, |
914 WebSocket.Listener listener) { |
929 WebSocket.Listener listener) { |
915 // Make sure to pass the HttpClientFacade to the web socket builder. |
930 // Make sure to pass the HttpClientFacade to the web socket builder. |
916 // This will ensure that the facade is not released before the |
931 // This will ensure that the facade is not released before the |
917 // WebSocket has been created, at which point the pendingOperationCount |
932 // WebSocket has been created, at which point the pendingOperationCount |
918 // will have been incremented by the DetachedConnectionChannel |
933 // will have been incremented by the DetachedConnectionChannel |
919 // (see PlainHttpConnection.detachChannel()) |
934 // (see PlainHttpConnection.detachChannel()) |
920 return new BuilderImpl(this.facade(), uri, listener); |
935 return new BuilderImpl(this.facade(), uri, listener, proxySelector); |
921 } |
936 } |
922 |
937 |
923 @Override |
938 @Override |
924 public Version version() { |
939 public Version version() { |
925 return version; |
940 return version; |
933 public String toString() { |
948 public String toString() { |
934 // Used by tests to get the client's id and compute the |
949 // Used by tests to get the client's id and compute the |
935 // name of the SelectorManager thread. |
950 // name of the SelectorManager thread. |
936 return super.toString() + ("(" + id + ")"); |
951 return super.toString() + ("(" + id + ")"); |
937 } |
952 } |
938 |
|
939 //private final HashMap<String, Boolean> http2NotSupported = new HashMap<>(); |
|
940 |
|
941 // boolean getHttp2Allowed() { |
|
942 // return version.equals(Version.HTTP_2); |
|
943 // } |
|
944 |
953 |
945 private void initFilters() { |
954 private void initFilters() { |
946 addFilter(AuthenticationFilter.class); |
955 addFilter(AuthenticationFilter.class); |
947 addFilter(RedirectFilter.class); |
956 addFilter(RedirectFilter.class); |
948 if (this.cookieHandler != null) { |
957 if (this.cookieHandler != null) { |