44 private final HttpHeaders userHeaders; |
46 private final HttpHeaders userHeaders; |
45 private final HttpHeadersImpl systemHeaders; |
47 private final HttpHeadersImpl systemHeaders; |
46 private final URI uri; |
48 private final URI uri; |
47 private InetSocketAddress authority; // only used when URI not specified |
49 private InetSocketAddress authority; // only used when URI not specified |
48 private final String method; |
50 private final String method; |
49 final BodyProcessor requestProcessor; |
51 final BodyPublisher requestPublisher; |
50 final boolean secure; |
52 final boolean secure; |
51 final boolean expectContinue; |
53 final boolean expectContinue; |
52 private boolean isWebSocket; |
54 private boolean isWebSocket; |
53 private AccessControlContext acc; |
55 private AccessControlContext acc; |
54 private final Duration duration; |
56 private final Duration timeout; // may be null |
55 private final Optional<HttpClient.Version> version; |
57 private final Optional<HttpClient.Version> version; |
56 |
58 |
57 /** |
59 /** |
58 * Creates an HttpRequestImpl from the given builder. |
60 * Creates an HttpRequestImpl from the given builder. |
59 */ |
61 */ |
60 public HttpRequestImpl(HttpRequestBuilderImpl builder) { |
62 public HttpRequestImpl(HttpRequestBuilderImpl builder) { |
61 String method = builder.method(); |
63 String method = builder.method(); |
62 this.method = method == null? "GET" : method; |
64 this.method = method == null ? "GET" : method; |
63 this.userHeaders = ImmutableHeaders.of(builder.headers().map(), ALLOWED_HEADERS); |
65 this.userHeaders = ImmutableHeaders.of(builder.headers().map(), ALLOWED_HEADERS); |
64 this.systemHeaders = new HttpHeadersImpl(); |
66 this.systemHeaders = new HttpHeadersImpl(); |
65 this.uri = builder.uri(); |
67 this.uri = builder.uri(); |
|
68 assert uri != null; |
66 this.expectContinue = builder.expectContinue(); |
69 this.expectContinue = builder.expectContinue(); |
67 this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https"); |
70 this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https"); |
68 if (builder.body() == null) { |
71 this.requestPublisher = builder.bodyPublisher(); // may be null |
69 this.requestProcessor = HttpRequest.noBody(); |
72 this.timeout = builder.timeout(); |
70 } else { |
|
71 this.requestProcessor = builder.body(); |
|
72 } |
|
73 this.duration = builder.duration(); |
|
74 this.version = builder.version(); |
73 this.version = builder.version(); |
75 } |
74 } |
76 |
75 |
77 /** |
76 /** |
78 * Creates an HttpRequestImpl from the given request. |
77 * Creates an HttpRequestImpl from the given request. |
79 */ |
78 */ |
80 public HttpRequestImpl(HttpRequest request) { |
79 public HttpRequestImpl(HttpRequest request, AccessControlContext acc) { |
81 String method = request.method(); |
80 String method = request.method(); |
82 this.method = method == null? "GET" : method; |
81 this.method = method == null ? "GET" : method; |
83 this.userHeaders = request.headers(); |
82 this.userHeaders = request.headers(); |
84 if (request instanceof HttpRequestImpl) { |
83 if (request instanceof HttpRequestImpl) { |
85 this.systemHeaders = ((HttpRequestImpl) request).systemHeaders; |
84 this.systemHeaders = ((HttpRequestImpl) request).systemHeaders; |
86 this.isWebSocket = ((HttpRequestImpl) request).isWebSocket; |
85 this.isWebSocket = ((HttpRequestImpl) request).isWebSocket; |
87 } else { |
86 } else { |
88 this.systemHeaders = new HttpHeadersImpl(); |
87 this.systemHeaders = new HttpHeadersImpl(); |
89 } |
88 } |
90 this.uri = request.uri(); |
89 this.uri = request.uri(); |
91 this.expectContinue = request.expectContinue(); |
90 this.expectContinue = request.expectContinue(); |
92 this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https"); |
91 this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https"); |
93 if (!request.bodyProcessor().isPresent()) { |
92 this.requestPublisher = request.bodyPublisher().orElse(null); |
94 this.requestProcessor = HttpRequest.noBody(); |
93 if (acc != null && requestPublisher instanceof RequestPublishers.FilePublisher) { |
95 } else { |
94 // Restricts the file publisher with the senders ACC, if any |
96 this.requestProcessor = request.bodyProcessor().get(); |
95 ((RequestPublishers.FilePublisher)requestPublisher).setAccessControlContext(acc); |
97 } |
96 } |
98 this.duration = request.duration(); |
97 this.timeout = request.timeout().orElse(null); |
99 this.version = request.version(); |
98 this.version = request.version(); |
100 } |
99 } |
101 |
100 |
102 /** Creates a HttpRequestImpl using fields of an existing request impl. */ |
101 /** Creates a HttpRequestImpl using fields of an existing request impl. */ |
103 public HttpRequestImpl(URI uri, |
102 public HttpRequestImpl(URI uri, |
108 this.isWebSocket = other.isWebSocket; |
107 this.isWebSocket = other.isWebSocket; |
109 this.systemHeaders = other.systemHeaders; |
108 this.systemHeaders = other.systemHeaders; |
110 this.uri = uri; |
109 this.uri = uri; |
111 this.expectContinue = other.expectContinue; |
110 this.expectContinue = other.expectContinue; |
112 this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https"); |
111 this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https"); |
113 this.requestProcessor = other.requestProcessor; |
112 this.requestPublisher = other.requestPublisher; // may be null |
114 this.acc = other.acc; |
113 this.acc = other.acc; |
115 this.duration = other.duration; |
114 this.timeout = other.timeout; |
116 this.version = other.version(); |
115 this.version = other.version(); |
117 } |
116 } |
118 |
117 |
119 /* used for creating CONNECT requests */ |
118 /* used for creating CONNECT requests */ |
120 HttpRequestImpl(String method, HttpClientImpl client, |
119 HttpRequestImpl(String method, InetSocketAddress authority) { |
121 InetSocketAddress authority) { |
|
122 // TODO: isWebSocket flag is not specified, but the assumption is that |
120 // TODO: isWebSocket flag is not specified, but the assumption is that |
123 // such a request will never be made on a connection that will be returned |
121 // such a request will never be made on a connection that will be returned |
124 // to the connection pool (we might need to revisit this constructor later) |
122 // to the connection pool (we might need to revisit this constructor later) |
125 this.method = method; |
123 this.method = method; |
126 this.systemHeaders = new HttpHeadersImpl(); |
124 this.systemHeaders = new HttpHeadersImpl(); |
127 this.userHeaders = ImmutableHeaders.empty(); |
125 this.userHeaders = ImmutableHeaders.empty(); |
128 this.uri = URI.create("socket://" + authority.getHostString() + ":" + Integer.toString(authority.getPort()) + "/"); |
126 this.uri = URI.create("socket://" + authority.getHostString() + ":" |
129 this.requestProcessor = HttpRequest.noBody(); |
127 + Integer.toString(authority.getPort()) + "/"); |
|
128 this.requestPublisher = null; |
130 this.authority = authority; |
129 this.authority = authority; |
131 this.secure = false; |
130 this.secure = false; |
132 this.expectContinue = false; |
131 this.expectContinue = false; |
133 this.duration = null; |
132 this.timeout = null; |
134 this.version = Optional.of(client.version()); |
133 // The CONNECT request sent for tunneling is only used in two cases: |
|
134 // 1. websocket, which only supports HTTP/1.1 |
|
135 // 2. SSL tunneling through a HTTP/1.1 proxy |
|
136 // In either case we do not want to upgrade the connection to the proxy. |
|
137 // What we want to possibly upgrade is the tunneled connection to the |
|
138 // target server (so not the CONNECT request itself) |
|
139 this.version = Optional.of(HttpClient.Version.HTTP_1_1); |
135 } |
140 } |
136 |
141 |
137 /** |
142 /** |
138 * Creates a HttpRequestImpl from the given set of Headers and the associated |
143 * Creates a HttpRequestImpl from the given set of Headers and the associated |
139 * "parent" request. Fields not taken from the headers are taken from the |
144 * "parent" request. Fields not taken from the headers are taken from the |
259 @Override |
252 @Override |
260 public void setSystemHeader(String name, String value) { |
253 public void setSystemHeader(String name, String value) { |
261 systemHeaders.setHeader(name, value); |
254 systemHeaders.setHeader(name, value); |
262 } |
255 } |
263 |
256 |
264 // @Override |
257 InetSocketAddress getAddress(HttpClientImpl client) { |
265 // public <T> HttpResponse<T> |
|
266 // response(HttpResponse.BodyHandler<T> responseHandler) |
|
267 // throws IOException, InterruptedException |
|
268 // { |
|
269 // if (!sent.compareAndSet(false, true)) { |
|
270 // throw new IllegalStateException("request already sent"); |
|
271 // } |
|
272 // MultiExchange<Void,T> mex = new MultiExchange<>(this, responseHandler); |
|
273 // return mex.response(); |
|
274 // } |
|
275 // |
|
276 // @Override |
|
277 // public <T> CompletableFuture<HttpResponse<T>> |
|
278 // responseAsync(HttpResponse.BodyHandler<T> responseHandler) |
|
279 // { |
|
280 // if (!sent.compareAndSet(false, true)) { |
|
281 // throw new IllegalStateException("request already sent"); |
|
282 // } |
|
283 // MultiExchange<Void,T> mex = new MultiExchange<>(this, responseHandler); |
|
284 // return mex.responseAsync(null) |
|
285 // .thenApply((HttpResponseImpl<T> b) -> (HttpResponse<T>) b); |
|
286 // } |
|
287 // |
|
288 // @Override |
|
289 // public <U, T> CompletableFuture<U> |
|
290 // multiResponseAsync(HttpResponse.MultiProcessor<U, T> responseHandler) |
|
291 // { |
|
292 // if (!sent.compareAndSet(false, true)) { |
|
293 // throw new IllegalStateException("request already sent"); |
|
294 // } |
|
295 // MultiExchange<U,T> mex = new MultiExchange<>(this, responseHandler); |
|
296 // return mex.multiResponseAsync(); |
|
297 // } |
|
298 |
|
299 public InetSocketAddress getAddress(HttpClientImpl client) { |
|
300 URI uri = uri(); |
258 URI uri = uri(); |
301 if (uri == null) { |
259 if (uri == null) { |
302 return authority(); |
260 return authority(); |
303 } |
261 } |
304 int port = uri.getPort(); |
262 int p = uri.getPort(); |
305 if (port == -1) { |
263 if (p == -1) { |
306 if (uri.getScheme().equalsIgnoreCase("https")) { |
264 if (uri.getScheme().equalsIgnoreCase("https")) { |
307 port = 443; |
265 p = 443; |
308 } else { |
266 } else { |
309 port = 80; |
267 p = 80; |
310 } |
268 } |
311 } |
269 } |
312 String host = uri.getHost(); |
270 final String host = uri.getHost(); |
|
271 final int port = p; |
313 if (proxy(client) == null) { |
272 if (proxy(client) == null) { |
314 return new InetSocketAddress(host, port); |
273 PrivilegedAction<InetSocketAddress> pa = () -> new InetSocketAddress(host, port); |
|
274 return AccessController.doPrivileged(pa); |
315 } else { |
275 } else { |
316 return InetSocketAddress.createUnresolved(host, port); |
276 return InetSocketAddress.createUnresolved(host, port); |
317 } |
277 } |
318 } |
278 } |
319 } |
279 } |