Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
41171 views
1
/*
2
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package jdk.internal.net.http;
27
28
import java.io.IOException;
29
import java.net.InetSocketAddress;
30
import java.net.Proxy;
31
import java.net.ProxySelector;
32
import java.net.URI;
33
import java.security.AccessControlContext;
34
import java.security.AccessController;
35
import java.security.PrivilegedAction;
36
import java.time.Duration;
37
import java.util.List;
38
import java.util.Locale;
39
import java.util.Objects;
40
import java.util.Optional;
41
import java.net.http.HttpClient;
42
import java.net.http.HttpHeaders;
43
import java.net.http.HttpRequest;
44
45
import jdk.internal.net.http.common.HttpHeadersBuilder;
46
import jdk.internal.net.http.common.Utils;
47
import jdk.internal.net.http.websocket.OpeningHandshake;
48
import jdk.internal.net.http.websocket.WebSocketRequest;
49
50
import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
51
import static jdk.internal.net.http.common.Utils.ProxyHeaders;
52
53
public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
54
55
private final HttpHeaders userHeaders;
56
private final HttpHeadersBuilder systemHeadersBuilder;
57
private final URI uri;
58
private volatile Proxy proxy; // ensure safe publishing
59
private final InetSocketAddress authority; // only used when URI not specified
60
private final String method;
61
final BodyPublisher requestPublisher;
62
final boolean secure;
63
final boolean expectContinue;
64
private volatile boolean isWebSocket;
65
@SuppressWarnings("removal")
66
private volatile AccessControlContext acc;
67
private final Duration timeout; // may be null
68
private final Optional<HttpClient.Version> version;
69
70
private static String userAgent() {
71
PrivilegedAction<String> pa = () -> System.getProperty("java.version");
72
@SuppressWarnings("removal")
73
String version = AccessController.doPrivileged(pa);
74
return "Java-http-client/" + version;
75
}
76
77
/** The value of the User-Agent header for all requests sent by the client. */
78
public static final String USER_AGENT = userAgent();
79
80
/**
81
* Creates an HttpRequestImpl from the given builder.
82
*/
83
public HttpRequestImpl(HttpRequestBuilderImpl builder) {
84
String method = builder.method();
85
this.method = method == null ? "GET" : method;
86
this.userHeaders = HttpHeaders.of(builder.headersBuilder().map(), ALLOWED_HEADERS);
87
this.systemHeadersBuilder = new HttpHeadersBuilder();
88
this.uri = builder.uri();
89
assert uri != null;
90
this.proxy = null;
91
this.expectContinue = builder.expectContinue();
92
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
93
this.requestPublisher = builder.bodyPublisher(); // may be null
94
this.timeout = builder.timeout();
95
this.version = builder.version();
96
this.authority = null;
97
}
98
99
/**
100
* Creates an HttpRequestImpl from the given request.
101
*/
102
public HttpRequestImpl(HttpRequest request, ProxySelector ps) {
103
String method = request.method();
104
if (method != null && !Utils.isValidName(method))
105
throw new IllegalArgumentException("illegal method \""
106
+ method.replace("\n","\\n")
107
.replace("\r", "\\r")
108
.replace("\t", "\\t")
109
+ "\"");
110
URI requestURI = Objects.requireNonNull(request.uri(),
111
"uri must be non null");
112
Duration timeout = request.timeout().orElse(null);
113
this.method = method == null ? "GET" : method;
114
this.userHeaders = HttpHeaders.of(request.headers().map(), Utils.VALIDATE_USER_HEADER);
115
if (request instanceof HttpRequestImpl) {
116
// all cases exception WebSocket should have a new system headers
117
this.isWebSocket = ((HttpRequestImpl) request).isWebSocket;
118
if (isWebSocket) {
119
this.systemHeadersBuilder = ((HttpRequestImpl)request).systemHeadersBuilder;
120
} else {
121
this.systemHeadersBuilder = new HttpHeadersBuilder();
122
}
123
} else {
124
HttpRequestBuilderImpl.checkURI(requestURI);
125
checkTimeout(timeout);
126
this.systemHeadersBuilder = new HttpHeadersBuilder();
127
}
128
if (!userHeaders.firstValue("User-Agent").isPresent()) {
129
this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
130
}
131
this.uri = requestURI;
132
if (isWebSocket) {
133
// WebSocket determines and sets the proxy itself
134
this.proxy = ((HttpRequestImpl) request).proxy;
135
} else {
136
if (ps != null)
137
this.proxy = retrieveProxy(ps, uri);
138
else
139
this.proxy = null;
140
}
141
this.expectContinue = request.expectContinue();
142
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
143
this.requestPublisher = request.bodyPublisher().orElse(null);
144
this.timeout = timeout;
145
this.version = request.version();
146
this.authority = null;
147
}
148
149
private static void checkTimeout(Duration duration) {
150
if (duration != null) {
151
if (duration.isNegative() || Duration.ZERO.equals(duration))
152
throw new IllegalArgumentException("Invalid duration: " + duration);
153
}
154
}
155
156
/** Returns a new instance suitable for redirection. */
157
public static HttpRequestImpl newInstanceForRedirection(URI uri,
158
String method,
159
HttpRequestImpl other,
160
boolean mayHaveBody) {
161
return new HttpRequestImpl(uri, method, other, mayHaveBody);
162
}
163
164
/** Returns a new instance suitable for authentication. */
165
public static HttpRequestImpl newInstanceForAuthentication(HttpRequestImpl other) {
166
HttpRequestImpl request = new HttpRequestImpl(other.uri(), other.method(), other, true);
167
if (request.isWebSocket()) {
168
Utils.setWebSocketUpgradeHeaders(request);
169
}
170
return request;
171
}
172
173
/**
174
* Creates a HttpRequestImpl using fields of an existing request impl.
175
* The newly created HttpRequestImpl does not copy the system headers.
176
*/
177
private HttpRequestImpl(URI uri,
178
String method,
179
HttpRequestImpl other,
180
boolean mayHaveBody) {
181
assert method == null || Utils.isValidName(method);
182
this.method = method == null? "GET" : method;
183
this.userHeaders = other.userHeaders;
184
this.isWebSocket = other.isWebSocket;
185
this.systemHeadersBuilder = new HttpHeadersBuilder();
186
if (!userHeaders.firstValue("User-Agent").isPresent()) {
187
this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
188
}
189
this.uri = uri;
190
this.proxy = other.proxy;
191
this.expectContinue = other.expectContinue;
192
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
193
this.requestPublisher = mayHaveBody ? publisher(other) : null; // may be null
194
this.acc = other.acc;
195
this.timeout = other.timeout;
196
this.version = other.version();
197
this.authority = null;
198
}
199
200
private BodyPublisher publisher(HttpRequestImpl other) {
201
BodyPublisher res = other.requestPublisher;
202
if (!Objects.equals(method, other.method)) {
203
res = null;
204
}
205
return res;
206
}
207
208
/* used for creating CONNECT requests */
209
HttpRequestImpl(String method, InetSocketAddress authority, ProxyHeaders headers) {
210
// TODO: isWebSocket flag is not specified, but the assumption is that
211
// such a request will never be made on a connection that will be returned
212
// to the connection pool (we might need to revisit this constructor later)
213
assert "CONNECT".equalsIgnoreCase(method);
214
this.method = method;
215
this.systemHeadersBuilder = new HttpHeadersBuilder();
216
this.systemHeadersBuilder.map().putAll(headers.systemHeaders().map());
217
this.userHeaders = headers.userHeaders();
218
this.uri = URI.create("socket://" + authority.getHostString() + ":"
219
+ Integer.toString(authority.getPort()) + "/");
220
this.proxy = null;
221
this.requestPublisher = null;
222
this.authority = authority;
223
this.secure = false;
224
this.expectContinue = false;
225
this.timeout = null;
226
// The CONNECT request sent for tunneling is only used in two cases:
227
// 1. websocket, which only supports HTTP/1.1
228
// 2. SSL tunneling through a HTTP/1.1 proxy
229
// In either case we do not want to upgrade the connection to the proxy.
230
// What we want to possibly upgrade is the tunneled connection to the
231
// target server (so not the CONNECT request itself)
232
this.version = Optional.of(HttpClient.Version.HTTP_1_1);
233
}
234
235
final boolean isConnect() {
236
return "CONNECT".equalsIgnoreCase(method);
237
}
238
239
/**
240
* Creates a HttpRequestImpl from the given set of Headers and the associated
241
* "parent" request. Fields not taken from the headers are taken from the
242
* parent.
243
*/
244
static HttpRequestImpl createPushRequest(HttpRequestImpl parent,
245
HttpHeaders headers)
246
throws IOException
247
{
248
return new HttpRequestImpl(parent, headers);
249
}
250
251
// only used for push requests
252
private HttpRequestImpl(HttpRequestImpl parent, HttpHeaders headers)
253
throws IOException
254
{
255
this.method = headers.firstValue(":method")
256
.orElseThrow(() -> new IOException("No method in Push Promise"));
257
String path = headers.firstValue(":path")
258
.orElseThrow(() -> new IOException("No path in Push Promise"));
259
String scheme = headers.firstValue(":scheme")
260
.orElseThrow(() -> new IOException("No scheme in Push Promise"));
261
String authority = headers.firstValue(":authority")
262
.orElseThrow(() -> new IOException("No authority in Push Promise"));
263
StringBuilder sb = new StringBuilder();
264
sb.append(scheme).append("://").append(authority).append(path);
265
this.uri = URI.create(sb.toString());
266
this.proxy = null;
267
this.userHeaders = HttpHeaders.of(headers.map(), ALLOWED_HEADERS);
268
this.systemHeadersBuilder = parent.systemHeadersBuilder;
269
this.expectContinue = parent.expectContinue;
270
this.secure = parent.secure;
271
this.requestPublisher = parent.requestPublisher;
272
this.acc = parent.acc;
273
this.timeout = parent.timeout;
274
this.version = parent.version;
275
this.authority = null;
276
}
277
278
@Override
279
public String toString() {
280
return (uri == null ? "" : uri.toString()) + " " + method;
281
}
282
283
@Override
284
public HttpHeaders headers() {
285
return userHeaders;
286
}
287
288
InetSocketAddress authority() { return authority; }
289
290
void setH2Upgrade(Http2ClientImpl h2client) {
291
systemHeadersBuilder.setHeader("Connection", "Upgrade, HTTP2-Settings");
292
systemHeadersBuilder.setHeader("Upgrade", "h2c");
293
systemHeadersBuilder.setHeader("HTTP2-Settings", h2client.getSettingsString());
294
}
295
296
@Override
297
public boolean expectContinue() { return expectContinue; }
298
299
/** Retrieves the proxy, from the given ProxySelector, if there is one. */
300
private static Proxy retrieveProxy(ProxySelector ps, URI uri) {
301
Proxy proxy = null;
302
List<Proxy> pl = ps.select(uri);
303
if (!pl.isEmpty()) {
304
Proxy p = pl.get(0);
305
if (p.type() == Proxy.Type.HTTP)
306
proxy = p;
307
}
308
return proxy;
309
}
310
311
InetSocketAddress proxy() {
312
if (proxy == null || proxy.type() != Proxy.Type.HTTP
313
|| method.equalsIgnoreCase("CONNECT")) {
314
return null;
315
}
316
return (InetSocketAddress)proxy.address();
317
}
318
319
boolean secure() { return secure; }
320
321
@Override
322
public void setProxy(Proxy proxy) {
323
assert isWebSocket;
324
this.proxy = proxy;
325
}
326
327
@Override
328
public void isWebSocket(boolean is) {
329
isWebSocket = is;
330
}
331
332
boolean isWebSocket() {
333
return isWebSocket;
334
}
335
336
@Override
337
public Optional<BodyPublisher> bodyPublisher() {
338
return requestPublisher == null ? Optional.empty()
339
: Optional.of(requestPublisher);
340
}
341
342
/**
343
* Returns the request method for this request. If not set explicitly,
344
* the default method for any request is "GET".
345
*/
346
@Override
347
public String method() { return method; }
348
349
@Override
350
public URI uri() { return uri; }
351
352
@Override
353
public Optional<Duration> timeout() {
354
return timeout == null ? Optional.empty() : Optional.of(timeout);
355
}
356
357
HttpHeaders getUserHeaders() { return userHeaders; }
358
359
HttpHeadersBuilder getSystemHeadersBuilder() { return systemHeadersBuilder; }
360
361
@Override
362
public Optional<HttpClient.Version> version() { return version; }
363
364
void addSystemHeader(String name, String value) {
365
systemHeadersBuilder.addHeader(name, value);
366
}
367
368
@Override
369
public void setSystemHeader(String name, String value) {
370
systemHeadersBuilder.setHeader(name, value);
371
}
372
373
@SuppressWarnings("removal")
374
InetSocketAddress getAddress() {
375
URI uri = uri();
376
if (uri == null) {
377
return authority();
378
}
379
int p = uri.getPort();
380
if (p == -1) {
381
if (uri.getScheme().equalsIgnoreCase("https")) {
382
p = 443;
383
} else {
384
p = 80;
385
}
386
}
387
final String host = uri.getHost();
388
final int port = p;
389
if (proxy() == null) {
390
PrivilegedAction<InetSocketAddress> pa = () -> new InetSocketAddress(host, port);
391
return AccessController.doPrivileged(pa);
392
} else {
393
return InetSocketAddress.createUnresolved(host, port);
394
}
395
}
396
}
397
398