37
37
import java .time .Duration ;
38
38
import java .util .*;
39
39
import java .util .concurrent .CompletableFuture ;
40
+ import java .util .concurrent .CompletionException ;
40
41
import java .util .concurrent .TimeUnit ;
41
42
import java .util .function .Consumer ;
42
43
import java .util .function .Function ;
@@ -560,7 +561,7 @@ public static Builder contentTypeHeader(Builder builder, String contentType) {
560
561
* @return HttpResponse
561
562
*/
562
563
public static HttpResponse <InputStream > execute (HttpClient httpClient , HttpRequest httpRequest ) {
563
- return execute ( httpClient , httpRequest , BodyHandlers .ofInputStream ());
564
+ return AsyncHttpRDF . getOrElseThrow ( executeAsync ( httpClient , httpRequest , BodyHandlers .ofInputStream ()), httpRequest );
564
565
}
565
566
566
567
/**
@@ -580,13 +581,35 @@ public static HttpResponse<InputStream> execute(HttpClient httpClient, HttpReque
580
581
*
581
582
* @param httpClient
582
583
* @param httpRequest
583
- * @param bodyHandler
584
584
* @return HttpResponse
585
585
*/
586
- /*package*/ static <X > HttpResponse <X > execute (HttpClient httpClient , HttpRequest httpRequest , BodyHandler <X > bodyHandler ) {
586
+ public static CompletableFuture <HttpResponse <InputStream >> executeAsync (HttpClient httpClient , HttpRequest httpRequest ) {
587
+ return executeAsync (httpClient , httpRequest , BodyHandlers .ofInputStream ());
588
+ }
589
+
590
+ /**
591
+ * Execute a request, return a {@code HttpResponse<X>} which
592
+ * can be passed to {@link #handleHttpStatusCode(HttpResponse)} which will
593
+ * convert non-2xx status code to {@link HttpException HttpExceptions}.
594
+ * <p>
595
+ * This function applies the HTTP authentication challenge support
596
+ * and will repeat the request if necessary with added authentication.
597
+ * <p>
598
+ * See {@link AuthEnv} for authentication registration.
599
+ * <br/>
600
+ * See {@link #executeJDK} to execute exactly once without challenge response handling.
601
+ *
602
+ * @see AuthEnv AuthEnv for authentic registration
603
+ * @see #executeJDK executeJDK to execute exacly once.
604
+ *
605
+ * @param httpClient
606
+ * @param httpRequest
607
+ * @param bodyHandler
608
+ * @return HttpResponse
609
+ */ /*package*/ static <X > CompletableFuture <HttpResponse <X >> executeAsync (HttpClient httpClient , HttpRequest httpRequest , BodyHandler <X > bodyHandler ) {
587
610
// To run with no jena-supplied authentication handling.
588
611
if ( false )
589
- return executeJDK (httpClient , httpRequest , bodyHandler );
612
+ return executeJDKAsync (httpClient , httpRequest , bodyHandler );
590
613
URI uri = httpRequest .uri ();
591
614
URI key = null ;
592
615
@@ -602,29 +625,16 @@ public static HttpResponse<InputStream> execute(HttpClient httpClient, HttpReque
602
625
authEnv .registerUsernamePassword (key , userpasswd [0 ], userpasswd [1 ]);
603
626
}
604
627
}
605
- try {
606
- return AuthLib .authExecute (httpClient , httpRequest , bodyHandler );
607
- } finally {
608
- if ( key != null )
609
- // The AuthEnv is "per tenant".
610
- // Temporary registration within the AuthEnv of the
611
- // user:password is acceptable.
612
- authEnv .unregisterUsernamePassword (key );
613
- }
614
- }
615
628
616
- /**
617
- * Execute request and return a {@code HttpResponse<InputStream>} response.
618
- * Status codes have not been handled. The response can be passed to
619
- * {@link #handleResponseInputStream(HttpResponse)} which will convert non-2xx
620
- * status code to {@link HttpException HttpExceptions}.
621
- *
622
- * @param httpClient
623
- * @param httpRequest
624
- * @return HttpResponse
625
- */
626
- public static HttpResponse <InputStream > executeJDK (HttpClient httpClient , HttpRequest httpRequest ) {
627
- return execute (httpClient , httpRequest , BodyHandlers .ofInputStream ());
629
+ URI finalKey = key ;
630
+ return AuthLib .authExecuteAsync (httpClient , httpRequest , bodyHandler )
631
+ .whenComplete ((httpResponse , throwable ) -> {
632
+ if ( finalKey != null )
633
+ // The AuthEnv is "per tenant".
634
+ // Temporary registration within the AuthEnv of the
635
+ // user:password is acceptable.
636
+ authEnv .unregisterUsernamePassword (finalKey );
637
+ });
628
638
}
629
639
630
640
/**
@@ -640,25 +650,32 @@ public static HttpResponse<InputStream> executeJDK(HttpClient httpClient, HttpRe
640
650
* @return HttpResponse
641
651
*/
642
652
public static <T > HttpResponse <T > executeJDK (HttpClient httpClient , HttpRequest httpRequest , BodyHandler <T > bodyHandler ) {
643
- try {
644
- // This is the one place all HTTP requests go through.
645
- logRequest (httpRequest );
646
- HttpResponse <T > httpResponse = httpClient .send (httpRequest , bodyHandler );
647
- logResponse (httpResponse );
648
- return httpResponse ;
649
- //} catch (HttpTimeoutException ex) {
650
- } catch (IOException | InterruptedException ex ) {
651
- if ( ex .getMessage () != null ) {
652
- // This is silly.
653
- // Rather than an HTTP exception, bad authentication becomes IOException("too many authentication attempts");
654
- // or IOException("No credentials provided") if the authenticator decides to return null.
655
- if ( ex .getMessage ().contains ("too many authentication attempts" ) ||
656
- ex .getMessage ().contains ("No credentials provided" ) ) {
657
- throw new HttpException (401 , HttpSC .getMessage (401 ));
658
- }
659
- }
660
- throw new HttpException (httpRequest .method ()+" " +httpRequest .uri ().toString (), ex );
661
- }
653
+ return AsyncHttpRDF .getOrElseThrow (executeJDKAsync (httpClient , httpRequest , bodyHandler ), httpRequest );
654
+ }
655
+
656
+ /**
657
+ * Execute request and return a {@code HttpResponse<InputStream>} response.
658
+ * Status codes have not been handled. The response can be passed to
659
+ * {@link #handleResponseInputStream(HttpResponse)} which will convert non-2xx
660
+ * status code to {@link HttpException HttpExceptions}.
661
+ *
662
+ * @param httpClient
663
+ * @param httpRequest
664
+ * @return HttpResponse
665
+ */
666
+ public static CompletableFuture <HttpResponse <InputStream >> executeJDKAsync (HttpClient httpClient , HttpRequest httpRequest ) {
667
+ return executeAsync (httpClient , httpRequest , BodyHandlers .ofInputStream ());
668
+ }
669
+
670
+ public static <T > CompletableFuture <HttpResponse <T >> executeJDKAsync (HttpClient httpClient , HttpRequest httpRequest , BodyHandler <T > bodyHandler ) {
671
+ // This is the one place all HTTP requests go through.
672
+ logRequest (httpRequest );
673
+ CompletableFuture <HttpResponse <T >> future = httpClient .sendAsync (httpRequest , bodyHandler )
674
+ .thenApply (httpResponse -> {
675
+ logResponse (httpResponse );
676
+ return httpResponse ;
677
+ });
678
+ return future ;
662
679
}
663
680
664
681
/*package*/ static CompletableFuture <HttpResponse <InputStream >> asyncExecute (HttpClient httpClient , HttpRequest httpRequest ) {
0 commit comments