21
21
import org.openqa.selenium.Credentials;
22
22
import org.openqa.selenium.TimeoutException;
23
23
import org.openqa.selenium.UsernameAndPassword;
24
+
import org.openqa.selenium.WebDriverException;
24
25
import org.openqa.selenium.remote.http.BinaryMessage;
25
26
import org.openqa.selenium.remote.http.ClientConfig;
26
27
import org.openqa.selenium.remote.http.CloseMessage;
46
47
import java.net.http.HttpResponse.BodyHandlers;
47
48
import java.net.http.HttpTimeoutException;
48
49
import java.nio.ByteBuffer;
50
+
import java.time.Duration;
49
51
import java.util.List;
50
52
import java.util.Objects;
53
+
import java.util.concurrent.CancellationException;
51
54
import java.util.concurrent.CompletableFuture;
52
55
import java.util.concurrent.CompletionStage;
56
+
import java.util.concurrent.CompletionStage;
57
+
import java.util.concurrent.ExecutionException;
58
+
import java.util.concurrent.TimeUnit;
59
+
import java.util.function.Supplier;
53
60
54
61
import static java.net.http.HttpClient.Redirect.ALWAYS;
55
62
56
63
public class JdkHttpClient implements HttpClient {
57
64
private final JdkHttpMessages messages;
58
65
private final java.net.http.HttpClient client;
66
+
private final Duration readTimeout;
59
67
60
68
JdkHttpClient(ClientConfig config) {
61
69
Objects.requireNonNull(config, "Client config must be set");
62
70
63
71
this.messages = new JdkHttpMessages(config);
72
+
this.readTimeout = config.readTimeout();
64
73
65
74
java.net.http.HttpClient.Builder builder = java.net.http.HttpClient.newBuilder()
66
75
.connectTimeout(config.connectionTimeout())
67
76
.followRedirects(ALWAYS);
68
77
69
-
70
78
Credentials credentials = config.credentials();
71
79
if (credentials != null) {
72
80
if (!(credentials instanceof UsernameAndPassword)) {
@@ -148,18 +156,40 @@ public void onError(java.net.http.WebSocket webSocket, Throwable error) {
148
156
return new WebSocket() {
149
157
@Override
150
158
public WebSocket send(Message message) {
159
+
Supplier<CompletableFuture<java.net.http.WebSocket>> makeCall;
160
+
151
161
if (message instanceof BinaryMessage) {
152
162
BinaryMessage binaryMessage = (BinaryMessage) message;
153
-
underlyingSocket.sendBinary(ByteBuffer.wrap(binaryMessage.data()), true);
163
+
makeCall = () -> underlyingSocket.sendBinary(ByteBuffer.wrap(binaryMessage.data()), true);
154
164
} else if (message instanceof TextMessage) {
155
165
TextMessage textMessage = (TextMessage) message;
156
-
underlyingSocket.sendText(textMessage.text(), true);
166
+
makeCall = () -> underlyingSocket.sendText(textMessage.text(), true);
157
167
} else if (message instanceof CloseMessage) {
158
168
CloseMessage closeMessage = (CloseMessage) message;
159
-
underlyingSocket.sendClose(closeMessage.code(), closeMessage.reason());
169
+
makeCall = () -> underlyingSocket.sendClose(closeMessage.code(), closeMessage.reason());
160
170
} else {
161
171
throw new IllegalArgumentException("Unsupport message type: " + message);
162
172
}
173
+
174
+
synchronized (underlyingSocket) {
175
+
CompletableFuture<java.net.http.WebSocket> future = makeCall.get();
176
+
try {
177
+
future.get(readTimeout.toMillis(), TimeUnit.MILLISECONDS);
178
+
} catch (CancellationException e) {
179
+
throw new WebDriverException(e.getMessage(), e);
180
+
} catch (ExecutionException e) {
181
+
Throwable cause = e.getCause();
182
+
if (cause == null) {
183
+
throw new WebDriverException(e);
184
+
}
185
+
throw new WebDriverException(cause);
186
+
} catch (InterruptedException e) {
187
+
Thread.currentThread().interrupt();
188
+
throw new WebDriverException(e.getMessage());
189
+
} catch (java.util.concurrent.TimeoutException e) {
190
+
throw new TimeoutException(e);
191
+
}
192
+
}
163
193
return this;
164
194
}
165
195
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4