Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions java/src/org/openqa/selenium/remote/http/jdk/JdkHttpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.io.UncheckedIOException;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
Expand All @@ -62,8 +63,6 @@
import java.util.logging.Level;
import java.util.logging.Logger;

import static java.net.http.HttpClient.Redirect.ALWAYS;

public class JdkHttpClient implements HttpClient {
public static final Logger LOG = Logger.getLogger(JdkHttpClient.class.getName());
private final JdkHttpMessages messages;
Expand All @@ -82,7 +81,7 @@ public class JdkHttpClient implements HttpClient {

java.net.http.HttpClient.Builder builder = java.net.http.HttpClient.newBuilder()
.connectTimeout(config.connectionTimeout())
.followRedirects(ALWAYS)
.followRedirects(java.net.http.HttpClient.Redirect.NEVER)
.executor(executorService);

Credentials credentials = config.credentials();
Expand Down Expand Up @@ -289,7 +288,42 @@ public HttpResponse execute(HttpRequest req) throws UncheckedIOException {

BodyHandler<byte[]> byteHandler = BodyHandlers.ofByteArray();
try {
return messages.createResponse(client.send(messages.createRequest(req), byteHandler));
URI rawUri = messages.getRawUri(req);

// We need a custom handling of redirects to:
// - increase the maximum number of retries to 100
// - avoid a downgrade of POST requests, see the javadoc of j.n.h.HttpClient.Redirect
// - not run into https://bugs.openjdk.org/browse/JDK-8304701
for (int i = 0; i < 100; i++) {
java.net.http.HttpRequest request = messages.createRequest(req, rawUri);
java.net.http.HttpResponse<byte[]> response = client.send(request, byteHandler);

switch (response.statusCode()) {
case 301:
case 302:
case 303:
case 307:
case 308:
URI location = rawUri.resolve(response.headers()
.firstValue("location")
.orElseThrow(() -> new ProtocolException(
"HTTP " + response.statusCode() + " without 'location' header set"
)));

if ("https".equalsIgnoreCase(rawUri.getScheme()) && !"https".equalsIgnoreCase(location.getScheme()) ) {
throw new SecurityException("Downgrade from secure to insecure connection.");
} else if ("wss".equalsIgnoreCase(rawUri.getScheme()) && !"wss".equalsIgnoreCase(location.getScheme()) ) {
throw new SecurityException("Downgrade from secure to insecure connection.");
}

rawUri = location;
continue;
default:
return messages.createResponse(response);
}
}

throw new ProtocolException("Too many redirects: 101");
} catch (HttpTimeoutException e) {
throw new TimeoutException(e);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public JdkHttpMessages(ClientConfig config) {
this.config = Objects.requireNonNull(config, "Client config");
}

public java.net.http.HttpRequest createRequest(HttpRequest req) {
String rawUrl = getRawUrl(config.baseUri(), req.getUri());
public java.net.http.HttpRequest createRequest(HttpRequest req, URI rawUri) {
String rawUrl = rawUri.toString();

// Add query string if necessary
String queryString = StreamSupport.stream(req.getQueryParameterNames().spliterator(), false)
Expand Down Expand Up @@ -129,20 +129,18 @@ private BodyPublisher notChunkingBodyPublisher(HttpRequest req) {
return BodyPublishers.fromPublisher(chunking, Long.parseLong(length));
}

private String getRawUrl(URI baseUrl, String uri) {
public URI getRawUri(HttpRequest req) {
URI baseUrl = config.baseUri();
String uri = req.getUri();
String rawUrl;

if (uri.startsWith("ws://") || uri.startsWith("wss://") ||
uri.startsWith("http://") || uri.startsWith("https://")) {
uri.startsWith("http://") || uri.startsWith("https://")) {
rawUrl = uri;
} else {
rawUrl = baseUrl.toString().replaceAll("/$", "") + uri;
}

return rawUrl;
}

public URI getRawUri(HttpRequest req) {
String rawUrl = getRawUrl(config.baseUri(), req.getUri());
return URI.create(rawUrl);
}

Expand Down