44
44
import java .util .concurrent .ExecutionException ;
45
45
import java .util .concurrent .ExecutorService ;
46
46
import java .util .concurrent .Executors ;
47
+ import java .util .concurrent .Future ;
47
48
import java .util .concurrent .TimeUnit ;
48
49
import java .util .concurrent .atomic .AtomicInteger ;
49
50
import java .util .function .Supplier ;
@@ -369,9 +370,64 @@ private URI getWebSocketUri(HttpRequest request) throws URISyntaxException {
369
370
return uri ;
370
371
}
371
372
373
+ @ Override
374
+ public CompletableFuture <HttpResponse > executeAsync (HttpRequest request ) {
375
+ // the facade for this http request
376
+ CompletableFuture <HttpResponse > cf = new CompletableFuture <>();
377
+
378
+ // the actual http request
379
+ Future <?> future =
380
+ executorService .submit (
381
+ () -> {
382
+ try {
383
+ HttpResponse response = handler .execute (request );
384
+
385
+ cf .complete (response );
386
+ } catch (Throwable t ) {
387
+ cf .completeExceptionally (t );
388
+ }
389
+ });
390
+
391
+ // try to interrupt the http request in case of a timeout, to avoid
392
+ // https://bugs.openjdk.org/browse/JDK-8258397
393
+ cf .exceptionally (
394
+ (throwable ) -> {
395
+ if (throwable instanceof java .util .concurrent .TimeoutException ) {
396
+ // interrupts the thread
397
+ future .cancel (true );
398
+ }
399
+
400
+ // nobody will read this result
401
+ return null ;
402
+ });
403
+
404
+ // will complete exceptionally with a java.util.concurrent.TimeoutException
405
+ return cf .orTimeout (readTimeout .toMillis (), TimeUnit .MILLISECONDS );
406
+ }
407
+
372
408
@ Override
373
409
public HttpResponse execute (HttpRequest req ) throws UncheckedIOException {
374
- return handler .execute (req );
410
+ try {
411
+ // executeAsync does define a timeout, no need to use a timeout here
412
+ return executeAsync (req ).get ();
413
+ } catch (CancellationException e ) {
414
+ throw new WebDriverException (e .getMessage (), e );
415
+ } catch (InterruptedException e ) {
416
+ Thread .currentThread ().interrupt ();
417
+ throw new WebDriverException (e .getMessage (), e );
418
+ } catch (ExecutionException e ) {
419
+ Throwable cause = e .getCause ();
420
+
421
+ if (cause instanceof java .util .concurrent .TimeoutException ) {
422
+ throw new TimeoutException (cause );
423
+ } else if (cause instanceof RuntimeException ) {
424
+ throw (RuntimeException ) cause ;
425
+ } else if (cause instanceof Error ) {
426
+ throw (Error ) cause ;
427
+ }
428
+
429
+ throw new WebDriverException ((cause != null ) ? cause : e );
430
+ }
375
431
}
376
432
377
433
private HttpResponse execute0 (HttpRequest req ) throws UncheckedIOException {
@@ -390,34 +446,13 @@ private HttpResponse execute0(HttpRequest req) throws UncheckedIOException {
390
446
// - avoid a downgrade of POST requests, see the javadoc of j.n.h.HttpClient.Redirect
391
447
// - not run into https://bugs.openjdk.org/browse/JDK-8304701
392
448
for (int i = 0 ; i < 100 ; i ++) {
393
- java .net .http .HttpRequest request = messages .createRequest (req , method , rawUri );
394
- java .net .http .HttpResponse <byte []> response ;
395
-
396
- // use sendAsync to not run into https://bugs.openjdk.org/browse/JDK-8258397
397
- CompletableFuture <java .net .http .HttpResponse <byte []>> future =
398
- client .sendAsync (request , byteHandler );
399
-
400
- try {
401
- response = future .get (readTimeout .toMillis (), TimeUnit .MILLISECONDS );
402
- } catch (CancellationException e ) {
403
- throw new WebDriverException (e .getMessage (), e );
404
- } catch (ExecutionException e ) {
405
- Throwable cause = e .getCause ();
406
-
407
- if (cause instanceof HttpTimeoutException ) {
408
- throw new TimeoutException (cause );
409
- } else if (cause instanceof IOException ) {
410
- throw (IOException ) cause ;
411
- } else if (cause instanceof RuntimeException ) {
412
- throw (RuntimeException ) cause ;
413
- }
414
-
415
- throw new WebDriverException ((cause != null ) ? cause : e );
416
- } catch (java .util .concurrent .TimeoutException e ) {
417
- future .cancel (true );
418
- throw new TimeoutException (e );
449
+ if (Thread .interrupted ()) {
450
+ throw new InterruptedException ("http request has been interrupted" );
419
451
}
420
452
453
+ java .net .http .HttpRequest request = messages .createRequest (req , method , rawUri );
454
+ java .net .http .HttpResponse <byte []> response = client .send (request , byteHandler );
455
+
421
456
switch (response .statusCode ()) {
422
457
case 303 :
423
458
method = HttpMethod .GET ;
@@ -454,6 +489,8 @@ private HttpResponse execute0(HttpRequest req) throws UncheckedIOException {
454
489
}
455
490
456
491
throw new ProtocolException ("Too many redirects: 101" );
492
+ } catch (HttpTimeoutException e ) {
493
+ throw new TimeoutException (e );
457
494
} catch (IOException e ) {
458
495
throw new UncheckedIOException (e );
459
496
} catch (InterruptedException e ) {
0 commit comments