38 import java.util.TreeMap; |
38 import java.util.TreeMap; |
39 import java.util.concurrent.CompletableFuture; |
39 import java.util.concurrent.CompletableFuture; |
40 import java.util.concurrent.CompletionStage; |
40 import java.util.concurrent.CompletionStage; |
41 import java.util.concurrent.ConcurrentLinkedDeque; |
41 import java.util.concurrent.ConcurrentLinkedDeque; |
42 import java.util.concurrent.Flow; |
42 import java.util.concurrent.Flow; |
|
43 import java.util.function.BiPredicate; |
43 import java.util.function.Predicate; |
44 import java.util.function.Predicate; |
44 import jdk.incubator.http.HttpClient.Version; |
45 import jdk.incubator.http.HttpClient.Version; |
45 import jdk.incubator.http.internal.common.Demand; |
46 import jdk.incubator.http.internal.common.Demand; |
46 import jdk.incubator.http.internal.common.FlowTube; |
47 import jdk.incubator.http.internal.common.FlowTube; |
47 import jdk.incubator.http.internal.common.SequentialScheduler; |
48 import jdk.incubator.http.internal.common.SequentialScheduler; |
216 String[] alpn, |
217 String[] alpn, |
217 HttpRequestImpl request, |
218 HttpRequestImpl request, |
218 HttpClientImpl client) { |
219 HttpClientImpl client) { |
219 if (proxy != null) |
220 if (proxy != null) |
220 return new AsyncSSLTunnelConnection(addr, client, alpn, proxy, |
221 return new AsyncSSLTunnelConnection(addr, client, alpn, proxy, |
221 proxyHeaders(request)); |
222 proxyTunnelHeaders(request)); |
222 else |
223 else |
223 return new AsyncSSLConnection(addr, client, alpn); |
224 return new AsyncSSLConnection(addr, client, alpn); |
|
225 } |
|
226 |
|
227 /** |
|
228 * This method is used to build a filter that will accept or |
|
229 * veto (header-name, value) tuple for transmission on the |
|
230 * wire. |
|
231 * The filter is applied to the headers when sending the headers |
|
232 * to the remote party. |
|
233 * Which tuple is accepted/vetoed depends on: |
|
234 * <pre> |
|
235 * - whether the connection is a tunnel connection |
|
236 * [talking to a server through a proxy tunnel] |
|
237 * - whether the method is CONNECT |
|
238 * [establishing a CONNECT tunnel through a proxy] |
|
239 * - whether the request is using a proxy |
|
240 * (and the connection is not a tunnel) |
|
241 * [talking to a server through a proxy] |
|
242 * - whether the request is a direct connection to |
|
243 * a server (no tunnel, no proxy). |
|
244 * </pre> |
|
245 * @param request |
|
246 * @return |
|
247 */ |
|
248 BiPredicate<String,List<String>> headerFilter(HttpRequestImpl request) { |
|
249 if (isTunnel()) { |
|
250 // talking to a server through a proxy tunnel |
|
251 // don't send proxy-* headers to a plain server |
|
252 assert !request.isConnect(); |
|
253 return Utils.NO_PROXY_HEADERS_FILTER; |
|
254 } else if (request.isConnect()) { |
|
255 // establishing a proxy tunnel |
|
256 // check for proxy tunnel disabled schemes |
|
257 // assert !this.isTunnel(); |
|
258 assert request.proxy() == null; |
|
259 return Utils.PROXY_TUNNEL_FILTER; |
|
260 } else if (request.proxy() != null) { |
|
261 // talking to a server through a proxy (no tunnel) |
|
262 // check for proxy disabled schemes |
|
263 // assert !isTunnel() && !request.isConnect(); |
|
264 return Utils.PROXY_FILTER; |
|
265 } else { |
|
266 // talking to a server directly (no tunnel, no proxy) |
|
267 // don't send proxy-* headers to a plain server |
|
268 // assert request.proxy() == null && !request.isConnect(); |
|
269 return Utils.NO_PROXY_HEADERS_FILTER; |
|
270 } |
224 } |
271 } |
225 |
272 |
226 // Composes a new immutable HttpHeaders that combines the |
273 // Composes a new immutable HttpHeaders that combines the |
227 // user and system header but only keeps those headers that |
274 // user and system header but only keeps those headers that |
228 // start with "proxy-" |
275 // start with "proxy-" |
229 private static HttpHeaders proxyHeaders(HttpRequestImpl request) { |
276 private static HttpHeaders proxyTunnelHeaders(HttpRequestImpl request) { |
230 Map<String, List<String>> combined = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); |
277 Map<String, List<String>> combined = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); |
231 combined.putAll(request.getSystemHeaders().map()); |
278 combined.putAll(request.getSystemHeaders().map()); |
232 combined.putAll(request.headers().map()); // let user override system |
279 combined.putAll(request.headers().map()); // let user override system |
233 // keep only proxy-* |
280 |
234 return ImmutableHeaders.of(combined, Utils.IS_PROXY_HEADER); |
281 // keep only proxy-* - and also strip authorization headers |
|
282 // for disabled schemes |
|
283 return ImmutableHeaders.of(combined, Utils.PROXY_TUNNEL_FILTER); |
235 } |
284 } |
236 |
285 |
237 /* Returns either a plain HTTP connection or a plain tunnelling connection |
286 /* Returns either a plain HTTP connection or a plain tunnelling connection |
238 * for proxied WebSocket */ |
287 * for proxied WebSocket */ |
239 private static HttpConnection getPlainConnection(InetSocketAddress addr, |
288 private static HttpConnection getPlainConnection(InetSocketAddress addr, |
240 InetSocketAddress proxy, |
289 InetSocketAddress proxy, |
241 HttpRequestImpl request, |
290 HttpRequestImpl request, |
242 HttpClientImpl client) { |
291 HttpClientImpl client) { |
243 if (request.isWebSocket() && proxy != null) |
292 if (request.isWebSocket() && proxy != null) |
244 return new PlainTunnelingConnection(addr, proxy, client, |
293 return new PlainTunnelingConnection(addr, proxy, client, |
245 proxyHeaders(request)); |
294 proxyTunnelHeaders(request)); |
246 |
295 |
247 if (proxy == null) |
296 if (proxy == null) |
248 return new PlainHttpConnection(addr, client); |
297 return new PlainHttpConnection(addr, client); |
249 else |
298 else |
250 return new PlainProxyConnection(proxy, client); |
299 return new PlainProxyConnection(proxy, client); |