< prev index next >

src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpResponse.java

Print this page




   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.incubator.http;
  27 
  28 import java.io.IOException;
  29 import java.io.UncheckedIOException;
  30 import java.net.URI;
  31 import jdk.incubator.http.ResponseProcessors.MultiFile;
  32 import jdk.incubator.http.ResponseProcessors.MultiProcessorImpl;
  33 import static jdk.incubator.http.internal.common.Utils.unchecked;
  34 import static jdk.incubator.http.internal.common.Utils.charsetFrom;
  35 import java.nio.ByteBuffer;
  36 import java.nio.charset.Charset;
  37 import java.nio.charset.StandardCharsets;
  38 import java.nio.file.OpenOption;
  39 import java.nio.file.Path;
  40 import java.nio.file.Paths;
  41 import java.nio.file.StandardOpenOption;
  42 import java.util.Map;



  43 import java.util.Optional;
  44 import java.util.concurrent.CompletableFuture;
  45 import java.util.concurrent.CompletionStage;
  46 import java.util.concurrent.Flow;
  47 import java.util.function.Consumer;
  48 import java.util.function.Function;
  49 import javax.net.ssl.SSLParameters;
  50 
  51 /**
  52  * Represents a response to a {@link HttpRequest}.
  53  * {@Incubating}
  54  *
  55  * <p>A {@code HttpResponse} is available when the response status code and
  56  * headers have been received, and typically after the response body has also
  57  * been received. This depends on the response body handler provided when
  58  * sending the request. In all cases, the response body handler is invoked
  59  * before the body is read. This gives applications an opportunity to decide
  60  * how to handle the body.
  61  *
  62  * <p> Methods are provided in this class for accessing the response headers,
  63  * and response body.
  64  * <p>
  65  * <b>Response handlers and processors</b>
  66  * <p>
  67  * Response bodies are handled at two levels. Application code supplies a response
  68  * handler ({@link BodyHandler}) which may examine the response status code
  69  * and headers, and which then returns a {@link BodyProcessor} to actually read
  70  * (or discard) the body and convert it into some useful Java object type. The handler
  71  * can return one of the pre-defined processor types, or a custom processor, or
  72  * if the body is to be discarded, it can call {@link BodyProcessor#discard(Object)
  73  * BodyProcessor.discard()} and return a processor which discards the response body.
  74  * Static implementations of both handlers and processors are provided in
  75  * {@link BodyHandler BodyHandler} and {@link BodyProcessor BodyProcessor} respectively.
  76  * In all cases, the handler functions provided are convenience implementations
  77  * which ignore the supplied status code and
  78  * headers and return the relevant pre-defined {@code BodyProcessor}.
  79  * <p>
  80  * See {@link BodyHandler} for example usage.

  81  *
  82  * @param <T> the response body type
  83  * @since 9
  84  */
  85 public abstract class HttpResponse<T> {
  86 
  87     /**
  88      * Creates an HttpResponse.
  89      */
  90     protected HttpResponse() { }
  91 
  92     /**
  93      * Returns the status code for this response.
  94      *
  95      * @return the response code
  96      */
  97     public abstract int statusCode();
  98 
  99     /**
 100      * Returns the initial {@link HttpRequest} that initiated the exchange.





 101      *
 102      * @return the request
 103      */
 104     public abstract HttpRequest request();
 105 
 106     /**
 107      * Returns the final {@link HttpRequest} that was sent on the wire for the
 108      * exchange ( may, or may not, be the same as the initial request ).


 109      *
 110      * @return the request
 111      */
 112     public abstract HttpRequest finalRequest();
 113 
 114     /**
 115      * Returns the received response headers.
 116      *
 117      * @return the response headers
 118      */
 119     public abstract HttpHeaders headers();
 120 
 121     /**
 122      * Returns the received response trailers, if there are any, when they
 123      * become available. For many response processor types this will be at the same
 124      * time as the {@code HttpResponse} itself is available. In such cases, the
 125      * returned {@code CompletableFuture} will be already completed.
 126      *
 127      * @return a CompletableFuture of the response trailers (may be empty)
 128      */
 129     public abstract CompletableFuture<HttpHeaders> trailers();
 130 
 131     /**
 132      * Returns the body. Depending on the type of {@code T}, the returned body may
 133      * represent the body after it was read (such as {@code byte[]}, or
 134      * {@code String}, or {@code Path}) or it may represent an object with
 135      * which the body is read, such as an {@link java.io.InputStream}.
 136      *



 137      * @return the body
 138      */
 139     public abstract T body();
 140 
 141     /**
 142      * Returns the {@link javax.net.ssl.SSLParameters} in effect for this
 143      * response. Returns {@code null} if this is not a HTTPS response.
 144      *
 145      * @return the SSLParameters associated with the response
 146      */
 147     public abstract SSLParameters sslParameters();
 148 
 149     /**
 150      * Returns the {@code URI} that the response was received from. This may be
 151      * different from the request {@code URI} if redirection occurred.
 152      *
 153      * @return the URI of the response
 154      */
 155     public abstract URI uri();
 156 
 157     /**
 158      * Returns the HTTP protocol version that was used for this response.
 159      *
 160      * @return HTTP protocol version
 161      */
 162     public abstract HttpClient.Version version();
 163 



















































































 164     /**
 165      * A handler for response bodies.
 166      * {@Incubating}
 167      * <p>
 168      * This is a function that takes two parameters: the response status code,
 169      * and the response headers, and which returns a {@link BodyProcessor}.
 170      * The function is always called just before the response body is read. Its
 171      * implementation may examine the status code or headers and must decide,
 172      * whether to accept the response body or discard it, and if accepting it,
 173      * exactly how to handle it.
 174      * <p>
 175      * Some pre-defined implementations which do not utilize the status code
 176      * or headers (meaning the body is always accepted) are defined:
 177      * <ul><li>{@link #asByteArray() }</li>
 178      * <li>{@link #asByteArrayConsumer(java.util.function.Consumer)
 179      * asByteArrayConsumer(Consumer)}</li>



 180      * <li>{@link #asFileDownload(java.nio.file.Path,OpenOption...)
 181      * asFileDownload(Path,OpenOption...)}</li>

 182      * <li>{@link #discard(Object) }</li>
 183      * <li>{@link #asString(java.nio.charset.Charset)
 184      * asString(Charset)}</li></ul>
 185      * <p>
 186      * These implementations return the equivalent {@link BodyProcessor}.

 187      * Alternatively, the handler can be used to examine the status code
 188      * or headers and return different body processors as appropriate.
 189      * <p>
 190      * <b>Examples of handler usage</b>
 191      * <p>
 192      * The first example uses one of the predefined handler functions which
 193      * ignore the response headers and status, and always process the response
 194      * body in the same way.
 195      * <pre>
 196      * {@code
 197      *      HttpResponse<Path> resp = HttpRequest
 198      *              .create(URI.create("http://www.foo.com"))
 199      *              .GET()
 200      *              .response(BodyHandler.asFile(Paths.get("/tmp/f")));
 201      * }
 202      * </pre>
 203      * Note, that even though these pre-defined handlers ignore the status code
 204      * and headers, this information is still accessible from the {@code HttpResponse}
 205      * when it is returned.
 206      * <p>
 207      * In the second example, the function returns a different processor depending
 208      * on the status code.
 209      * <pre>
 210      * {@code
 211      *      HttpResponse<Path> resp1 = HttpRequest
 212      *              .create(URI.create("http://www.foo.com"))
 213      *              .GET()
 214      *              .response(
 215      *                  (status, headers) -> status == 200
 216      *                      ? BodyProcessor.asFile(Paths.get("/tmp/f"))
 217      *                      : BodyProcessor.discard(Paths.get("/NULL")));
 218      * }
 219      * </pre>
 220      *
 221      * @param <T> the response body type.
 222      */
 223     @FunctionalInterface
 224     public interface BodyHandler<T> {
 225 
 226         /**
 227          * Returns a {@link BodyProcessor BodyProcessor} considering the given response status
 228          * code and headers. This method is always called before the body is read
 229          * and its implementation can decide to keep the body and store it somewhere
 230          * or else discard it, by  returning the {@code BodyProcessor} returned
 231          * from {@link BodyProcessor#discard(java.lang.Object) discard()}.

 232          *
 233          * @param statusCode the HTTP status code received
 234          * @param responseHeaders the response headers received
 235          * @return a response body handler
 236          */
 237         public BodyProcessor<T> apply(int statusCode, HttpHeaders responseHeaders);
 238 
 239         /**
 240          * Returns a response body handler which discards the response body and
 241          * uses the given value as a replacement for it.
 242          *
 243          * @param <U> the response body type
 244          * @param value the value of U to return as the body
 245          * @return a response body handler
 246          */
 247         public static <U> BodyHandler<U> discard(U value) {
 248             return (status, headers) -> BodyProcessor.discard(value);
 249         }
 250 
 251         /**
 252          * Returns a {@code BodyHandler<String>} that returns a
 253          * {@link BodyProcessor BodyProcessor}{@code <String>} obtained from
 254          * {@link BodyProcessor#asString(java.nio.charset.Charset)
 255          * BodyProcessor.asString(Charset)}. If a charset is provided, the
 256          * body is decoded using it. If charset is {@code null} then the processor
 257          * tries to determine the character set from the {@code Content-encoding}
 258          * header. If that charset is not supported then
 259          * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
 260          *
 261          * @param charset the name of the charset to interpret the body as. If
 262          * {@code null} then charset determined from Content-encoding header

 263          * @return a response body handler
 264          */
 265         public static BodyHandler<String> asString(Charset charset) {
 266             return (status, headers) -> {
 267                 if (charset != null) {
 268                     return BodyProcessor.asString(charset);
 269                 }
 270                 return BodyProcessor.asString(charsetFrom(headers));
 271             };
 272         }
 273 


































 274 
 275         /**
 276          * Returns a {@code BodyHandler<Path>} that returns a
 277          * {@link BodyProcessor BodyProcessor}{@code <Path>} obtained from
 278          * {@link BodyProcessor#asFile(Path) BodyProcessor.asFile(Path)}.
 279          * <p>
 280          * When the {@code HttpResponse} object is returned, the body has been completely
 281          * written to the file, and {@link #body()} returns a reference to its
 282          * {@link Path}.
 283          *
 284          * @param file the file to store the body in
 285          * @return a response body handler



 286          */
 287         public static BodyHandler<Path> asFile(Path file) {
 288             return (status, headers) -> BodyProcessor.asFile(file);

 289         }
 290 
 291         /**
 292          * Returns a {@code BodyHandler<Path>} that returns a
 293          * {@link BodyProcessor BodyProcessor}&lt;{@link Path}&gt;
 294          * where the download directory is specified, but the filename is
 295          * obtained from the {@code Content-Disposition} response header. The
 296          * {@code Content-Disposition} header must specify the <i>attachment</i> type
 297          * and must also contain a
 298          * <i>filename</i> parameter. If the filename specifies multiple path
 299          * components only the final component is used as the filename (with the
 300          * given directory name). When the {@code HttpResponse} object is
 301          * returned, the body has been completely written to the file and {@link
 302          * #body()} returns a {@code Path} object for the file. The returned {@code Path} is the

 303          * combination of the supplied directory name and the file name supplied
 304          * by the server. If the destination directory does not exist or cannot
 305          * be written to, then the response will fail with an {@link IOException}.
 306          *
 307          * @param directory the directory to store the file in
 308          * @param openOptions open options
 309          * @return a response body handler
 310          */
 311         public static BodyHandler<Path> asFileDownload(Path directory, OpenOption... openOptions) {
 312             return (status, headers) -> {
 313                 String dispoHeader = headers.firstValue("Content-Disposition")
 314                         .orElseThrow(() -> unchecked(new IOException("No Content-Disposition")));
 315                 if (!dispoHeader.startsWith("attachment;")) {
 316                     throw unchecked(new IOException("Unknown Content-Disposition type"));
 317                 }
 318                 int n = dispoHeader.indexOf("filename=");
 319                 if (n == -1) {
 320                     throw unchecked(new IOException("Bad Content-Disposition type"));
 321                 }
 322                 int lastsemi = dispoHeader.lastIndexOf(';');
 323                 String disposition;
 324                 if (lastsemi < n) {
 325                     disposition = dispoHeader.substring(n + 9);
 326                 } else {
 327                     disposition = dispoHeader.substring(n + 9, lastsemi);
 328                 }
 329                 Path file = Paths.get(directory.toString(), disposition);
 330                 return BodyProcessor.asFile(file, openOptions);
 331             };
 332         }
 333 
 334         /**
 335          * Returns a {@code BodyHandler<Path>} that returns a
 336          * {@link BodyProcessor BodyProcessor}{@code <Path>} obtained from
 337          * {@link BodyProcessor#asFile(java.nio.file.Path, java.nio.file.OpenOption...)
 338          * BodyProcessor.asFile(Path,OpenOption...)}.
 339          * <p>
 340          * When the {@code HttpResponse} object is returned, the body has been completely
 341          * written to the file, and {@link #body()} returns a reference to its
 342          * {@link Path}.


 343          *
 344          * @param file the filename to store the body in
 345          * @param openOptions any options to use when opening/creating the file
 346          * @return a response body handler
 347          */
 348         public static BodyHandler<Path> asFile(Path file, OpenOption... openOptions) {
 349             return (status, headers) -> BodyProcessor.asFile(file, openOptions);
 350         }
 351 
 352         /**
 353          * Returns a {@code BodyHandler<Void>} that returns a
 354          * {@link BodyProcessor BodyProcessor}{@code <Void>} obtained from
 355          * {@link BodyProcessor#asByteArrayConsumer(java.util.function.Consumer)
 356          * BodyProcessor.asByteArrayConsumer(Consumer)}.
 357          * <p>
 358          * When the {@code HttpResponse} object is returned, the body has been completely
 359          * written to the consumer.
 360          *
 361          * @param consumer a Consumer to accept the response body
 362          * @return a response body handler
 363          */
 364         public static BodyHandler<Void> asByteArrayConsumer(Consumer<Optional<byte[]>> consumer) {
 365             return (status, headers) -> BodyProcessor.asByteArrayConsumer(consumer);
 366         }
 367 
 368         /**
 369          * Returns a {@code BodyHandler<byte[]>} that returns a
 370          * {@link BodyProcessor BodyProcessor}&lt;{@code byte[]}&gt; obtained
 371          * from {@link BodyProcessor#asByteArray() BodyProcessor.asByteArray()}.
 372          * <p>
 373          * When the {@code HttpResponse} object is returned, the body has been completely
 374          * written to the byte array.
 375          *
 376          * @return a response body handler
 377          */
 378         public static BodyHandler<byte[]> asByteArray() {
 379             return (status, headers) -> BodyProcessor.asByteArray();
 380         }
 381 
 382         /**
 383          * Returns a {@code BodyHandler<String>} that returns a
 384          * {@link BodyProcessor BodyProcessor}{@code <String>} obtained from
 385          * {@link BodyProcessor#asString(java.nio.charset.Charset)
 386          * BodyProcessor.asString(Charset)}. The body is
 387          * decoded using the character set specified in
 388          * the {@code Content-encoding} response header. If there is no such
 389          * header, or the character set is not supported, then
 390          * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
 391          * <p>
 392          * When the {@code HttpResponse} object is returned, the body has been completely
 393          * written to the string.
 394          *
 395          * @return a response body handler
 396          */
 397         public static BodyHandler<String> asString() {
 398             return (status, headers) -> BodyProcessor.asString(charsetFrom(headers));
























 399         }
 400     }
 401 
 402     /**
 403      * A processor for response bodies.
 404      * {@Incubating}
 405      * <p>
 406      * The object acts as a {@link Flow.Subscriber}&lt;{@link ByteBuffer}&gt; to
 407      * the HTTP client implementation which publishes ByteBuffers containing the
 408      * response body. The processor converts the incoming buffers of data to
 409      * some user-defined object type {@code T}.
 410      * <p>
 411      * The {@link #getBody()} method returns a {@link CompletionStage}{@code <T>}
 412      * that provides the response body object. The {@code CompletionStage} must
 413      * be obtainable at any time. When it completes depends on the nature
 414      * of type {@code T}. In many cases, when {@code T} represents the entire body after being
 415      * read then it completes after the body has been read. If {@code T} is a streaming
 416      * type such as {@link java.io.InputStream} then it completes before the
 417      * body has been read, because the calling code uses it to consume the data.

















 418      *
 419      * @param <T> the response body type
 420      */
 421     public interface BodyProcessor<T>
 422             extends Flow.Subscriber<ByteBuffer> {
 423 
 424         /**
 425          * Returns a {@code CompletionStage} which when completed will return the
 426          * response body object.
 427          *
 428          * @return a CompletionStage for the response body
 429          */
 430         public CompletionStage<T> getBody();
 431 
 432         /**
 433          * Returns a body processor which stores the response body as a {@code
 434          * String} converted using the given {@code Charset}.
 435          * <p>
 436          * The {@link HttpResponse} using this processor is available after the
 437          * entire response has been read.
 438          *
 439          * @param charset the character set to convert the String with
 440          * @return a body processor
 441          */
 442         public static BodyProcessor<String> asString(Charset charset) {
 443             return new ResponseProcessors.ByteArrayProcessor<>(
 444                     bytes -> new String(bytes, charset)
 445             );
 446         }
 447 
 448         /**
 449          * Returns a {@code BodyProcessor} which stores the response body as a
 450          * byte array.
 451          * <p>
 452          * The {@link HttpResponse} using this processor is available after the
 453          * entire response has been read.
 454          *
 455          * @return a body processor



 456          */
 457         public static BodyProcessor<byte[]> asByteArray() {
 458             return new ResponseProcessors.ByteArrayProcessor<>(
 459                     Function.identity() // no conversion
 460             );
 461         }
 462 





 463         /**
 464          * Returns a {@code BodyProcessor} which stores the response body in a
 465          * file opened with the given options and name. The file will be opened
 466          * with the given options using
 467          * {@link java.nio.channels.FileChannel#open(java.nio.file.Path,java.nio.file.OpenOption...)
 468          * FileChannel.open} just before the body is read. Any exception thrown will be returned
 469          * or thrown from {@link HttpClient#send(jdk.incubator.http.HttpRequest,
 470          * jdk.incubator.http.HttpResponse.BodyHandler) HttpClient::send}
 471          * or {@link HttpClient#sendAsync(jdk.incubator.http.HttpRequest,
 472          * jdk.incubator.http.HttpResponse.BodyHandler) HttpClient::sendAsync}
 473          * as appropriate.
 474          * <p>
 475          * The {@link HttpResponse} using this processor is available after the
 476          * entire response has been read.
 477          *
 478          * @param file the file to store the body in
 479          * @param openOptions the list of options to open the file with
 480          * @return a body processor




































 481          */
 482         public static BodyProcessor<Path> asFile(Path file, OpenOption... openOptions) {
 483             return new ResponseProcessors.PathProcessor(file, openOptions);
 484         }
 485 
 486         /**
 487          * Returns a {@code BodyProcessor} which provides the incoming body
 488          * data to the provided Consumer of {@code Optional<byte[]>}. Each
 489          * call to {@link Consumer#accept(java.lang.Object) Consumer.accept()}
 490          * will contain a non empty {@code Optional}, except for the final invocation after
 491          * all body data has been read, when the {@code Optional} will be empty.
 492          * <p>
 493          * The {@link HttpResponse} using this processor is available after the
 494          * entire response has been read.

 495          *
 496          * @param consumer a Consumer of byte arrays
 497          * @return a BodyProcessor
 498          */
 499         public static BodyProcessor<Void> asByteArrayConsumer(Consumer<Optional<byte[]>> consumer) {
 500             return new ResponseProcessors.ConsumerProcessor(consumer);
 501         }
 502 
 503         /**
 504          * Returns a {@code BodyProcessor} which stores the response body in a
 505          * file opened with the given name. Has the same effect as calling
 506          * {@link #asFile(java.nio.file.Path, java.nio.file.OpenOption...) asFile}
 507          * with the standard open options {@code CREATE} and {@code WRITE}
 508          * <p>
 509          * The {@link HttpResponse} using this processor is available after the
 510          * entire response has been read.
 511          *
 512          * @param file the file to store the body in
 513          * @return a body processor













 514          */
 515         public static BodyProcessor<Path> asFile(Path file) {
 516             return new ResponseProcessors.PathProcessor(
 517                     file,
 518                     StandardOpenOption.CREATE, StandardOpenOption.WRITE);
 519         }
 520 
 521         /**
 522          * Returns a response processor which discards the response body. The
 523          * supplied value is the value that will be returned from
 524          * {@link HttpResponse#body()}.
 525          *
 526          * @param <U> The type of the response body
 527          * @param value the value to return from HttpResponse.body()
 528          * @return a {@code BodyProcessor}
 529          */
 530         public static <U> BodyProcessor<U> discard(U value) {
 531             return new ResponseProcessors.NullProcessor<>(Optional.ofNullable(value));
























 532         }
 533     }
 534 
 535     /**
 536      * A response processor for a HTTP/2 multi response.
 537      * {@Incubating}
 538      * <p>
 539      * A multi response comprises a main response, and zero or more additional
 540      * responses. Each additional response is sent by the server in response to
 541      * requests that the server also generates. Additional responses are
 542      * typically resources that the server expects the client will need which
 543      * are related to the initial request.
 544      * <p>
 545      * Note. Instead of implementing this interface, applications should consider
 546      * first using the mechanism (built on this interface) provided by
 547      * {@link MultiProcessor#asMap(java.util.function.Function, boolean)
 548      * MultiProcessor.asMap()} which is a slightly simplified, but
 549      * general purpose interface.
 550      * <p>
 551      * The server generated requests are also known as <i>push promises</i>.
 552      * The server is permitted to send any number of these requests up to the
 553      * point where the main response is fully received. Therefore, after
 554      * completion of the main response, the final number of additional
 555      * responses is known. Additional responses may be canceled, but given that
 556      * the server does not wait for any acknowledgment before sending the
 557      * response, this must be done quickly to avoid unnecessary data transmission.
 558      *
 559      * <p> {@code MultiProcessor}s are parameterized with a type {@code U} which
 560      * represents some meaningful aggregate of the responses received. This
 561      * would typically be a collection of response or response body objects.
 562      *
 563      * @param <U> a type representing the aggregated results
 564      * @param <T> a type representing all of the response bodies
 565      *
 566      * @since 9
 567      */
 568     public interface MultiProcessor<U,T> {
 569         /**
 570          * Called for the main request and each push promise that is received.
 571          * The first call will always be for the main request that was sent
 572          * by the caller. This {@link HttpRequest} parameter
 573          * represents the initial request or subsequent PUSH_PROMISE. The
 574          * implementation must return an {@code Optional} of {@link BodyHandler} for
 575          * the response body. Different handlers (of the same type) can be returned
 576          * for different pushes within the same multi send. If no handler
 577          * (an empty {@code Optional}) is returned, then the push will be canceled. It is
 578          * an error to not return a valid {@code BodyHandler} for the initial (main) request.
 579          *
 580          * @param request the main request or subsequent push promise
 581          *
 582          * @return an optional body handler
 583          */
 584         Optional<BodyHandler<T>> onRequest(HttpRequest request);


















 585 
 586         /**
 587          * Called for each response received. For each request either one of
 588          * onResponse() or onError() is guaranteed to be called, but not both.
 589          *
 590          * [Note] The reason for switching to this callback interface rather
 591          * than using CompletableFutures supplied to onRequest() is that there
 592          * is a subtle interaction between those CFs and the CF returned from
 593          * completion() (or when onComplete() was called formerly). The completion()
 594          * CF will not complete until after all of the work done by the onResponse()
 595          * calls is done. Whereas if you just create CF's dependent on a supplied
 596          * CF (to onRequest()) then the implementation has no visibility of the
 597          * dependent CFs and can't guarantee to call onComplete() (or complete
 598          * the completion() CF) after the dependent CFs complete.
 599          *
 600          * @param response the response received
 601          */
 602         void onResponse(HttpResponse<T> response);
 603 
 604         /**
 605          * Called if an error occurs receiving a response. For each request
 606          * either one of onResponse() or onError() is guaranteed to be called,
 607          * but not both.
 608          *
 609          * @param request the main request or subsequent push promise
 610          * @param t the Throwable that caused the error
 611          */
 612         void onError(HttpRequest request, Throwable t);
 613 
 614         /**
 615          * Returns a {@link java.util.concurrent.CompletableFuture}{@code <U>}
 616          * which completes when the aggregate result object itself is available.
 617          * It is expected that the returned {@code CompletableFuture} will depend
 618          * on one of the given {@code CompletableFuture<Void}s which themselves complete
 619          * after all individual responses associated with the multi response
 620          * have completed, or after all push promises have been received.


 621          *
 622          * @implNote Implementations might follow the pattern shown below
 623          * <pre>
 624          * {@code
 625          *      CompletableFuture<U> completion(
 626          *              CompletableFuture<Void> onComplete,
 627          *              CompletableFuture<Void> onFinalPushPromise)
 628          *      {
 629          *          return onComplete.thenApply((v) -> {
 630          *              U u = ... instantiate and populate a U instance
 631          *              return u;
 632          *          });
 633          *      }
 634          * }
 635          * </pre>
 636          *
 637          * @param onComplete a CompletableFuture which completes after all
 638          * responses have been received relating to this multi request.
 639          *
 640          * @param onFinalPushPromise CompletableFuture which completes after all
 641          * push promises have been received.
 642          *
 643          * @return the aggregate CF response object
 644          */
 645         CompletableFuture<U> completion(CompletableFuture<Void> onComplete,
 646                 CompletableFuture<Void> onFinalPushPromise);
 647 
 648         /**
 649          * Returns a general purpose handler for multi responses. The aggregated
 650          * result object produced by this handler is a
 651          * {@code Map<HttpRequest,CompletableFuture<HttpResponse<V>>>}. Each
 652          * request (both the original user generated request and each server
 653          * generated push promise) is returned as a key of the map. The value
 654          * corresponding to each key is a
 655          * {@code CompletableFuture<HttpResponse<V>>}.
 656          * <p>
 657          * There are two ways to use these handlers, depending on the value of
 658          * the <i>completion</I> parameter. If completion is true, then the
 659          * aggregated result will be available after all responses have
 660          * themselves completed. If <i>completion</i> is false, then the
 661          * aggregated result will be available immediately after the last push
 662          * promise was received. In the former case, this implies that all the
 663          * CompletableFutures in the map values will have completed. In the
 664          * latter case, they may or may not have completed yet.
 665          * <p>
 666          * The simplest way to use these handlers is to set completion to
 667          * {@code true}, and then all (results) values in the Map will be
 668          * accessible without blocking.
 669          * <p>
 670          * See {@link #asMap(java.util.function.Function, boolean)
 671          * }
 672          * for a code sample of using this interface.
 673          *



 674          * @param <V> the body type used for all responses
 675          * @param pushHandler a function invoked for each request or push
 676          * promise
 677          * @param completion {@code true} if the aggregate CompletableFuture
 678          * completes after all responses have been received, or {@code false}
 679          * after all push promises received.
 680          *
 681          * @return a MultiProcessor
 682          */
 683         public static <V> MultiProcessor<MultiMapResult<V>,V> asMap(
 684             Function<HttpRequest, Optional<HttpResponse.BodyHandler<V>>> pushHandler,
 685                 boolean completion) {
 686 
 687             return new MultiProcessorImpl<V>(pushHandler, completion);

 688         }
 689 
 690         /**
 691          * Returns a general purpose handler for multi responses. This is a
 692          * convenience method which invokes {@link #asMap(java.util.function.Function,boolean)
 693          * asMap(Function, true)} meaning that the aggregate result
 694          * object completes after all responses have been received.
 695          * <p>
 696          * <b>Example usage:</b>
 697          * <br>
 698          * <pre>
 699          * {@code
 700          *          HttpRequest request = HttpRequest.newBuilder()
 701          *                  .uri(URI.create("https://www.foo.com/"))
 702          *                  .GET()
 703          *                  .build();
 704          *
 705          *          HttpClient client = HttpClient.newHttpClient();
 706          *
 707          *          Map<HttpRequest,CompletableFuture<HttpResponse<String>>> results = client
 708          *              .sendAsync(request, MultiProcessor.asMap(
 709          *                  (req) -> Optional.of(HttpResponse.BodyHandler.asString())))
 710          *              .join();
 711          * }</pre>
 712          * <p>
 713          * The lambda in this example is the simplest possible implementation,
 714          * where neither the incoming requests are examined, nor the response
 715          * headers, and every push that the server sends is accepted. When the
 716          * join() call returns, all {@code HttpResponse}s and their associated
 717          * body objects are available.
 718          *
 719          * @param <V> the body type used for all responses
 720          * @param pushHandler a function invoked for each request or push
 721          * promise
 722          * @return a MultiProcessor
 723          */
 724         public static <V> MultiProcessor<MultiMapResult<V>,V> asMap(
 725             Function<HttpRequest, Optional<HttpResponse.BodyHandler<V>>> pushHandler) {
 726 
 727             return asMap(pushHandler, true);
 728         }
 729 
 730     }
 731 }


   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.incubator.http;
  27 
  28 import java.io.IOException;
  29 import java.io.InputStream;
  30 import java.net.URI;
  31 import jdk.incubator.http.ResponseSubscribers.MultiSubscriberImpl;

  32 import static jdk.incubator.http.internal.common.Utils.unchecked;
  33 import static jdk.incubator.http.internal.common.Utils.charsetFrom;
  34 import java.nio.ByteBuffer;
  35 import java.nio.charset.Charset;
  36 import java.nio.channels.FileChannel;
  37 import java.nio.file.OpenOption;
  38 import java.nio.file.Path;
  39 import java.nio.file.Paths;
  40 import java.nio.file.StandardOpenOption;
  41 import java.security.AccessControlContext;
  42 import java.util.Arrays;
  43 import java.util.List;
  44 import java.util.Objects;
  45 import java.util.Optional;
  46 import java.util.concurrent.CompletableFuture;
  47 import java.util.concurrent.CompletionStage;
  48 import java.util.concurrent.Flow;
  49 import java.util.function.Consumer;
  50 import java.util.function.Function;
  51 import javax.net.ssl.SSLParameters;
  52 
  53 /**
  54  * Represents a response to a {@link HttpRequest}.
  55  * {@Incubating}
  56  *
  57  * <p> A {@code HttpResponse} is available when the response status code and
  58  * headers have been received, and typically after the response body has also
  59  * been received. This depends on the response body handler provided when
  60  * sending the request. In all cases, the response body handler is invoked
  61  * before the body is read. This gives applications an opportunity to decide
  62  * how to handle the body.
  63  *
  64  * <p> Methods are provided in this class for accessing the response headers,
  65  * and response body.
  66  *
  67  * <p><b>Response handlers and subscribers</b>
  68  *
  69  * <p> Response bodies are handled at two levels. Application code supplies a
  70  * response handler ({@link BodyHandler}) which may examine the response status
  71  * code and headers, and which then returns a {@link BodySubscriber} to actually
  72  * read (or discard) the body and convert it into some useful Java object type.
  73  * The handler can return one of the pre-defined subscriber types, or a custom
  74  * subscriber, or if the body is to be discarded it can call {@link
  75  * BodySubscriber#discard(Object) discard} and return a subscriber which
  76  * discards the response body. Static implementations of both handlers and
  77  * subscribers are provided in {@linkplain BodyHandler BodyHandler} and
  78  * {@linkplain BodySubscriber BodySubscriber} respectively. In all cases, the
  79  * handler functions provided are convenience implementations which ignore the
  80  * supplied status code and headers and return the relevant pre-defined {@code
  81  * BodySubscriber}.
  82  *
  83  * <p> See {@link BodyHandler} for example usage.
  84  *
  85  * @param <T> the response body type
  86  * @since 9
  87  */
  88 public abstract class HttpResponse<T> {
  89 
  90     /**
  91      * Creates an HttpResponse.
  92      */
  93     protected HttpResponse() { }
  94 
  95     /**
  96      * Returns the status code for this response.
  97      *
  98      * @return the response code
  99      */
 100     public abstract int statusCode();
 101 
 102     /**
 103      * Returns the {@link HttpRequest} corresponding to this response.
 104      *
 105      * <p> This may not be the original request provided by the caller,
 106      * for example, if that request was redirected.
 107      *
 108      * @see #previousResponse()
 109      *
 110      * @return the request
 111      */
 112     public abstract HttpRequest request();
 113 
 114     /**
 115      * Returns an {@code Optional} containing the previous intermediate response
 116      * if one was received. An intermediate response is one that is received
 117      * as a result of redirection or authentication. If no previous response
 118      * was received then an empty {@code Optional} is returned.
 119      *
 120      * @return an Optional containing the HttpResponse, if any.
 121      */
 122     public abstract Optional<HttpResponse<T>> previousResponse();
 123 
 124     /**
 125      * Returns the received response headers.
 126      *
 127      * @return the response headers
 128      */
 129     public abstract HttpHeaders headers();
 130 
 131     /**
 132      * Returns the body. Depending on the type of {@code T}, the returned body
 133      * may represent the body after it was read (such as {@code byte[]}, or










 134      * {@code String}, or {@code Path}) or it may represent an object with
 135      * which the body is read, such as an {@link java.io.InputStream}.
 136      *
 137      * <p> If this {@code HttpResponse} was returned from an invocation of
 138      * {@link #previousResponse()} then this method returns {@code null}
 139      *
 140      * @return the body
 141      */
 142     public abstract T body();
 143 
 144     /**
 145      * Returns the {@link javax.net.ssl.SSLParameters} in effect for this
 146      * response. Returns {@code null} if this is not a HTTPS response.
 147      *
 148      * @return the SSLParameters associated with the response
 149      */
 150     public abstract SSLParameters sslParameters();
 151 
 152     /**
 153      * Returns the {@code URI} that the response was received from. This may be
 154      * different from the request {@code URI} if redirection occurred.
 155      *
 156      * @return the URI of the response
 157      */
 158     public abstract URI uri();
 159 
 160     /**
 161      * Returns the HTTP protocol version that was used for this response.
 162      *
 163      * @return HTTP protocol version
 164      */
 165     public abstract HttpClient.Version version();
 166 
 167 
 168     private static String pathForSecurityCheck(Path path) {
 169         return path.toFile().getPath();
 170     }
 171 
 172     /** A body handler that is further restricted by a given ACC. */
 173     interface UntrustedBodyHandler<T> extends BodyHandler<T> {
 174         void setAccessControlContext(AccessControlContext acc);
 175     }
 176 
 177     /**
 178      * A Path body handler.
 179      *
 180      * Note: Exists mainly too allow setting of the senders ACC post creation of
 181      * the handler.
 182      */
 183     static class PathBodyHandler implements UntrustedBodyHandler<Path> {
 184         private final Path file;
 185         private final OpenOption[]openOptions;
 186         private volatile AccessControlContext acc;
 187 
 188         PathBodyHandler(Path file, OpenOption... openOptions) {
 189             this.file = file;
 190             this.openOptions = openOptions;
 191         }
 192 
 193         @Override
 194         public void setAccessControlContext(AccessControlContext acc) {
 195             this.acc = acc;
 196         }
 197 
 198         @Override
 199         public BodySubscriber<Path> apply(int statusCode, HttpHeaders headers) {
 200             ResponseSubscribers.PathSubscriber bs = (ResponseSubscribers.PathSubscriber)
 201                     BodySubscriber.asFileImpl(file, openOptions);
 202             bs.setAccessControlContext(acc);
 203             return bs;
 204         }
 205     }
 206 
 207     // Similar to Path body handler, but for file download. Supports setting ACC.
 208     static class FileDownloadBodyHandler implements UntrustedBodyHandler<Path> {
 209         private final Path directory;
 210         private final OpenOption[]openOptions;
 211         private volatile AccessControlContext acc;
 212 
 213         FileDownloadBodyHandler(Path directory, OpenOption... openOptions) {
 214             this.directory = directory;
 215             this.openOptions = openOptions;
 216         }
 217 
 218         @Override
 219         public void setAccessControlContext(AccessControlContext acc) {
 220             this.acc = acc;
 221         }
 222 
 223         @Override
 224         public BodySubscriber<Path> apply(int statusCode, HttpHeaders headers) {
 225             String dispoHeader = headers.firstValue("Content-Disposition")
 226                     .orElseThrow(() -> unchecked(new IOException("No Content-Disposition")));
 227             if (!dispoHeader.startsWith("attachment;")) {
 228                 throw unchecked(new IOException("Unknown Content-Disposition type"));
 229             }
 230             int n = dispoHeader.indexOf("filename=");
 231             if (n == -1) {
 232                 throw unchecked(new IOException("Bad Content-Disposition type"));
 233             }
 234             int lastsemi = dispoHeader.lastIndexOf(';');
 235             String disposition;
 236             if (lastsemi < n) {
 237                 disposition = dispoHeader.substring(n + 9);
 238             } else {
 239                 disposition = dispoHeader.substring(n + 9, lastsemi);
 240             }
 241             Path file = Paths.get(directory.toString(), disposition);
 242 
 243             ResponseSubscribers.PathSubscriber bs = (ResponseSubscribers.PathSubscriber)
 244                     BodySubscriber.asFileImpl(file, openOptions);
 245             bs.setAccessControlContext(acc);
 246             return bs;
 247         }
 248     }
 249 
 250     /**
 251      * A handler for response bodies.
 252      * {@Incubating}
 253      *
 254      * <p> This is a function that takes two parameters: the response status code,
 255      * and the response headers, and which returns a {@linkplain BodySubscriber}.
 256      * The function is always called just before the response body is read. Its
 257      * implementation may examine the status code or headers and must decide,
 258      * whether to accept the response body or discard it, and if accepting it,
 259      * exactly how to handle it.
 260      *
 261      * <p> Some pre-defined implementations which do not utilize the status code
 262      * or headers (meaning the body is always accepted) are defined:
 263      * <ul><li>{@link #asByteArray() }</li>
 264      * <li>{@link #asByteArrayConsumer(java.util.function.Consumer)
 265      * asByteArrayConsumer(Consumer)}</li>
 266      * <li>{@link #asString(java.nio.charset.Charset) asString(Charset)}</li>
 267      * <li>{@link #asFile(Path, OpenOption...)
 268      * asFile(Path,OpenOption...)}</li>
 269      * <li>{@link #asFileDownload(java.nio.file.Path,OpenOption...)
 270      * asFileDownload(Path,OpenOption...)}</li>
 271      * <li>{@link #asInputStream() asInputStream()}</li>
 272      * <li>{@link #discard(Object) }</li>
 273      * <li>{@link #buffering(BodyHandler, int)
 274      * buffering(BodyHandler,int)}</li>
 275      * </ul>
 276      *
 277      * <p> These implementations return the equivalent {@link BodySubscriber}.
 278      * Alternatively, the handler can be used to examine the status code
 279      * or headers and return different body subscribers as appropriate.
 280      *
 281      * <p><b>Examples of handler usage</b>
 282      *
 283      * <p> The first example uses one of the predefined handler functions which
 284      * ignores the response headers and status, and always process the response
 285      * body in the same way.
 286      * <pre>
 287      * {@code
 288      *      HttpResponse<Path> resp = HttpRequest
 289      *              .create(URI.create("http://www.foo.com"))
 290      *              .GET()
 291      *              .response(BodyHandler.asFile(Paths.get("/tmp/f")));
 292      * }
 293      * </pre>
 294      * Note, that even though these pre-defined handlers ignore the status code
 295      * and headers, this information is still accessible from the
 296      * {@code HttpResponse} when it is returned.
 297      *
 298      * <p> In the second example, the function returns a different subscriber
 299      * depending on the status code.
 300      * <pre>
 301      * {@code
 302      *      HttpResponse<Path> resp1 = HttpRequest
 303      *              .create(URI.create("http://www.foo.com"))
 304      *              .GET()
 305      *              .response(
 306      *                  (status, headers) -> status == 200
 307      *                      ? BodySubscriber.asFile(Paths.get("/tmp/f"))
 308      *                      : BodySubscriber.discard(Paths.get("/NULL")));
 309      * }
 310      * </pre>
 311      *
 312      * @param <T> the response body type
 313      */
 314     @FunctionalInterface
 315     public interface BodyHandler<T> {
 316 
 317         /**
 318          * Returns a {@link BodySubscriber BodySubscriber} considering the given
 319          * response status code and headers. This method is always called before
 320          * the body is read and its implementation can decide to keep the body
 321          * and store it somewhere, or else discard it by returning the {@code
 322          * BodySubscriber} returned from {@link BodySubscriber#discard(Object)
 323          * discard}.
 324          *
 325          * @param statusCode the HTTP status code received
 326          * @param responseHeaders the response headers received
 327          * @return a body subscriber
 328          */
 329         public BodySubscriber<T> apply(int statusCode, HttpHeaders responseHeaders);
 330 
 331         /**
 332          * Returns a response body handler which discards the response body and
 333          * uses the given value as a replacement for it.
 334          *
 335          * @param <U> the response body type
 336          * @param value the value of U to return as the body, may be {@code null}
 337          * @return a response body handler
 338          */
 339         public static <U> BodyHandler<U> discard(U value) {
 340             return (status, headers) -> BodySubscriber.discard(value);
 341         }
 342 
 343         /**
 344          * Returns a {@code BodyHandler<String>} that returns a
 345          * {@link BodySubscriber BodySubscriber}{@code <String>} obtained from
 346          * {@link BodySubscriber#asString(Charset) BodySubscriber.asString(Charset)}.
 347          * If a charset is provided, the body is decoded using it. If charset is
 348          * {@code null} then the handler tries to determine the character set
 349          * from the {@code Content-encoding} header. If that charset is not
 350          * supported then {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8}
 351          * is used.
 352          *
 353          * @param charset The name of the charset to interpret the body as. If
 354          *                {@code null} then the charset is determined from the
 355          *                <i>Content-encoding</i> header.
 356          * @return a response body handler
 357          */
 358         public static BodyHandler<String> asString(Charset charset) {
 359             return (status, headers) -> {
 360                 if (charset != null) {
 361                     return BodySubscriber.asString(charset);
 362                 }
 363                 return BodySubscriber.asString(charsetFrom(headers));
 364             };
 365         }
 366 
 367         /**
 368          * Returns a {@code BodyHandler<Path>} that returns a
 369          * {@link BodySubscriber BodySubscriber}{@code <Path>} obtained from
 370          * {@link BodySubscriber#asFile(Path, OpenOption...)
 371          * BodySubscriber.asFile(Path,OpenOption...)}.
 372          *
 373          * <p> When the {@code HttpResponse} object is returned, the body has
 374          * been completely written to the file, and {@link #body()} returns a
 375          * reference to its {@link Path}.
 376          *
 377          * @param file the filename to store the body in
 378          * @param openOptions any options to use when opening/creating the file
 379          * @return a response body handler
 380          * @throws SecurityException If a security manager has been installed
 381          *          and it denies {@link SecurityManager#checkWrite(String)
 382          *          write access} to the file. The {@link
 383          *          SecurityManager#checkDelete(String) checkDelete} method is
 384          *          invoked to check delete access if the file is opened with
 385          *          the {@code DELETE_ON_CLOSE} option.
 386          */
 387         public static BodyHandler<Path> asFile(Path file, OpenOption... openOptions) {
 388             Objects.requireNonNull(file);
 389             SecurityManager sm = System.getSecurityManager();
 390             if (sm != null) {
 391                 String fn = pathForSecurityCheck(file);
 392                 sm.checkWrite(fn);
 393                 List<OpenOption> opts = Arrays.asList(openOptions);
 394                 if (opts.contains(StandardOpenOption.DELETE_ON_CLOSE))
 395                     sm.checkDelete(fn);
 396                 if (opts.contains(StandardOpenOption.READ))
 397                     sm.checkRead(fn);
 398             }
 399             return new PathBodyHandler(file, openOptions);
 400         }
 401 
 402         /**
 403          * Returns a {@code BodyHandler<Path>} that returns a
 404          * {@link BodySubscriber BodySubscriber}{@code <Path>} obtained from
 405          * {@link BodySubscriber#asFile(Path) BodySubscriber.asFile(Path)}.
 406          *
 407          * <p> When the {@code HttpResponse} object is returned, the body has
 408          * been completely written to the file, and {@link #body()} returns a
 409          * reference to its {@link Path}.
 410          *
 411          * @param file the file to store the body in
 412          * @return a response body handler
 413          * @throws SecurityException if a security manager has been installed
 414          *          and it denies {@link SecurityManager#checkWrite(String)
 415          *          write access} to the file
 416          */
 417         public static BodyHandler<Path> asFile(Path file) {
 418             return BodyHandler.asFile(file, StandardOpenOption.CREATE,
 419                                             StandardOpenOption.WRITE);
 420         }
 421 
 422         /**
 423          * Returns a {@code BodyHandler<Path>} that returns a
 424          * {@link BodySubscriber BodySubscriber}&lt;{@link Path}&gt;
 425          * where the download directory is specified, but the filename is
 426          * obtained from the {@code Content-Disposition} response header. The
 427          * {@code Content-Disposition} header must specify the <i>attachment</i>
 428          * type and must also contain a <i>filename</i> parameter. If the
 429          * filename specifies multiple path components only the final component
 430          * is used as the filename (with the given directory name).
 431          *
 432          * <p> When the {@code HttpResponse} object is returned, the body has
 433          * been completely written to the file and {@link #body()} returns a
 434          * {@code Path} object for the file. The returned {@code Path} is the
 435          * combination of the supplied directory name and the file name supplied
 436          * by the server. If the destination directory does not exist or cannot
 437          * be written to, then the response will fail with an {@link IOException}.
 438          *
 439          * @param directory the directory to store the file in
 440          * @param openOptions open options
 441          * @return a response body handler
 442          * @throws SecurityException If a security manager has been installed
 443          *          and it denies {@link SecurityManager#checkWrite(String)
 444          *          write access} to the file. The {@link
 445          *          SecurityManager#checkDelete(String) checkDelete} method is
 446          *          invoked to check delete access if the file is opened with
 447          *          the {@code DELETE_ON_CLOSE} option.
 448          */
 449          //####: check if the dir exists and is writable??
 450         public static BodyHandler<Path> asFileDownload(Path directory,
 451                                                        OpenOption... openOptions) {
 452             Objects.requireNonNull(directory);
 453             SecurityManager sm = System.getSecurityManager();
 454             if (sm != null) {
 455                 String fn = pathForSecurityCheck(directory);
 456                 sm.checkWrite(fn);
 457                 List<OpenOption> opts = Arrays.asList(openOptions);
 458                 if (opts.contains(StandardOpenOption.DELETE_ON_CLOSE))
 459                     sm.checkDelete(fn);
 460                 if (opts.contains(StandardOpenOption.READ))
 461                     sm.checkRead(fn);
 462             }
 463             return new FileDownloadBodyHandler(directory, openOptions);
 464         }
 465 
 466         /**
 467          * Returns a {@code BodyHandler<InputStream>} that returns a
 468          * {@link BodySubscriber BodySubscriber}{@code <InputStream>} obtained
 469          * from {@link BodySubscriber#asInputStream() BodySubscriber.asInputStream}.
 470          *
 471          * <p> When the {@code HttpResponse} object is returned, the response
 472          * headers will have been completely read, but the body may not have
 473          * been fully received yet. The {@link #body()} method returns an
 474          * {@link InputStream} from which the body can be read as it is received.
 475          *
 476          * @apiNote See {@link BodySubscriber#asInputStream()} for more information.
 477          *


 478          * @return a response body handler
 479          */
 480         public static BodyHandler<InputStream> asInputStream() {
 481             return (status, headers) -> BodySubscriber.asInputStream();
 482         }
 483 
 484         /**
 485          * Returns a {@code BodyHandler<Void>} that returns a
 486          * {@link BodySubscriber BodySubscriber}{@code <Void>} obtained from
 487          * {@link BodySubscriber#asByteArrayConsumer(Consumer)
 488          * BodySubscriber.asByteArrayConsumer(Consumer)}.
 489          *
 490          * <p> When the {@code HttpResponse} object is returned, the body has
 491          * been completely written to the consumer.
 492          *
 493          * @param consumer a Consumer to accept the response body
 494          * @return a response body handler
 495          */
 496         public static BodyHandler<Void> asByteArrayConsumer(Consumer<Optional<byte[]>> consumer) {
 497             return (status, headers) -> BodySubscriber.asByteArrayConsumer(consumer);
 498         }
 499 
 500         /**
 501          * Returns a {@code BodyHandler<byte[]>} that returns a
 502          * {@link BodySubscriber BodySubscriber}&lt;{@code byte[]}&gt; obtained
 503          * from {@link BodySubscriber#asByteArray() BodySubscriber.asByteArray()}.
 504          *
 505          * <p> When the {@code HttpResponse} object is returned, the body has
 506          * been completely written to the byte array.
 507          *
 508          * @return a response body handler
 509          */
 510         public static BodyHandler<byte[]> asByteArray() {
 511             return (status, headers) -> BodySubscriber.asByteArray();
 512         }
 513 
 514         /**
 515          * Returns a {@code BodyHandler<String>} that returns a
 516          * {@link BodySubscriber BodySubscriber}{@code <String>} obtained from
 517          * {@link BodySubscriber#asString(java.nio.charset.Charset)
 518          * BodySubscriber.asString(Charset)}. The body is
 519          * decoded using the character set specified in
 520          * the {@code Content-encoding} response header. If there is no such
 521          * header, or the character set is not supported, then
 522          * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
 523          *
 524          * <p> When the {@code HttpResponse} object is returned, the body has
 525          * been completely written to the string.
 526          *
 527          * @return a response body handler
 528          */
 529         public static BodyHandler<String> asString() {
 530             return (status, headers) -> BodySubscriber.asString(charsetFrom(headers));
 531         }
 532 
 533         /**
 534          * Returns a {@code BodyHandler} which, when invoked, returns a {@linkplain
 535          * BodySubscriber#buffering(BodySubscriber,int) buffering BodySubscriber}
 536          * that buffers data before delivering it to the downstream subscriber.
 537          * These {@code BodySubscriber} instances are created by calling
 538          * {@linkplain BodySubscriber#buffering(BodySubscriber,int)
 539          * BodySubscriber.buffering} with a subscriber obtained from the given
 540          * downstream handler and the {@code bufferSize} parameter.
 541          *
 542          * @param downstreamHandler the downstream handler
 543          * @param bufferSize the buffer size parameter passed to {@linkplain
 544          *        BodySubscriber#buffering(BodySubscriber,int) BodySubscriber.buffering}
 545          * @return a body handler
 546          * @throws IllegalArgumentException if {@code bufferSize <= 0}
 547          */
 548          public static <T> BodyHandler<T> buffering(BodyHandler<T> downstreamHandler,
 549                                                     int bufferSize) {
 550              if (bufferSize <= 0)
 551                  throw new IllegalArgumentException("must be greater than 0");
 552              return (status, headers) -> BodySubscriber
 553                      .buffering(downstreamHandler.apply(status, headers),
 554                                 bufferSize);
 555          }
 556     }
 557 
 558     /**
 559      * A subscriber for response bodies.
 560      * {@Incubating}
 561      *
 562      * <p> The object acts as a {@link Flow.Subscriber}&lt;{@link List}&lt;{@link
 563      * ByteBuffer}&gt;&gt; to the HTTP client implementation, which publishes
 564      * unmodifiable lists of ByteBuffers containing the response body. The Flow
 565      * of data, as well as the order of ByteBuffers in the Flow lists, is a
 566      * strictly ordered representation of the response body. Both the Lists and
 567      * the ByteBuffers, once passed to the subscriber, are no longer used by the
 568      * HTTP client. The subscriber converts the incoming buffers of data to some
 569      * user-defined object type {@code T}.
 570      *
 571      * <p> The {@link #getBody()} method returns a {@link CompletionStage}{@code
 572      * <T>} that provides the response body object. The {@code CompletionStage}
 573      * must be obtainable at any time. When it completes depends on the nature
 574      * of type {@code T}. In many cases, when {@code T} represents the entire
 575      * body after being read then it completes after the body has been read. If
 576      * {@code T} is a streaming type such as {@link java.io.InputStream} then it
 577      * completes before the body has been read, because the calling code uses it
 578      * to consume the data.
 579      *
 580      * @apiNote To ensure that all resources associated with the
 581      * corresponding exchange are properly released, an implementation
 582      * of {@code BodySubscriber} must ensure to {@linkplain
 583      * Flow.Subscription#request request} more data until {@link
 584      * #onComplete() onComplete} or {@link #onError(Throwable) onError}
 585      * are signalled, or {@linkplain Flow.Subscription#request cancel} its
 586      * {@linkplain #onSubscribe(Flow.Subscription) subscription}
 587      * if unable or unwilling to do so.
 588      * Calling {@code cancel} before exhausting the data may cause
 589      * the underlying HTTP connection to be closed and prevent it
 590      * from being reused for subsequent operations.
 591      *
 592      * @param <T> the response body type
 593      */
 594     public interface BodySubscriber<T>
 595             extends Flow.Subscriber<List<ByteBuffer>> {
 596 
 597         /**
 598          * Returns a {@code CompletionStage} which when completed will return
 599          * the response body object.
 600          *
 601          * @return a CompletionStage for the response body
 602          */
 603         public CompletionStage<T> getBody();
 604 
 605         /**
 606          * Returns a body subscriber which stores the response body as a {@code
 607          * String} converted using the given {@code Charset}.
 608          *
 609          * <p> The {@link HttpResponse} using this subscriber is available after
 610          * the entire response has been read.
 611          *
 612          * @param charset the character set to convert the String with
 613          * @return a body subscriber
 614          */
 615         public static BodySubscriber<String> asString(Charset charset) {
 616             return new ResponseSubscribers.ByteArraySubscriber<>(
 617                     bytes -> new String(bytes, charset)
 618             );
 619         }
 620 
 621         /**
 622          * Returns a {@code BodySubscriber} which stores the response body as a
 623          * byte array.



 624          *
 625          * <p> The {@link HttpResponse} using this subscriber is available after
 626          * the entire response has been read.
 627          *
 628          * @return a body subscriber
 629          */
 630         public static BodySubscriber<byte[]> asByteArray() {
 631             return new ResponseSubscribers.ByteArraySubscriber<>(
 632                     Function.identity() // no conversion
 633             );
 634         }
 635 
 636         // no security check
 637         private static BodySubscriber<Path> asFileImpl(Path file, OpenOption... openOptions) {
 638             return new ResponseSubscribers.PathSubscriber(file, openOptions);
 639         }
 640 
 641         /**
 642          * Returns a {@code BodySubscriber} which stores the response body in a
 643          * file opened with the given options and name. The file will be opened
 644          * with the given options using {@link FileChannel#open(Path,OpenOption...)
 645          * FileChannel.open} just before the body is read. Any exception thrown
 646          * will be returned or thrown from {@link HttpClient#send(HttpRequest,
 647          * BodyHandler) HttpClient::send} or {@link HttpClient#sendAsync(HttpRequest,
 648          * BodyHandler) HttpClient::sendAsync} as appropriate.
 649          *
 650          * <p> The {@link HttpResponse} using this subscriber is available after
 651          * the entire response has been read.



 652          *
 653          * @param file the file to store the body in
 654          * @param openOptions the list of options to open the file with
 655          * @return a body subscriber
 656          * @throws SecurityException If a security manager has been installed
 657          *          and it denies {@link SecurityManager#checkWrite(String)
 658          *          write access} to the file. The {@link
 659          *          SecurityManager#checkDelete(String) checkDelete} method is
 660          *          invoked to check delete access if the file is opened with the
 661          *          {@code DELETE_ON_CLOSE} option.
 662          */
 663         public static BodySubscriber<Path> asFile(Path file, OpenOption... openOptions) {
 664             Objects.requireNonNull(file);
 665             SecurityManager sm = System.getSecurityManager();
 666             if (sm != null) {
 667                 String fn = pathForSecurityCheck(file);
 668                 sm.checkWrite(fn);
 669                 List<OpenOption> opts = Arrays.asList(openOptions);
 670                 if (opts.contains(StandardOpenOption.DELETE_ON_CLOSE))
 671                     sm.checkDelete(fn);
 672                 if (opts.contains(StandardOpenOption.READ))
 673                     sm.checkRead(fn);
 674             }
 675             return asFileImpl(file, openOptions);
 676         }
 677 
 678         /**
 679          * Returns a {@code BodySubscriber} which stores the response body in a
 680          * file opened with the given name. Has the same effect as calling
 681          * {@link #asFile(Path, OpenOption...) asFile} with the standard open
 682          * options {@code CREATE} and {@code WRITE}
 683          *
 684          * <p> The {@link HttpResponse} using this subscriber is available after
 685          * the entire response has been read.
 686          *
 687          * @param file the file to store the body in
 688          * @return a body subscriber
 689          * @throws SecurityException if a security manager has been installed
 690          *          and it denies {@link SecurityManager#checkWrite(String)
 691          *          write access} to the file
 692          */
 693         public static BodySubscriber<Path> asFile(Path file) {
 694             return asFile(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
 695         }
 696 
 697         /**
 698          * Returns a {@code BodySubscriber} which provides the incoming body
 699          * data to the provided Consumer of {@code Optional<byte[]>}. Each
 700          * call to {@link Consumer#accept(java.lang.Object) Consumer.accept()}
 701          * will contain a non empty {@code Optional}, except for the final
 702          * invocation after all body data has been read, when the {@code
 703          * Optional} will be empty.
 704          *
 705          * <p> The {@link HttpResponse} using this subscriber is available after
 706          * the entire response has been read.
 707          *
 708          * @param consumer a Consumer of byte arrays
 709          * @return a BodySubscriber
 710          */
 711         public static BodySubscriber<Void> asByteArrayConsumer(Consumer<Optional<byte[]>> consumer) {
 712             return new ResponseSubscribers.ConsumerSubscriber(consumer);
 713         }
 714 
 715         /**
 716          * Returns a {@code BodySubscriber} which streams the response body as
 717          * an {@link InputStream}.





 718          *
 719          * <p> The {@link HttpResponse} using this subscriber is available
 720          * immediately after the response headers have been read, without
 721          * requiring to wait for the entire body to be processed. The response
 722          * body can then be read directly from the {@link InputStream}.
 723          *
 724          * @apiNote To ensure that all resources associated with the
 725          * corresponding exchange are properly released the caller must
 726          * ensure to either read all bytes until EOF is reached, or call
 727          * {@link InputStream#close} if it is unable or unwilling to do so.
 728          * Calling {@code close} before exhausting the stream may cause
 729          * the underlying HTTP connection to be closed and prevent it
 730          * from being reused for subsequent operations.
 731          *
 732          * @return a body subscriber that streams the response body as an
 733          *         {@link InputStream}.
 734          */
 735         public static BodySubscriber<InputStream> asInputStream() {
 736             return new ResponseSubscribers.HttpResponseInputStream();


 737         }
 738 
 739         /**
 740          * Returns a response subscriber which discards the response body. The
 741          * supplied value is the value that will be returned from
 742          * {@link HttpResponse#body()}.
 743          *
 744          * @param <U> The type of the response body
 745          * @param value the value to return from HttpResponse.body(), may be {@code null}
 746          * @return a {@code BodySubscriber}
 747          */
 748         public static <U> BodySubscriber<U> discard(U value) {
 749             return new ResponseSubscribers.NullSubscriber<>(Optional.ofNullable(value));
 750         }
 751 
 752         /**
 753          * Returns a {@code BodySubscriber} which buffers data before delivering
 754          * it to the given downstream subscriber. The subscriber guarantees to
 755          * deliver {@code buffersize} bytes of data to each invocation of the
 756          * downstream's {@linkplain #onNext(Object) onNext} method, except for
 757          * the final invocation, just before {@linkplain #onComplete() onComplete}
 758          * is invoked. The final invocation of {@code onNext} may contain fewer
 759          * than {@code buffersize} bytes.
 760          *
 761          * <p> The returned subscriber delegates its {@link #getBody()} method
 762          * to the downstream subscriber.
 763          *
 764          * @param downstream the downstream subscriber
 765          * @param bufferSize the buffer size
 766          * @return a buffering body subscriber
 767          * @throws IllegalArgumentException if {@code bufferSize <= 0}
 768          */
 769          public static <T> BodySubscriber<T> buffering(BodySubscriber<T> downstream,
 770                                                        int bufferSize) {
 771              if (bufferSize <= 0)
 772                  throw new IllegalArgumentException("must be greater than 0");
 773              return new BufferingSubscriber<T>(downstream, bufferSize);
 774          }
 775     }
 776 
 777     /**
 778      * A response subscriber for a HTTP/2 multi response.
 779      * {@Incubating}
 780      *
 781      * <p> A multi response comprises a main response, and zero or more additional
 782      * responses. Each additional response is sent by the server in response to
 783      * requests (PUSH_PROMISEs) that the server also generates. Additional responses are
 784      * typically resources that the server expects the client will need which
 785      * are related to the initial request.
 786      * <p>
 787      * Note. Instead of implementing this interface, applications should consider
 788      * first using the mechanism (built on this interface) provided by
 789      * {@link MultiSubscriber#asMap(java.util.function.Function, boolean)
 790      * MultiSubscriber.asMap()} which is a slightly simplified, but also
 791      * general purpose interface.
 792      * <p>
 793      * The server generated requests are also known as <i>push promises</i>.
 794      * The server is permitted to send any number of these requests up to the
 795      * point where the main response is fully received. Therefore, after
 796      * completion of the main response, the final number of additional
 797      * responses is known. Additional responses may be canceled, but given that
 798      * the server does not wait for any acknowledgment before sending the
 799      * response, this must be done quickly to avoid unnecessary data transmission.
 800      *
 801      * <p> {@code MultiSubscriber}s are parameterized with a type {@code U} which
 802      * represents some meaningful aggregate of the responses received. This
 803      * would typically be a collection of response or response body objects.
 804      *
 805      * @param <U> a type representing the aggregated results
 806      * @param <T> a type representing all of the response bodies
 807      *
 808      * @since 9
 809      */
 810     public interface MultiSubscriber<U,T> {
 811         /**
 812          * Called for the main request from the user. This {@link HttpRequest}
 813          * parameter is the request that was supplied to {@link
 814          * HttpClient#sendAsync(HttpRequest, MultiSubscriber)}. The
 815          * implementation must return an {@link BodyHandler} for the response
 816          * body.




 817          *
 818          * @param request the request
 819          *
 820          * @return an optional body handler
 821          */
 822         BodyHandler<T> onRequest(HttpRequest request);
 823 
 824         /**
 825          * Called for each push promise that is received. The {@link HttpRequest}
 826          * parameter represents the PUSH_PROMISE. The implementation must return
 827          * an {@code Optional} of {@link BodyHandler} for the response body.
 828          * Different handlers (of the same type) can be returned for different
 829          * pushes within the same multi send. If no handler (an empty {@code
 830          * Optional}) is returned, then the push will be canceled. If required,
 831          * the {@code CompletableFuture<Void>} supplied to the {@code
 832          * onFinalPushPromise} parameter of {@link
 833          * #completion(CompletableFuture, CompletableFuture)} can be used to
 834          * determine when the final PUSH_PROMISE is received.
 835          *
 836          * @param pushPromise the push promise
 837          *
 838          * @return an optional body handler
 839          */
 840         Optional<BodyHandler<T>> onPushPromise(HttpRequest pushPromise);
 841 
 842         /**
 843          * Called for each response received. For each request either one of
 844          * onResponse() or onError() is guaranteed to be called, but not both.
 845          *
 846          * <p> Note: The reason for switching to this callback interface rather
 847          * than using CompletableFutures supplied to onRequest() is that there
 848          * is a subtle interaction between those CFs and the CF returned from
 849          * completion() (or when onComplete() was called formerly). The completion()
 850          * CF will not complete until after all of the work done by the onResponse()
 851          * calls is done. Whereas if you just create CF's dependent on a supplied
 852          * CF (to onRequest()) then the implementation has no visibility of the
 853          * dependent CFs and can't guarantee to call onComplete() (or complete
 854          * the completion() CF) after the dependent CFs complete.
 855          *
 856          * @param response the response received
 857          */
 858         void onResponse(HttpResponse<T> response);
 859 
 860         /**
 861          * Called if an error occurs receiving a response. For each request
 862          * either one of onResponse() or onError() is guaranteed to be called,
 863          * but not both.
 864          *
 865          * @param request the main request or subsequent push promise
 866          * @param t the Throwable that caused the error
 867          */
 868         void onError(HttpRequest request, Throwable t);
 869 
 870         /**
 871          * Returns a {@link java.util.concurrent.CompletableFuture}{@code <U>}
 872          * which completes when the aggregate result object itself is available.
 873          * It is expected that the returned {@code CompletableFuture} will depend
 874          * on one of the given {@code CompletableFuture<Void}s which themselves
 875          * complete after all individual responses associated with the multi
 876          * response have completed, or after all push promises have been received.
 877          * This method is called after {@link #onRequest(HttpRequest)} but
 878          * before any other methods.
 879          *
 880          * @implNote Implementations might follow the pattern shown below
 881          * <pre>
 882          * {@code
 883          *      CompletableFuture<U> completion(
 884          *              CompletableFuture<Void> onComplete,
 885          *              CompletableFuture<Void> onFinalPushPromise)
 886          *      {
 887          *          return onComplete.thenApply((v) -> {
 888          *              U u = ... instantiate and populate a U instance
 889          *              return u;
 890          *          });
 891          *      }
 892          * }
 893          * </pre>
 894          *
 895          * @param onComplete a CompletableFuture which completes after all
 896          * responses have been received relating to this multi request.
 897          *
 898          * @param onFinalPushPromise CompletableFuture which completes after all
 899          * push promises have been received.
 900          *
 901          * @return the aggregate CF response object
 902          */
 903         CompletableFuture<U> completion(CompletableFuture<Void> onComplete,
 904                 CompletableFuture<Void> onFinalPushPromise);
 905 
 906         /**
 907          * Returns a general purpose handler for multi responses. The aggregated
 908          * result object produced by this handler is a
 909          * {@code Map<HttpRequest,CompletableFuture<HttpResponse<V>>>}. Each
 910          * request (both the original user generated request and each server
 911          * generated push promise) is returned as a key of the map. The value
 912          * corresponding to each key is a
 913          * {@code CompletableFuture<HttpResponse<V>>}.
 914          *
 915          * <p> There are two ways to use these handlers, depending on the value
 916          * of the <i>completion</I> parameter. If completion is true, then the
 917          * aggregated result will be available after all responses have
 918          * themselves completed. If <i>completion</i> is false, then the
 919          * aggregated result will be available immediately after the last push
 920          * promise was received. In the former case, this implies that all the
 921          * CompletableFutures in the map values will have completed. In the
 922          * latter case, they may or may not have completed yet.
 923          *
 924          * <p> The simplest way to use these handlers is to set completion to
 925          * {@code true}, and then all (results) values in the Map will be
 926          * accessible without blocking.
 927          * <p>
 928          * See {@link #asMap(java.util.function.Function, boolean)}

 929          * for a code sample of using this interface.
 930          *
 931          * <p> See {@link #asMap(Function, boolean)} for a code sample of using
 932          * this interface.
 933          *
 934          * @param <V> the body type used for all responses
 935          * @param reqHandler a function invoked for the user's request and each
 936          *                   push promise
 937          * @param completion {@code true} if the aggregate CompletableFuture
 938          *                   completes after all responses have been received,
 939          *                   or {@code false} after all push promises received
 940          *
 941          * @return a MultiSubscriber
 942          */
 943         public static <V> MultiSubscriber<MultiMapResult<V>,V> asMap(
 944                 Function<HttpRequest, Optional<HttpResponse.BodyHandler<V>>> reqHandler,
 945                 boolean completion) {
 946             return new MultiSubscriberImpl<V>(reqHandler.andThen(optv -> optv.get()),
 947                                               reqHandler,
 948                                               completion);
 949         }
 950 
 951         /**
 952          * Returns a general purpose handler for multi responses. This is a
 953          * convenience method which invokes {@link #asMap(Function,boolean)
 954          * asMap(Function, true)} meaning that the aggregate result
 955          * object completes after all responses have been received.
 956          *
 957          * <p><b>Example usage:</b>
 958          * <br>
 959          * <pre>
 960          * {@code
 961          *          HttpRequest request = HttpRequest.newBuilder()
 962          *                  .uri(URI.create("https://www.foo.com/"))
 963          *                  .GET()
 964          *                  .build();
 965          *
 966          *          HttpClient client = HttpClient.newHttpClient();
 967          *
 968          *          Map<HttpRequest,CompletableFuture<HttpResponse<String>>> results = client
 969          *              .sendAsync(request, MultiSubscriber.asMap(
 970          *                  (req) -> Optional.of(HttpResponse.BodyHandler.asString())))
 971          *              .join();
 972          * }</pre>
 973          *
 974          * <p> The lambda in this example is the simplest possible implementation,
 975          * where neither the incoming requests are examined, nor the response
 976          * headers, and every push that the server sends is accepted. When the
 977          * join() call returns, all {@code HttpResponse}s and their associated
 978          * body objects are available.
 979          *
 980          * @param <V> the body type used for all responses
 981          * @param reqHandler a function invoked for each push promise and the
 982          *                   main request
 983          * @return a MultiSubscriber
 984          */
 985         public static <V> MultiSubscriber<MultiMapResult<V>,V> asMap(
 986                 Function<HttpRequest, Optional<HttpResponse.BodyHandler<V>>> reqHandler) {
 987 
 988             return asMap(reqHandler, true);
 989         }
 990 
 991     }
 992 }
< prev index next >