src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpResponse.java
branchhttp-client-branch
changeset 56009 cf8792f51dee
parent 56008 bbd688c6fbbb
child 56010 782b2f2d1e76
equal deleted inserted replaced
56008:bbd688c6fbbb 56009:cf8792f51dee
     1 /*
     1 /*
     2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package jdk.incubator.http;
    26 package jdk.incubator.http;
    27 
    27 
       
    28 import java.io.BufferedReader;
    28 import java.io.IOException;
    29 import java.io.IOException;
    29 import java.io.InputStream;
    30 import java.io.InputStream;
    30 import java.net.URI;
    31 import java.net.URI;
    31 import jdk.incubator.http.ResponseSubscribers.MultiSubscriberImpl;
    32 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.unchecked;
    33 import static jdk.incubator.http.internal.common.Utils.charsetFrom;
    34 import static jdk.incubator.http.internal.common.Utils.charsetFrom;
    34 import java.nio.ByteBuffer;
    35 import java.nio.ByteBuffer;
    35 import java.nio.charset.Charset;
    36 import java.nio.charset.Charset;
    36 import java.nio.channels.FileChannel;
    37 import java.nio.channels.FileChannel;
       
    38 import java.nio.charset.StandardCharsets;
    37 import java.nio.file.OpenOption;
    39 import java.nio.file.OpenOption;
    38 import java.nio.file.Path;
    40 import java.nio.file.Path;
    39 import java.nio.file.Paths;
    41 import java.nio.file.Paths;
    40 import java.nio.file.StandardOpenOption;
    42 import java.nio.file.StandardOpenOption;
    41 import java.security.AccessControlContext;
    43 import java.security.AccessControlContext;
    42 import java.util.Arrays;
       
    43 import java.util.List;
    44 import java.util.List;
    44 import java.util.Objects;
    45 import java.util.Objects;
    45 import java.util.Optional;
    46 import java.util.Optional;
    46 import java.util.concurrent.CompletableFuture;
    47 import java.util.concurrent.CompletableFuture;
    47 import java.util.concurrent.CompletionStage;
    48 import java.util.concurrent.CompletionStage;
    48 import java.util.concurrent.Flow;
    49 import java.util.concurrent.Flow;
    49 import java.util.concurrent.Flow.Subscriber;
    50 import java.util.concurrent.Flow.Subscriber;
    50 import java.util.function.Consumer;
    51 import java.util.function.Consumer;
    51 import java.util.function.Function;
    52 import java.util.function.Function;
       
    53 import java.util.stream.Stream;
    52 import javax.net.ssl.SSLParameters;
    54 import javax.net.ssl.SSLParameters;
    53 
    55 
    54 /**
    56 /**
    55  * Represents a response to a {@link HttpRequest}.
    57  * Represents a response to a {@link HttpRequest}.
    56  * {@Incubating}
    58  * {@Incubating}
   397             return (status, headers) -> BodySubscriber.fromSubscriber(subscriber,
   399             return (status, headers) -> BodySubscriber.fromSubscriber(subscriber,
   398                                                                       finisher);
   400                                                                       finisher);
   399         }
   401         }
   400 
   402 
   401         /**
   403         /**
       
   404          * Returns a response body handler that returns a {@link BodySubscriber
       
   405          * BodySubscriber}{@code <Void>} obtained from {@link
       
   406          * BodySubscriber#fromLineSubscriber(Subscriber, Function, Charset, String)
       
   407          * BodySubscriber.fromLineSubscriber(subscriber, s -> null, charset, null)},
       
   408          * with the given {@code subscriber}.
       
   409          * The {@link Charset charset} used to decode the response body bytes is
       
   410          * obtained from the HTTP response headers as specified by {@link #asString()},
       
   411          * and lines are delimited in the manner of {@link BufferedReader#readLine()}.
       
   412          *
       
   413          * <p> The response body is not available through this, or the {@code
       
   414          * HttpResponse} API, but instead all response body is forwarded to the
       
   415          * given {@code subscriber}, which should make it available, if
       
   416          * appropriate, through some other mechanism, e.g. an entry in a
       
   417          * database, etc.
       
   418          *
       
   419          * @apiNote This method can be used as an adapter between {@code
       
   420          * BodySubscriber} and {@code Flow.Subscriber}.
       
   421          *
       
   422          * <p> For example:
       
   423          * <pre> {@code
       
   424          *  TextSubscriber subscriber = new TextSubscriber();
       
   425          *  HttpResponse<Void> response = client.sendAsync(request,
       
   426          *      BodyHandler.fromLineSubscriber(subscriber, "\n")).join();
       
   427          *  System.out.println(response.statusCode());
       
   428          * }</pre>
       
   429          *
       
   430          * @param subscriber the subscriber
       
   431          * @return a response body handler
       
   432          */
       
   433         public static BodyHandler<Void>
       
   434         fromLineSubscriber(Subscriber<? super String> subscriber) {
       
   435             Objects.requireNonNull(subscriber);
       
   436             return (status, headers)
       
   437                     -> BodySubscriber.fromLineSubscriber(subscriber, s -> null,
       
   438                     charsetFrom(headers), null);
       
   439         }
       
   440 
       
   441         /**
       
   442          * Returns a response body handler that returns a {@link BodySubscriber
       
   443          * BodySubscriber}{@code <T>} obtained from {@link
       
   444          * BodySubscriber#fromLineSubscriber(Subscriber, Function, Charset, String)
       
   445          * BodySubscriber.fromLineSubscriber(subscriber, finisher, charset, lineSeparator)},
       
   446          * with the given {@code subscriber}, {@code finisher} function, and line separator.
       
   447          * The {@link Charset charset} used to decode the response body bytes is
       
   448          * obtained from the HTTP response headers as specified by {@link #asString()}.
       
   449          *
       
   450          * <p> The given {@code finisher} function is applied after the given
       
   451          * subscriber's {@code onComplete} has been invoked. The {@code finisher}
       
   452          * function is invoked with the given subscriber, and returns a value
       
   453          * that is set as the response's body.
       
   454          *
       
   455          * @apiNote This method can be used as an adapter between {@code
       
   456          * BodySubscriber} and {@code Flow.Subscriber}.
       
   457          *
       
   458          * <p> For example:
       
   459          * <pre> {@code
       
   460          * TextSubscriber subscriber = ...;  // accumulates bytes and transforms them into a String
       
   461          * HttpResponse<String> response = client.sendAsync(request,
       
   462          *     BodyHandler.fromSubscriber(subscriber, TextSubscriber::getTextResult, "\n")).join();
       
   463          * String text = response.body();
       
   464          * }</pre>
       
   465          *
       
   466          * @param <S> the type of the Subscriber
       
   467          * @param <T> the type of the response body
       
   468          * @param subscriber the subscriber
       
   469          * @param finisher a function to be applied after the subscriber has completed
       
   470          * @param lineSeparator an optional line separator: can be {@code null},
       
   471          *                      in which case lines will be delimited in the manner of
       
   472          *                      {@link BufferedReader#readLine()}.
       
   473          * @return a response body handler
       
   474          * @throws IllegalArgumentException if the supplied {@code lineSeparator} is the empty string.
       
   475          */
       
   476         public static <S extends Subscriber<? super String>,T> BodyHandler<T>
       
   477         fromLineSubscriber(S subscriber, Function<S,T> finisher, String lineSeparator) {
       
   478             Objects.requireNonNull(subscriber);
       
   479             Objects.requireNonNull(finisher);
       
   480             // implicit null check
       
   481             if (lineSeparator != null && lineSeparator.isEmpty())
       
   482                 throw new IllegalArgumentException("empty line separator");
       
   483             return (status, headers) ->
       
   484                     BodySubscriber.fromLineSubscriber(subscriber, finisher,
       
   485                             charsetFrom(headers), lineSeparator);
       
   486         }
       
   487 
       
   488         /**
   402          * Returns a response body handler which discards the response body and
   489          * Returns a response body handler which discards the response body and
   403          * uses the given value as a replacement for it.
   490          * uses the given value as a replacement for it.
   404          *
   491          *
   405          * @param <U> the response body type
   492          * @param <U> the response body type
   406          * @param value the value of U to return as the body, may be {@code null}
   493          * @param value the value of U to return as the body, may be {@code null}
   540         public static BodyHandler<InputStream> asInputStream() {
   627         public static BodyHandler<InputStream> asInputStream() {
   541             return (status, headers) -> BodySubscriber.asInputStream();
   628             return (status, headers) -> BodySubscriber.asInputStream();
   542         }
   629         }
   543 
   630 
   544         /**
   631         /**
       
   632          * Returns a {@code BodyHandler<Stream<String>>} that returns a
       
   633          * {@link BodySubscriber BodySubscriber}{@code <Stream<String>>} obtained from
       
   634          * {@link BodySubscriber#asLines(Charset)}
       
   635          * BodySubscriber.asLines(charset)}.
       
   636          * The {@link Charset charset} used to decode the response body bytes is
       
   637          * obtained from the HTTP response headers as specified by {@link #asString()},
       
   638          * and lines are delimited in the manner of {@link BufferedReader#readLine()}.
       
   639          *
       
   640          * <p> When the {@code HttpResponse} object is returned, the body may
       
   641          * not have been completely received.
       
   642          *
       
   643          * @return a response body handler
       
   644          */
       
   645         public static BodyHandler<Stream<String>> asLines() {
       
   646             return (status, headers) ->
       
   647                     BodySubscriber.asLines(charsetFrom(headers));
       
   648         }
       
   649 
       
   650         /**
   545          * Returns a {@code BodyHandler<Void>} that returns a
   651          * Returns a {@code BodyHandler<Void>} that returns a
   546          * {@link BodySubscriber BodySubscriber}{@code <Void>} obtained from
   652          * {@link BodySubscriber BodySubscriber}{@code <Void>} obtained from
   547          * {@link BodySubscriber#asByteArrayConsumer(Consumer)
   653          * {@link BodySubscriber#asByteArrayConsumer(Consumer)
   548          * BodySubscriber.asByteArrayConsumer(Consumer)}.
   654          * BodySubscriber.asByteArrayConsumer(Consumer)}.
   549          *
   655          *
   576          * Returns a {@code BodyHandler<String>} that returns a
   682          * Returns a {@code BodyHandler<String>} that returns a
   577          * {@link BodySubscriber BodySubscriber}{@code <String>} obtained from
   683          * {@link BodySubscriber BodySubscriber}{@code <String>} obtained from
   578          * {@link BodySubscriber#asString(java.nio.charset.Charset)
   684          * {@link BodySubscriber#asString(java.nio.charset.Charset)
   579          * BodySubscriber.asString(Charset)}. The body is
   685          * BodySubscriber.asString(Charset)}. The body is
   580          * decoded using the character set specified in
   686          * decoded using the character set specified in
   581          * the {@code Content-encoding} response header. If there is no such
   687          * the {@code Content-type} response header. If there is no such
   582          * header, or the character set is not supported, then
   688          * header, or the character set is not supported, then
   583          * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
   689          * {@link java.nio.charset.StandardCharsets#UTF_8 UTF_8} is used.
   584          *
   690          *
   585          * <p> When the {@code HttpResponse} object is returned, the body has
   691          * <p> When the {@code HttpResponse} object is returned, the body has
   586          * been completely written to the string.
   692          * been completely written to the string.
   707          */
   813          */
   708         public static <S extends Subscriber<? super List<ByteBuffer>>,T> BodySubscriber<T>
   814         public static <S extends Subscriber<? super List<ByteBuffer>>,T> BodySubscriber<T>
   709         fromSubscriber(S subscriber,
   815         fromSubscriber(S subscriber,
   710                        Function<S,T> finisher) {
   816                        Function<S,T> finisher) {
   711             return new ResponseSubscribers.SubscriberAdapter<S,T>(subscriber, finisher);
   817             return new ResponseSubscribers.SubscriberAdapter<S,T>(subscriber, finisher);
       
   818         }
       
   819 
       
   820         /**
       
   821          * Returns a body subscriber that forwards all response body to the
       
   822          * given {@code Flow.Subscriber}, lines by lines.
       
   823          * The {@linkplain #getBody()} completion
       
   824          * stage} of the returned body subscriber completes after one of the
       
   825          * given subscribers {@code onComplete} or {@code onError} has been
       
   826          * invoked.
       
   827          * Bytes are decoded using the {@linkplain StandardCharsets#UTF_8
       
   828          * UTF-8} charset, and lines are delimited in the manner of
       
   829          * {@link BufferedReader#readLine()}.
       
   830          *
       
   831          * @apiNote This method can be used as an adapter between {@code
       
   832          * BodySubscriber} and {@code Flow.Subscriber}.
       
   833          *
       
   834          * @implNote This is equivalent to calling <pre>{@code
       
   835          *      fromLineSubscriber(subscriber, s -> null, StandardCharsets.UTF_8, null)
       
   836          * }</pre>
       
   837          *
       
   838          * @param <S> the type of the Subscriber
       
   839          * @param subscriber the subscriber
       
   840          * @return a body subscriber
       
   841          */
       
   842         public static <S extends Subscriber<? super String>> BodySubscriber<Void>
       
   843         fromLineSubscriber(S subscriber) {
       
   844             return fromLineSubscriber(subscriber, s -> null,
       
   845                     StandardCharsets.UTF_8, null);
       
   846         }
       
   847 
       
   848         /**
       
   849          * Returns a body subscriber that forwards all response body to the
       
   850          * given {@code Flow.Subscriber}, lines by lines.
       
   851          * The {@linkplain #getBody()} completion
       
   852          * stage} of the returned body subscriber completes after one of the
       
   853          * given subscribers {@code onComplete} or {@code onError} has been
       
   854          * invoked.
       
   855          *
       
   856          * <p> The given {@code finisher} function is applied after the given
       
   857          * subscriber's {@code onComplete} has been invoked. The {@code finisher}
       
   858          * function is invoked with the given subscriber, and returns a value
       
   859          * that is set as the response's body.
       
   860          *
       
   861          * @apiNote This method can be used as an adapter between {@code
       
   862          * BodySubscriber} and {@code Flow.Subscriber}.
       
   863          *
       
   864          * @param <S> the type of the Subscriber
       
   865          * @param <T> the type of the response body
       
   866          * @param subscriber the subscriber
       
   867          * @param finisher a function to be applied after the subscriber has
       
   868          *                 completed
       
   869          * @param charset a {@link Charset} to decode the bytes
       
   870          * @param lineSeparator an optional line separator: can be {@code null},
       
   871          *                      in which case lines will be delimited in the manner of
       
   872          *                      {@link BufferedReader#readLine()}.
       
   873          * @return a body subscriber
       
   874          * @throws IllegalArgumentException if the supplied {@code lineSeparator} is the empty string.
       
   875          */
       
   876         public static <S extends Subscriber<? super String>,T> BodySubscriber<T>
       
   877         fromLineSubscriber(S subscriber,
       
   878                            Function<S,T> finisher,
       
   879                            Charset charset,
       
   880                            String lineSeparator) {
       
   881             return LineSubscriberAdapter.create(subscriber,
       
   882                     finisher, charset, lineSeparator);
   712         }
   883         }
   713 
   884 
   714         /**
   885         /**
   715          * Returns a body subscriber which stores the response body as a {@code
   886          * Returns a body subscriber which stores the response body as a {@code
   716          * String} converted using the given {@code Charset}.
   887          * String} converted using the given {@code Charset}.
   842          * @return a body subscriber that streams the response body as an
  1013          * @return a body subscriber that streams the response body as an
   843          *         {@link InputStream}.
  1014          *         {@link InputStream}.
   844          */
  1015          */
   845         public static BodySubscriber<InputStream> asInputStream() {
  1016         public static BodySubscriber<InputStream> asInputStream() {
   846             return new ResponseSubscribers.HttpResponseInputStream();
  1017             return new ResponseSubscribers.HttpResponseInputStream();
       
  1018         }
       
  1019 
       
  1020         /**
       
  1021          * Returns a {@code BodySubscriber} which streams the response body as
       
  1022          * a {@link Stream Stream<String>}, where each string in the stream
       
  1023          * corresponds to a line as defined by {@link BufferedReader#lines()}.
       
  1024          *
       
  1025          * <p> The {@link HttpResponse} using this subscriber is available
       
  1026          * immediately after the response headers have been read, without
       
  1027          * requiring to wait for the entire body to be processed. The response
       
  1028          * body can then be read directly from the {@link Stream}.
       
  1029          *
       
  1030          * @apiNote To ensure that all resources associated with the
       
  1031          * corresponding exchange are properly released the caller must
       
  1032          * ensure to either read all lines until the stream is exhausted,
       
  1033          * or call {@link Stream#close} if it is unable or unwilling to do so.
       
  1034          * Calling {@code close} before exhausting the stream may cause
       
  1035          * the underlying HTTP connection to be closed and prevent it
       
  1036          * from being reused for subsequent operations.
       
  1037          *
       
  1038          * @return a body subscriber that streams the response body as a
       
  1039          *         {@link Stream Stream<String>}.
       
  1040          *
       
  1041          * @see BufferedReader#lines()
       
  1042          */
       
  1043         public static BodySubscriber<Stream<String>> asLines(Charset charset) {
       
  1044             return ResponseSubscribers.HttpLineStream.create(charset);
   847         }
  1045         }
   848 
  1046 
   849         /**
  1047         /**
   850          * Returns a response subscriber which discards the response body. The
  1048          * Returns a response subscriber which discards the response body. The
   851          * supplied value is the value that will be returned from
  1049          * supplied value is the value that will be returned from