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.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 }