package jdk.incubator.http;
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.ProxySelector;
import java.net.URI;
import java.security.AccessControlContext;
import java.time.Duration;
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 ;
private final HttpHeadersImpl ;
private final URI uri;
private InetSocketAddress authority;
private final String method;
final BodyProcessor requestProcessor;
final boolean secure;
final boolean expectContinue;
private boolean isWebSocket;
private AccessControlContext acc;
private final Duration duration;
private final Optional<HttpClient.Version> version;
public HttpRequestImpl(HttpRequestBuilderImpl builder) {
this.method = builder.method();
this.userHeaders = ImmutableHeaders.of(builder.headers().map(), ALLOWED_HEADERS);
this.systemHeaders = new HttpHeadersImpl();
this.uri = builder.uri();
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.version = builder.version();
}
public HttpRequestImpl(HttpRequest request) {
this.method = request.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();
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.duration = request.duration();
this.version = request.version();
}
public HttpRequestImpl(URI uri,
String method,
HttpRequestImpl other) {
this.method = method == null? "GET" : method;
this.userHeaders = other.userHeaders;
this.isWebSocket = other.isWebSocket;
this.systemHeaders = other.systemHeaders;
this.uri = uri;
this.expectContinue = other.expectContinue;
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
this.requestProcessor = other.requestProcessor;
this.acc = other.acc;
this.duration = other.duration;
this.version = other.version();
}
HttpRequestImpl(String method, HttpClientImpl client,
InetSocketAddress authority) {
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.authority = authority;
this.secure = false;
this.expectContinue = false;
this.duration = null;
this.version = Optional.of(client.version());
}
static HttpRequestImpl (HttpRequestImpl parent,
HttpHeadersImpl headers)
throws IOException
{
return new HttpRequestImpl(parent, headers);
}
private (HttpRequestImpl parent, HttpHeadersImpl headers)
throws IOException
{
this.method = headers.firstValue(":method")
.orElseThrow(() -> new IOException("No method in Push Promise"));
String path = headers.firstValue(":path")
.orElseThrow(() -> new IOException("No path in Push Promise"));
String scheme = headers.firstValue(":scheme")
.orElseThrow(() -> new IOException("No scheme in Push Promise"));
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.userHeaders = ImmutableHeaders.of(headers.map(), ALLOWED_HEADERS);
this.systemHeaders = parent.systemHeaders;
this.expectContinue = parent.expectContinue;
this.secure = parent.secure;
this.requestProcessor = parent.requestProcessor;
this.acc = parent.acc;
this.duration = parent.duration;
this.version = parent.version;
}
@Override
public String toString() {
return (uri == null ? "" : uri.toString()) + " " + method;
}
@Override
public HttpHeaders () {
return userHeaders;
}
InetSocketAddress authority() { return authority; }
void setH2Upgrade(Http2ClientImpl h2client) {
systemHeaders.setHeader("Connection", "Upgrade, HTTP2-Settings");
systemHeaders.setHeader("Upgrade", "h2c");
systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
}
@Override
public boolean expectContinue() { return expectContinue; }
InetSocketAddress proxy(HttpClientImpl client) {
ProxySelector ps = client.proxy().orElse(null);
if (ps == null) {
ps = client.proxy().orElse(null);
}
if (ps == null || method.equalsIgnoreCase("CONNECT")) {
return null;
}
return (InetSocketAddress)ps.select(uri).get(0).address();
}
boolean secure() { return secure; }
@Override
public void isWebSocket(boolean is) {
isWebSocket = is;
}
boolean isWebSocket() {
return isWebSocket;
}
@Override
public Optional<BodyProcessor> bodyProcessor() {
return Optional.of(requestProcessor);
}
@Override
public String method() { return method; }
@Override
public URI uri() { return uri; }
@Override
public Duration duration() {
return duration;
}
HttpHeaders () { return userHeaders; }
HttpHeadersImpl () { return systemHeaders; }
@Override
public Optional<HttpClient.Version> version() { return version; }
void (String name, String value) {
systemHeaders.addHeader(name, value);
}
@Override
public void (String name, String value) {
systemHeaders.setHeader(name, value);
}
public InetSocketAddress getAddress(HttpClientImpl client) {
URI uri = uri();
if (uri == null) {
return authority();
}
int port = uri.getPort();
if (port == -1) {
if (uri.getScheme().equalsIgnoreCase("https")) {
port = 443;
} else {
port = 80;
}
}
String host = uri.getHost();
if (proxy(client) == null) {
return new InetSocketAddress(host, port);
} else {
return InetSocketAddress.createUnresolved(host, port);
}
}
}