< prev index next >
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpRequestImpl.java
Print this page
@@ -28,76 +28,88 @@
import jdk.incubator.http.internal.common.HttpHeadersImpl;
import jdk.incubator.http.internal.websocket.WebSocketRequest;
import java.io.IOException;
import java.net.InetSocketAddress;
+import java.net.Proxy;
import java.net.ProxySelector;
import java.net.URI;
import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.time.Duration;
+import java.util.List;
import java.util.Locale;
import java.util.Optional;
import static jdk.incubator.http.internal.common.Utils.ALLOWED_HEADERS;
class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
private final HttpHeaders userHeaders;
private final HttpHeadersImpl systemHeaders;
private final URI uri;
+ private Proxy proxy;
private InetSocketAddress authority; // only used when URI not specified
private final String method;
- final BodyProcessor requestProcessor;
+ final BodyPublisher requestPublisher;
final boolean secure;
final boolean expectContinue;
private boolean isWebSocket;
private AccessControlContext acc;
- private final Duration duration;
+ private final Duration timeout; // may be null
private final Optional<HttpClient.Version> version;
/**
* Creates an HttpRequestImpl from the given builder.
*/
public HttpRequestImpl(HttpRequestBuilderImpl builder) {
String method = builder.method();
- this.method = method == null? "GET" : method;
+ this.method = method == null ? "GET" : method;
this.userHeaders = ImmutableHeaders.of(builder.headers().map(), ALLOWED_HEADERS);
this.systemHeaders = new HttpHeadersImpl();
this.uri = builder.uri();
+ assert uri != null;
+ this.proxy = null;
this.expectContinue = builder.expectContinue();
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
- if (builder.body() == null) {
- this.requestProcessor = HttpRequest.noBody();
- } else {
- this.requestProcessor = builder.body();
- }
- this.duration = builder.duration();
+ this.requestPublisher = builder.bodyPublisher(); // may be null
+ this.timeout = builder.timeout();
this.version = builder.version();
}
/**
* Creates an HttpRequestImpl from the given request.
*/
- public HttpRequestImpl(HttpRequest request) {
+ public HttpRequestImpl(HttpRequest request, ProxySelector ps, AccessControlContext acc) {
String method = request.method();
- this.method = method == null? "GET" : method;
+ this.method = method == null ? "GET" : method;
this.userHeaders = request.headers();
if (request instanceof HttpRequestImpl) {
this.systemHeaders = ((HttpRequestImpl) request).systemHeaders;
this.isWebSocket = ((HttpRequestImpl) request).isWebSocket;
} else {
this.systemHeaders = new HttpHeadersImpl();
}
this.uri = request.uri();
+ if (isWebSocket) {
+ // WebSocket determines and sets the proxy itself
+ this.proxy = ((HttpRequestImpl) request).proxy;
+ } else {
+ if (ps != null)
+ this.proxy = retrieveProxy(ps, uri);
+ else
+ this.proxy = null;
+ }
this.expectContinue = request.expectContinue();
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
- if (!request.bodyProcessor().isPresent()) {
- this.requestProcessor = HttpRequest.noBody();
- } else {
- this.requestProcessor = request.bodyProcessor().get();
+ this.requestPublisher = request.bodyPublisher().orElse(null);
+ if (acc != null && requestPublisher instanceof RequestPublishers.FilePublisher) {
+ // Restricts the file publisher with the senders ACC, if any
+ ((RequestPublishers.FilePublisher)requestPublisher).setAccessControlContext(acc);
}
- this.duration = request.duration();
+ this.timeout = request.timeout().orElse(null);
this.version = request.version();
}
/** Creates a HttpRequestImpl using fields of an existing request impl. */
public HttpRequestImpl(URI uri,
@@ -106,34 +118,42 @@
this.method = method == null? "GET" : method;
this.userHeaders = other.userHeaders;
this.isWebSocket = other.isWebSocket;
this.systemHeaders = other.systemHeaders;
this.uri = uri;
+ this.proxy = other.proxy;
this.expectContinue = other.expectContinue;
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
- this.requestProcessor = other.requestProcessor;
+ this.requestPublisher = other.requestPublisher; // may be null
this.acc = other.acc;
- this.duration = other.duration;
+ this.timeout = other.timeout;
this.version = other.version();
}
/* used for creating CONNECT requests */
- HttpRequestImpl(String method, HttpClientImpl client,
- InetSocketAddress authority) {
+ HttpRequestImpl(String method, InetSocketAddress authority) {
// TODO: isWebSocket flag is not specified, but the assumption is that
// such a request will never be made on a connection that will be returned
// to the connection pool (we might need to revisit this constructor later)
this.method = method;
this.systemHeaders = new HttpHeadersImpl();
this.userHeaders = ImmutableHeaders.empty();
- this.uri = URI.create("socket://" + authority.getHostString() + ":" + Integer.toString(authority.getPort()) + "/");
- this.requestProcessor = HttpRequest.noBody();
+ this.uri = URI.create("socket://" + authority.getHostString() + ":"
+ + Integer.toString(authority.getPort()) + "/");
+ this.proxy = null;
+ this.requestPublisher = null;
this.authority = authority;
this.secure = false;
this.expectContinue = false;
- this.duration = null;
- this.version = Optional.of(client.version());
+ this.timeout = null;
+ // The CONNECT request sent for tunneling is only used in two cases:
+ // 1. websocket, which only supports HTTP/1.1
+ // 2. SSL tunneling through a HTTP/1.1 proxy
+ // In either case we do not want to upgrade the connection to the proxy.
+ // What we want to possibly upgrade is the tunneled connection to the
+ // target server (so not the CONNECT request itself)
+ this.version = Optional.of(HttpClient.Version.HTTP_1_1);
}
/**
* Creates a HttpRequestImpl from the given set of Headers and the associated
* "parent" request. Fields not taken from the headers are taken from the
@@ -159,18 +179,18 @@
String authority = headers.firstValue(":authority")
.orElseThrow(() -> new IOException("No authority in Push Promise"));
StringBuilder sb = new StringBuilder();
sb.append(scheme).append("://").append(authority).append(path);
this.uri = URI.create(sb.toString());
-
+ this.proxy = null;
this.userHeaders = ImmutableHeaders.of(headers.map(), ALLOWED_HEADERS);
this.systemHeaders = parent.systemHeaders;
this.expectContinue = parent.expectContinue;
this.secure = parent.secure;
- this.requestProcessor = parent.requestProcessor;
+ this.requestPublisher = parent.requestPublisher;
this.acc = parent.acc;
- this.duration = parent.duration;
+ this.timeout = parent.timeout;
this.version = parent.version;
}
@Override
public String toString() {
@@ -191,41 +211,51 @@
}
@Override
public boolean expectContinue() { return expectContinue; }
- InetSocketAddress proxy(HttpClientImpl client) {
- ProxySelector ps = client.proxy().orElse(null);
- if (ps == null) {
- ps = client.proxy().orElse(null);
+ /** Retrieves the proxy, from the given ProxySelector, if there is one. */
+ private static Proxy retrieveProxy(ProxySelector ps, URI uri) {
+ Proxy proxy = null;
+ List<Proxy> pl = ps.select(uri);
+ if (!pl.isEmpty()) {
+ Proxy p = pl.get(0);
+ if (p.type() == Proxy.Type.HTTP)
+ proxy = p;
+ }
+ return proxy;
}
- if (ps == null || method.equalsIgnoreCase("CONNECT")) {
+
+ InetSocketAddress proxy() {
+ if (proxy == null || proxy.type() != Proxy.Type.HTTP
+ || method.equalsIgnoreCase("CONNECT")) {
return null;
}
- return (InetSocketAddress)ps.select(uri).get(0).address();
+ return (InetSocketAddress)proxy.address();
}
boolean secure() { return secure; }
@Override
+ public void setProxy(Proxy proxy) {
+ assert isWebSocket;
+ this.proxy = proxy;
+ }
+
+ @Override
public void isWebSocket(boolean is) {
isWebSocket = is;
}
boolean isWebSocket() {
return isWebSocket;
}
-// /** Returns the follow-redirects setting for this request. */
-// @Override
-// public jdk.incubator.http.HttpClient.Redirect followRedirects() {
-// return followRedirects;
-// }
-
@Override
- public Optional<BodyProcessor> bodyProcessor() {
- return Optional.of(requestProcessor);
+ public Optional<BodyPublisher> bodyPublisher() {
+ return requestPublisher == null ? Optional.empty()
+ : Optional.of(requestPublisher);
}
/**
* Returns the request method for this request. If not set explicitly,
* the default method for any request is "GET".
@@ -235,18 +265,14 @@
@Override
public URI uri() { return uri; }
@Override
- public Duration duration() {
- return duration;
+ public Optional<Duration> timeout() {
+ return timeout == null ? Optional.empty() : Optional.of(timeout);
}
-// HttpClientImpl client() {
-// return client;
-// }
-
HttpHeaders getUserHeaders() { return userHeaders; }
HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
@Override
@@ -259,61 +285,28 @@
@Override
public void setSystemHeader(String name, String value) {
systemHeaders.setHeader(name, value);
}
-// @Override
-// public <T> HttpResponse<T>
-// response(HttpResponse.BodyHandler<T> responseHandler)
-// throws IOException, InterruptedException
-// {
-// if (!sent.compareAndSet(false, true)) {
-// throw new IllegalStateException("request already sent");
-// }
-// MultiExchange<Void,T> mex = new MultiExchange<>(this, responseHandler);
-// return mex.response();
-// }
-//
-// @Override
-// public <T> CompletableFuture<HttpResponse<T>>
-// responseAsync(HttpResponse.BodyHandler<T> responseHandler)
-// {
-// if (!sent.compareAndSet(false, true)) {
-// throw new IllegalStateException("request already sent");
-// }
-// MultiExchange<Void,T> mex = new MultiExchange<>(this, responseHandler);
-// return mex.responseAsync(null)
-// .thenApply((HttpResponseImpl<T> b) -> (HttpResponse<T>) b);
-// }
-//
-// @Override
-// public <U, T> CompletableFuture<U>
-// multiResponseAsync(HttpResponse.MultiProcessor<U, T> responseHandler)
-// {
-// if (!sent.compareAndSet(false, true)) {
-// throw new IllegalStateException("request already sent");
-// }
-// MultiExchange<U,T> mex = new MultiExchange<>(this, responseHandler);
-// return mex.multiResponseAsync();
-// }
-
- public InetSocketAddress getAddress(HttpClientImpl client) {
+ InetSocketAddress getAddress() {
URI uri = uri();
if (uri == null) {
return authority();
}
- int port = uri.getPort();
- if (port == -1) {
+ int p = uri.getPort();
+ if (p == -1) {
if (uri.getScheme().equalsIgnoreCase("https")) {
- port = 443;
+ p = 443;
} else {
- port = 80;
+ p = 80;
}
}
- String host = uri.getHost();
- if (proxy(client) == null) {
- return new InetSocketAddress(host, port);
+ final String host = uri.getHost();
+ final int port = p;
+ if (proxy() == null) {
+ PrivilegedAction<InetSocketAddress> pa = () -> new InetSocketAddress(host, port);
+ return AccessController.doPrivileged(pa);
} else {
return InetSocketAddress.createUnresolved(host, port);
}
}
}
< prev index next >