1 /*
   2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   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.net.URI;
  30 import jdk.incubator.http.ResponseProcessors.MultiProcessorImpl;
  31 import static jdk.incubator.http.internal.common.Utils.unchecked;
  32 import static jdk.incubator.http.internal.common.Utils.charsetFrom;
  33 import java.nio.ByteBuffer;
  34 import java.nio.charset.Charset;
  35 import java.nio.file.OpenOption;
  36 import java.nio.file.Path;
  37 import java.nio.file.Paths;
  38 import java.nio.file.StandardOpenOption;
  39 import java.util.List;
  40 import java.util.Optional;
  41 import java.util.concurrent.CompletableFuture;
  42 import java.util.concurrent.CompletionStage;
  43 import java.util.concurrent.Flow;
  44 import java.util.function.Consumer;
  45 import java.util.function.Function;
  46 import javax.net.ssl.SSLParameters;
  47 
  48 /**
  49  * Represents a response to a {@link HttpRequest}.
  50  * {@Incubating}
  51  *
  52  * <p>A {@code HttpResponse} is available when the response status code and
  53  * headers have been received, and typically after the response body has also
  54  * been received. This depends on the response body handler provided when
  55  * sending the request. In all cases, the response body handler is invoked
  56  * before the body is read. This gives applications an opportunity to decide
  57  * how to handle the body.
  58  *
  59  * <p> Methods are provided in this class for accessing the response headers,
  60  * and response body.
  61  * <p>
  62  * <b>Response handlers and processors</b>
  63  * <p>
  64  * Response bodies are handled at two levels. Application code supplies a response
  65  * handler ({@link BodyHandler}) which may examine the response status code
  66  * and headers, and which then returns a {@link BodyProcessor} to actually read
  67  * (or discard) the body and convert it into some useful Java object type. The handler
  68  * can return one of the pre-defined processor types, or a custom processor, or
  69  * if the body is to be discarded, it can call {@link BodyProcessor#discard(Object)
  70  * BodyProcessor.discard()} and return a processor which discards the response body.
  71  * Static implementations of both handlers and processors are provided in
  72  * {@link BodyHandler BodyHandler} and {@link BodyProcessor BodyProcessor} respectively.
  73  * In all cases, the handler functions provided are convenience implementations
  74  * which ignore the supplied status code and
  75  * headers and return the relevant pre-defined {@code BodyProcessor}.
  76  * <p>
  77  * See {@link BodyHandler} for example usage.
  78  *
  79  * @param <T> the response body type
  80  * @since 9
  81  */
  82 public abstract class HttpResponse<T> {
  83 
  84     /**
  85      * Creates an HttpResponse.
  86      */
  87     protected HttpResponse() { }
  88 
  89     /**
  90      * Returns the status code for this response.
  91      *
  92      * @return the response code
  93      */
  94     public abstract int statusCode();
  95 
  96     /**
  97      * Returns the initial {@link HttpRequest} that initiated the exchange.
  98      *
  99      * @return the request
 100      */
 101     public abstract HttpRequest request();
 102 
 103     /**
 104      * Returns the final {@link HttpRequest} that was sent on the wire for the
 105      * exchange ( may, or may not, be the same as the initial request ).
 106      *
 107      * @return the request
 108      */
 109     public abstract HttpRequest finalRequest();
 110 
 111     /**
 112      * Returns the received response headers.
 113      *
 114      * @return the response headers
 115      */
 116     public abstract HttpHeaders headers();
 117 
 118     /**
 119      * Returns the received response trailers, if there are any, when they
 120      * become available. For many response processor types this will be at the same
 121      * time as the {@code HttpResponse} itself is available. In such cases, the
 122      * returned {@code CompletableFuture} will be already completed.
 123      *
 124      * @return a CompletableFuture of the response trailers (may be empty)
 125      */
 126     public abstract CompletableFuture<HttpHeaders> trailers();
 127 
 128     /**
 129      * Returns the body. Depending on the type of {@code T}, the returned body may
 130      * represent the body after it was read (such as {@code byte[]}, or
 131      * {@code String}, or {@code Path}) or it may represent an object with
 132      * which the body is read, such as an {@link java.io.InputStream}.
 133      *
 134      * @return the body
 135      */
 136     public abstract T body();
 137 
 138     /**
 139      * Returns the {@link javax.net.ssl.SSLParameters} in effect for this
 140      * response. Returns {@code null} if this is not a HTTPS response.
 141      *
 142      * @return the SSLParameters associated with the response
 143      */
 144     public abstract SSLParameters sslParameters();
 145 
 146     /**
 147      * Returns the {@code URI} that the response was received from. This may be
 148      * different from the request {@code URI} if redirection occurred.
 149      *
 150      * @return the URI of the response
 151      */
 152     public abstract URI uri();
 153 
 154     /**
 155      * Returns the HTTP protocol version that was used for this response.
 156      *
 157      * @return HTTP protocol version
 158      */
 159     public abstract HttpClient.Version version();
 160 
 161     /**
 162      * A handler for response bodies.
 163      * {@Incubating}
 164      * <p>
 165      * This is a function that takes two parameters: the response status code,
 166      * and the response headers, and which returns a {@link BodyProcessor}.
 167      * The function is always called just before the response body is read. Its
 168      * implementation may examine the status code or headers and must decide,
 169      * whether to accept the response body or discard it, and if accepting it,
 170      * exactly how to handle it.
 171      * <p>
 172      * Some pre-defined implementations which do not utilize the status code
 173      * or headers (meaning the body is always accepted) are defined:
 174      * <ul><li>{@link #asByteArray() }</li>
 175      * <li>{@link #asByteArrayConsumer(java.util.function.Consumer)
 176      * asByteArrayConsumer(Consumer)}</li>
 177      * <li>{@link #asFileDownload(java.nio.file.Path,OpenOption...)
 178      * asFileDownload(Path,OpenOption...)}</li>
 179      * <li>{@link #discard(Object) }</li>
 180      * <li>{@link #asString(java.nio.charset.Charset)
 181      * asString(Charset)}</li></ul>
 182      * <p>
 183      * These implementations return the equivalent {@link BodyProcessor}.
 184      * Alternatively, the handler can be used to examine the status code
 185      * or headers and return different body processors as appropriate.
 186      * <p>
 187      * <b>Examples of handler usage</b>
 188      * <p>
 189      * The first example uses one of the predefined handler functions which
 190      * ignore the response headers and status, and always process the response
 191      * body in the same way.
 192      * <pre>
 193      * {@code
 194      *      HttpResponse<Path> resp = HttpRequest
 195      *              .create(URI.create("http://www.foo.com"))
 196      *              .GET()
 197      *              .response(BodyHandler.asFile(Paths.get("/tmp/f")));
 198      * }
 199      * </pre>
 200      * Note, that even though these pre-defined handlers ignore the status code
 201      * and headers, this information is still accessible from the {@code HttpResponse}
 202      * when it is returned.
 203      * <p>
 204      * In the second example, the function returns a different processor depending
 205      * on the status code.
 206      * <pre>
 207      * {@code
 208      *      HttpResponse<Path> resp1 = HttpRequest
 209      *              .create(URI.create("http://www.foo.com"))
 210      *              .GET()
 211      *              .response(
 212      *                  (status, headers) -> status == 200
 213      *                      ? BodyProcessor.asFile(Paths.get("/tmp/f"))
 214      *                      : BodyProcessor.discard(Paths.get("/NULL")));
 215      * }
 216      * </pre>
 217      *
 218      * @param <T> the response body type.
 219      */
 220     @FunctionalInterface
 221     public interface BodyHandler<T> {
 222 
 223         /**
 224          * Returns a {@link BodyProcessor BodyProcessor} considering the given response status
 225          * code and headers. This method is always called before the body is read
 226          * and its implementation can decide to keep the body and store it somewhere
 227          * or else discard it, by  returning the {@code BodyProcessor} returned
 228          * from {@link BodyProcessor#discard(java.lang.Object) discard()}.
 229          *
 230          * @param statusCode the HTTP status code received
 231          * @param responseHeaders the response headers received
 232          * @return a response body handler
 233          */
 234         public BodyProcessor<T> apply(int statusCode, HttpHeaders responseHeaders);
 235 
 236         /**
 237          * Returns a response body handler which discards the response body and
 238          * uses the given value as a replacement for it.
 239          *
 240          * @param <U> the response body type
 241          * @param value the value of U to return as the body
 242          * @return a response body handler
 243          */
 244         public static <U> BodyHandler<U> discard(U value) {
 245             return (status, headers) -> BodyProcessor.discard(value);
 246         }
 247 
 248         /**
 249          * Returns a {@code BodyHandler<String>} that returns a
 250          * {@link BodyProcessor BodyProcessor}{@code <String>} obtained from
 251          * {@link BodyProcessor#asString(java.nio.charset.Charset)
 252          * BodyProcessor.asString(Charset)}. If a charset is provided, the
 253          * body is decoded using it. If charset is {@code null} then the processor
 254          * tries to determine the character set from the {@code Content-encoding}
 255          * header. If that charset is not supported then
 256          * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
 257          *
 258          * @param charset the name of the charset to interpret the body as. If
 259          * {@code null} then charset determined from Content-encoding header
 260          * @return a response body handler
 261          */
 262         public static BodyHandler<String> asString(Charset charset) {
 263             return (status, headers) -> {
 264                 if (charset != null) {
 265                     return BodyProcessor.asString(charset);
 266                 }
 267                 return BodyProcessor.asString(charsetFrom(headers));
 268             };
 269         }
 270 
 271 
 272         /**
 273          * Returns a {@code BodyHandler<Path>} that returns a
 274          * {@link BodyProcessor BodyProcessor}{@code <Path>} obtained from
 275          * {@link BodyProcessor#asFile(Path) BodyProcessor.asFile(Path)}.
 276          * <p>
 277          * When the {@code HttpResponse} object is returned, the body has been completely
 278          * written to the file, and {@link #body()} returns a reference to its
 279          * {@link Path}.
 280          *
 281          * @param file the file to store the body in
 282          * @return a response body handler
 283          */
 284         public static BodyHandler<Path> asFile(Path file) {
 285             return (status, headers) -> BodyProcessor.asFile(file);
 286         }
 287 
 288         /**
 289          * Returns a {@code BodyHandler<Path>} that returns a
 290          * {@link BodyProcessor BodyProcessor}&lt;{@link Path}&gt;
 291          * where the download directory is specified, but the filename is
 292          * obtained from the {@code Content-Disposition} response header. The
 293          * {@code Content-Disposition} header must specify the <i>attachment</i> type
 294          * and must also contain a
 295          * <i>filename</i> parameter. If the filename specifies multiple path
 296          * components only the final component is used as the filename (with the
 297          * given directory name). When the {@code HttpResponse} object is
 298          * returned, the body has been completely written to the file and {@link
 299          * #body()} returns a {@code Path} object for the file. The returned {@code Path} is the
 300          * combination of the supplied directory name and the file name supplied
 301          * by the server. If the destination directory does not exist or cannot
 302          * be written to, then the response will fail with an {@link IOException}.
 303          *
 304          * @param directory the directory to store the file in
 305          * @param openOptions open options
 306          * @return a response body handler
 307          */
 308         public static BodyHandler<Path> asFileDownload(Path directory, OpenOption... openOptions) {
 309             return (status, headers) -> {
 310                 String dispoHeader = headers.firstValue("Content-Disposition")
 311                         .orElseThrow(() -> unchecked(new IOException("No Content-Disposition")));
 312                 if (!dispoHeader.startsWith("attachment;")) {
 313                     throw unchecked(new IOException("Unknown Content-Disposition type"));
 314                 }
 315                 int n = dispoHeader.indexOf("filename=");
 316                 if (n == -1) {
 317                     throw unchecked(new IOException("Bad Content-Disposition type"));
 318                 }
 319                 int lastsemi = dispoHeader.lastIndexOf(';');
 320                 String disposition;
 321                 if (lastsemi < n) {
 322                     disposition = dispoHeader.substring(n + 9);
 323                 } else {
 324                     disposition = dispoHeader.substring(n + 9, lastsemi);
 325                 }
 326                 Path file = Paths.get(directory.toString(), disposition);
 327                 return BodyProcessor.asFile(file, openOptions);
 328             };
 329         }
 330 
 331         /**
 332          * Returns a {@code BodyHandler<Path>} that returns a
 333          * {@link BodyProcessor BodyProcessor}{@code <Path>} obtained from
 334          * {@link BodyProcessor#asFile(java.nio.file.Path, java.nio.file.OpenOption...)
 335          * BodyProcessor.asFile(Path,OpenOption...)}.
 336          * <p>
 337          * When the {@code HttpResponse} object is returned, the body has been completely
 338          * written to the file, and {@link #body()} returns a reference to its
 339          * {@link Path}.
 340          *
 341          * @param file the filename to store the body in
 342          * @param openOptions any options to use when opening/creating the file
 343          * @return a response body handler
 344          */
 345         public static BodyHandler<Path> asFile(Path file, OpenOption... openOptions) {
 346             return (status, headers) -> BodyProcessor.asFile(file, openOptions);
 347         }
 348 
 349         /**
 350          * Returns a {@code BodyHandler<Void>} that returns a
 351          * {@link BodyProcessor BodyProcessor}{@code <Void>} obtained from
 352          * {@link BodyProcessor#asByteArrayConsumer(java.util.function.Consumer)
 353          * BodyProcessor.asByteArrayConsumer(Consumer)}.
 354          * <p>
 355          * When the {@code HttpResponse} object is returned, the body has been completely
 356          * written to the consumer.
 357          *
 358          * @param consumer a Consumer to accept the response body
 359          * @return a response body handler
 360          */
 361         public static BodyHandler<Void> asByteArrayConsumer(Consumer<Optional<byte[]>> consumer) {
 362             return (status, headers) -> BodyProcessor.asByteArrayConsumer(consumer);
 363         }
 364 
 365         /**
 366          * Returns a {@code BodyHandler<byte[]>} that returns a
 367          * {@link BodyProcessor BodyProcessor}&lt;{@code byte[]}&gt; obtained
 368          * from {@link BodyProcessor#asByteArray() BodyProcessor.asByteArray()}.
 369          * <p>
 370          * When the {@code HttpResponse} object is returned, the body has been completely
 371          * written to the byte array.
 372          *
 373          * @return a response body handler
 374          */
 375         public static BodyHandler<byte[]> asByteArray() {
 376             return (status, headers) -> BodyProcessor.asByteArray();
 377         }
 378 
 379         /**
 380          * Returns a {@code BodyHandler<String>} that returns a
 381          * {@link BodyProcessor BodyProcessor}{@code <String>} obtained from
 382          * {@link BodyProcessor#asString(java.nio.charset.Charset)
 383          * BodyProcessor.asString(Charset)}. The body is
 384          * decoded using the character set specified in
 385          * the {@code Content-encoding} response header. If there is no such
 386          * header, or the character set is not supported, then
 387          * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
 388          * <p>
 389          * When the {@code HttpResponse} object is returned, the body has been completely
 390          * written to the string.
 391          *
 392          * @return a response body handler
 393          */
 394         public static BodyHandler<String> asString() {
 395             return (status, headers) -> BodyProcessor.asString(charsetFrom(headers));
 396         }
 397 
 398         /**
 399          * Returns a {@code BodyHandler} which, when invoked, returns a {@linkplain
 400          * BodyProcessor#buffering(BodyProcessor,int) buffering BodyProcessor}
 401          * that buffers data before delivering it to the downstream processor.
 402          * These {@code BodyProcessor} instances are created by calling
 403          * {@linkplain BodyProcessor#buffering(BodyProcessor,int)
 404          * BodyProcessor.buffering} with a processor obtained from the given
 405          * downstream handler and the {@code bufferSize} parameter.
 406          *
 407          * @param downstreamHandler the downstream handler
 408          * @param bufferSize the buffer size parameter passed to {@linkplain
 409          *        BodyProcessor#buffering(BodyProcessor,int) BodyProcessor.buffering}
 410          * @return a body handler
 411          * @throws IllegalArgumentException if {@code bufferSize <= 0}
 412          */
 413          public static <T> BodyHandler<T> buffering(BodyHandler<T> downstreamHandler,
 414                                                     int bufferSize) {
 415              if (bufferSize <= 0)
 416                  throw new IllegalArgumentException("must be greater than 0");
 417              return (status, headers) -> BodyProcessor
 418                      .buffering(downstreamHandler.apply(status, headers),
 419                                 bufferSize);
 420          }
 421     }
 422 
 423     /**
 424      * A processor for response bodies.
 425      * {@Incubating}
 426      * <p>
 427      * The object acts as a {@link Flow.Subscriber}&lt;{@link List}&lt;{@link
 428      * ByteBuffer}&gt;&gt; to the HTTP client implementation which publishes
 429      * ByteBuffers containing the response body. The processor converts the
 430      * incoming buffers of data to some user-defined object type {@code T}.
 431      * <p>
 432      * The {@link #getBody()} method returns a {@link CompletionStage}{@code <T>}
 433      * that provides the response body object. The {@code CompletionStage} must
 434      * be obtainable at any time. When it completes depends on the nature
 435      * of type {@code T}. In many cases, when {@code T} represents the entire body after being
 436      * read then it completes after the body has been read. If {@code T} is a streaming
 437      * type such as {@link java.io.InputStream} then it completes before the
 438      * body has been read, because the calling code uses it to consume the data.
 439      *
 440      * @param <T> the response body type
 441      */
 442     public interface BodyProcessor<T>
 443             extends Flow.Subscriber<List<ByteBuffer>> {
 444 
 445         /**
 446          * Returns a {@code CompletionStage} which when completed will return the
 447          * response body object.
 448          *
 449          * @return a CompletionStage for the response body
 450          */
 451         public CompletionStage<T> getBody();
 452 
 453         /**
 454          * Returns a body processor which stores the response body as a {@code
 455          * String} converted using the given {@code Charset}.
 456          * <p>
 457          * The {@link HttpResponse} using this processor is available after the
 458          * entire response has been read.
 459          *
 460          * @param charset the character set to convert the String with
 461          * @return a body processor
 462          */
 463         public static BodyProcessor<String> asString(Charset charset) {
 464             return new ResponseProcessors.ByteArrayProcessor<>(
 465                     bytes -> new String(bytes, charset)
 466             );
 467         }
 468 
 469         /**
 470          * Returns a {@code BodyProcessor} which stores the response body as a
 471          * byte array.
 472          * <p>
 473          * The {@link HttpResponse} using this processor is available after the
 474          * entire response has been read.
 475          *
 476          * @return a body processor
 477          */
 478         public static BodyProcessor<byte[]> asByteArray() {
 479             return new ResponseProcessors.ByteArrayProcessor<>(
 480                     Function.identity() // no conversion
 481             );
 482         }
 483 
 484         /**
 485          * Returns a {@code BodyProcessor} which stores the response body in a
 486          * file opened with the given options and name. The file will be opened
 487          * with the given options using
 488          * {@link java.nio.channels.FileChannel#open(java.nio.file.Path,java.nio.file.OpenOption...)
 489          * FileChannel.open} just before the body is read. Any exception thrown will be returned
 490          * or thrown from {@link HttpClient#send(jdk.incubator.http.HttpRequest,
 491          * jdk.incubator.http.HttpResponse.BodyHandler) HttpClient::send}
 492          * or {@link HttpClient#sendAsync(jdk.incubator.http.HttpRequest,
 493          * jdk.incubator.http.HttpResponse.BodyHandler) HttpClient::sendAsync}
 494          * as appropriate.
 495          * <p>
 496          * The {@link HttpResponse} using this processor is available after the
 497          * entire response has been read.
 498          *
 499          * @param file the file to store the body in
 500          * @param openOptions the list of options to open the file with
 501          * @return a body processor
 502          */
 503         public static BodyProcessor<Path> asFile(Path file, OpenOption... openOptions) {
 504             return new ResponseProcessors.PathProcessor(file, openOptions);
 505         }
 506 
 507         /**
 508          * Returns a {@code BodyProcessor} which provides the incoming body
 509          * data to the provided Consumer of {@code Optional<byte[]>}. Each
 510          * call to {@link Consumer#accept(java.lang.Object) Consumer.accept()}
 511          * will contain a non empty {@code Optional}, except for the final invocation after
 512          * all body data has been read, when the {@code Optional} will be empty.
 513          * <p>
 514          * The {@link HttpResponse} using this processor is available after the
 515          * entire response has been read.
 516          *
 517          * @param consumer a Consumer of byte arrays
 518          * @return a BodyProcessor
 519          */
 520         public static BodyProcessor<Void> asByteArrayConsumer(Consumer<Optional<byte[]>> consumer) {
 521             return new ResponseProcessors.ConsumerProcessor(consumer);
 522         }
 523 
 524         /**
 525          * Returns a {@code BodyProcessor} which stores the response body in a
 526          * file opened with the given name. Has the same effect as calling
 527          * {@link #asFile(java.nio.file.Path, java.nio.file.OpenOption...) asFile}
 528          * with the standard open options {@code CREATE} and {@code WRITE}
 529          * <p>
 530          * The {@link HttpResponse} using this processor is available after the
 531          * entire response has been read.
 532          *
 533          * @param file the file to store the body in
 534          * @return a body processor
 535          */
 536         public static BodyProcessor<Path> asFile(Path file) {
 537             return new ResponseProcessors.PathProcessor(
 538                     file,
 539                     StandardOpenOption.CREATE, StandardOpenOption.WRITE);
 540         }
 541 
 542         /**
 543          * Returns a response processor which discards the response body. The
 544          * supplied value is the value that will be returned from
 545          * {@link HttpResponse#body()}.
 546          *
 547          * @param <U> The type of the response body
 548          * @param value the value to return from HttpResponse.body()
 549          * @return a {@code BodyProcessor}
 550          */
 551         public static <U> BodyProcessor<U> discard(U value) {
 552             return new ResponseProcessors.NullProcessor<>(Optional.ofNullable(value));
 553         }
 554 
 555         /**
 556          * Returns a {@code BodyProcessor} which buffers data before delivering
 557          * it to the given downstream processor. The processor guarantees to
 558          * deliver {@code buffersize} bytes of data to each invocation of the
 559          * downstream's {@linkplain #onNext(Object) onNext} method, except for
 560          * the final invocation, just before {@linkplain #onComplete() onComplete}
 561          * is invoked. The final invocation of {@code onNext} may contain fewer
 562          * than {@code buffersize} bytes.
 563          * <p>
 564          * The returned processor delegates its {@link #getBody()} method to the
 565          * downstream processor.
 566          *
 567          * @param downstream the downstream processor
 568          * @param bufferSize the buffer size
 569          * @return a buffering body processor
 570          * @throws IllegalArgumentException if {@code bufferSize <= 0}
 571          */
 572          public static <T> BodyProcessor<T> buffering(BodyProcessor<T> downstream,
 573                                                       int bufferSize) {
 574              if (bufferSize <= 0)
 575                  throw new IllegalArgumentException("must be greater than 0");
 576              return new BufferingProcessor<T>(downstream, bufferSize);
 577          }
 578     }
 579 
 580     /**
 581      * A response processor for a HTTP/2 multi response.
 582      * {@Incubating}
 583      * <p>
 584      * A multi response comprises a main response, and zero or more additional
 585      * responses. Each additional response is sent by the server in response to
 586      * requests that the server also generates. Additional responses are
 587      * typically resources that the server expects the client will need which
 588      * are related to the initial request.
 589      * <p>
 590      * Note. Instead of implementing this interface, applications should consider
 591      * first using the mechanism (built on this interface) provided by
 592      * {@link MultiProcessor#asMap(java.util.function.Function, boolean)
 593      * MultiProcessor.asMap()} which is a slightly simplified, but
 594      * general purpose interface.
 595      * <p>
 596      * The server generated requests are also known as <i>push promises</i>.
 597      * The server is permitted to send any number of these requests up to the
 598      * point where the main response is fully received. Therefore, after
 599      * completion of the main response, the final number of additional
 600      * responses is known. Additional responses may be canceled, but given that
 601      * the server does not wait for any acknowledgment before sending the
 602      * response, this must be done quickly to avoid unnecessary data transmission.
 603      *
 604      * <p> {@code MultiProcessor}s are parameterized with a type {@code U} which
 605      * represents some meaningful aggregate of the responses received. This
 606      * would typically be a collection of response or response body objects.
 607      *
 608      * @param <U> a type representing the aggregated results
 609      * @param <T> a type representing all of the response bodies
 610      *
 611      * @since 9
 612      */
 613     public interface MultiProcessor<U,T> {
 614         /**
 615          * Called for the main request and each push promise that is received.
 616          * The first call will always be for the main request that was sent
 617          * by the caller. This {@link HttpRequest} parameter
 618          * represents the initial request or subsequent PUSH_PROMISE. The
 619          * implementation must return an {@code Optional} of {@link BodyHandler} for
 620          * the response body. Different handlers (of the same type) can be returned
 621          * for different pushes within the same multi send. If no handler
 622          * (an empty {@code Optional}) is returned, then the push will be canceled. It is
 623          * an error to not return a valid {@code BodyHandler} for the initial (main) request.
 624          *
 625          * @param request the main request or subsequent push promise
 626          *
 627          * @return an optional body handler
 628          */
 629         Optional<BodyHandler<T>> onRequest(HttpRequest request);
 630 
 631         /**
 632          * Called for each response received. For each request either one of
 633          * onResponse() or onError() is guaranteed to be called, but not both.
 634          *
 635          * [Note] The reason for switching to this callback interface rather
 636          * than using CompletableFutures supplied to onRequest() is that there
 637          * is a subtle interaction between those CFs and the CF returned from
 638          * completion() (or when onComplete() was called formerly). The completion()
 639          * CF will not complete until after all of the work done by the onResponse()
 640          * calls is done. Whereas if you just create CF's dependent on a supplied
 641          * CF (to onRequest()) then the implementation has no visibility of the
 642          * dependent CFs and can't guarantee to call onComplete() (or complete
 643          * the completion() CF) after the dependent CFs complete.
 644          *
 645          * @param response the response received
 646          */
 647         void onResponse(HttpResponse<T> response);
 648 
 649         /**
 650          * Called if an error occurs receiving a response. For each request
 651          * either one of onResponse() or onError() is guaranteed to be called,
 652          * but not both.
 653          *
 654          * @param request the main request or subsequent push promise
 655          * @param t the Throwable that caused the error
 656          */
 657         void onError(HttpRequest request, Throwable t);
 658 
 659         /**
 660          * Returns a {@link java.util.concurrent.CompletableFuture}{@code <U>}
 661          * which completes when the aggregate result object itself is available.
 662          * It is expected that the returned {@code CompletableFuture} will depend
 663          * on one of the given {@code CompletableFuture<Void}s which themselves complete
 664          * after all individual responses associated with the multi response
 665          * have completed, or after all push promises have been received.
 666          *
 667          * @implNote Implementations might follow the pattern shown below
 668          * <pre>
 669          * {@code
 670          *      CompletableFuture<U> completion(
 671          *              CompletableFuture<Void> onComplete,
 672          *              CompletableFuture<Void> onFinalPushPromise)
 673          *      {
 674          *          return onComplete.thenApply((v) -> {
 675          *              U u = ... instantiate and populate a U instance
 676          *              return u;
 677          *          });
 678          *      }
 679          * }
 680          * </pre>
 681          *
 682          * @param onComplete a CompletableFuture which completes after all
 683          * responses have been received relating to this multi request.
 684          *
 685          * @param onFinalPushPromise CompletableFuture which completes after all
 686          * push promises have been received.
 687          *
 688          * @return the aggregate CF response object
 689          */
 690         CompletableFuture<U> completion(CompletableFuture<Void> onComplete,
 691                 CompletableFuture<Void> onFinalPushPromise);
 692 
 693         /**
 694          * Returns a general purpose handler for multi responses. The aggregated
 695          * result object produced by this handler is a
 696          * {@code Map<HttpRequest,CompletableFuture<HttpResponse<V>>>}. Each
 697          * request (both the original user generated request and each server
 698          * generated push promise) is returned as a key of the map. The value
 699          * corresponding to each key is a
 700          * {@code CompletableFuture<HttpResponse<V>>}.
 701          * <p>
 702          * There are two ways to use these handlers, depending on the value of
 703          * the <i>completion</I> parameter. If completion is true, then the
 704          * aggregated result will be available after all responses have
 705          * themselves completed. If <i>completion</i> is false, then the
 706          * aggregated result will be available immediately after the last push
 707          * promise was received. In the former case, this implies that all the
 708          * CompletableFutures in the map values will have completed. In the
 709          * latter case, they may or may not have completed yet.
 710          * <p>
 711          * The simplest way to use these handlers is to set completion to
 712          * {@code true}, and then all (results) values in the Map will be
 713          * accessible without blocking.
 714          * <p>
 715          * See {@link #asMap(java.util.function.Function, boolean)
 716          * }
 717          * for a code sample of using this interface.
 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          * @param completion {@code true} if the aggregate CompletableFuture
 723          * completes after all responses have been received, or {@code false}
 724          * after all push promises received.
 725          *
 726          * @return a MultiProcessor
 727          */
 728         public static <V> MultiProcessor<MultiMapResult<V>,V> asMap(
 729             Function<HttpRequest, Optional<HttpResponse.BodyHandler<V>>> pushHandler,
 730                 boolean completion) {
 731 
 732             return new MultiProcessorImpl<V>(pushHandler, completion);
 733         }
 734 
 735         /**
 736          * Returns a general purpose handler for multi responses. This is a
 737          * convenience method which invokes {@link #asMap(java.util.function.Function,boolean)
 738          * asMap(Function, true)} meaning that the aggregate result
 739          * object completes after all responses have been received.
 740          * <p>
 741          * <b>Example usage:</b>
 742          * <br>
 743          * <pre>
 744          * {@code
 745          *          HttpRequest request = HttpRequest.newBuilder()
 746          *                  .uri(URI.create("https://www.foo.com/"))
 747          *                  .GET()
 748          *                  .build();
 749          *
 750          *          HttpClient client = HttpClient.newHttpClient();
 751          *
 752          *          Map<HttpRequest,CompletableFuture<HttpResponse<String>>> results = client
 753          *              .sendAsync(request, MultiProcessor.asMap(
 754          *                  (req) -> Optional.of(HttpResponse.BodyHandler.asString())))
 755          *              .join();
 756          * }</pre>
 757          * <p>
 758          * The lambda in this example is the simplest possible implementation,
 759          * where neither the incoming requests are examined, nor the response
 760          * headers, and every push that the server sends is accepted. When the
 761          * join() call returns, all {@code HttpResponse}s and their associated
 762          * body objects are available.
 763          *
 764          * @param <V> the body type used for all responses
 765          * @param pushHandler a function invoked for each request or push
 766          * promise
 767          * @return a MultiProcessor
 768          */
 769         public static <V> MultiProcessor<MultiMapResult<V>,V> asMap(
 770             Function<HttpRequest, Optional<HttpResponse.BodyHandler<V>>> pushHandler) {
 771 
 772             return asMap(pushHandler, true);
 773         }
 774 
 775     }
 776 }