test/jdk/java/net/httpclient/BodyProcessorInputStreamTest.java
branchhttp-client-branch
changeset 55763 634d8e14c172
child 49765 ee6f7a61f3a5
child 56089 42208b2f224e
equal deleted inserted replaced
55762:e947a3a50a95 55763:634d8e14c172
       
     1 /*
       
     2  * Copyright (c) 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.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 import java.io.IOException;
       
    25 import java.io.InputStream;
       
    26 import java.io.InputStreamReader;
       
    27 import java.io.Reader;
       
    28 import java.net.URI;
       
    29 import jdk.incubator.http.HttpClient;
       
    30 import jdk.incubator.http.HttpHeaders;
       
    31 import jdk.incubator.http.HttpRequest;
       
    32 import jdk.incubator.http.HttpResponse;
       
    33 import java.nio.ByteBuffer;
       
    34 import java.nio.charset.Charset;
       
    35 import java.util.ArrayList;
       
    36 import java.util.Iterator;
       
    37 import java.util.List;
       
    38 import java.util.Locale;
       
    39 import java.util.Optional;
       
    40 import java.util.concurrent.ArrayBlockingQueue;
       
    41 import java.util.concurrent.BlockingQueue;
       
    42 import java.util.concurrent.CompletableFuture;
       
    43 import java.util.concurrent.CompletionStage;
       
    44 import java.util.concurrent.Flow;
       
    45 import java.util.stream.Stream;
       
    46 import static java.lang.System.err;
       
    47 
       
    48 /*
       
    49  * @test
       
    50  * @bug 8187503
       
    51  * @summary An example on how to read a response body with InputStream...
       
    52  * @run main/othervm -Dtest.debug=true BodyProcessorInputStreamTest
       
    53  * @author daniel fuchs
       
    54  */
       
    55 public class BodyProcessorInputStreamTest {
       
    56 
       
    57     public static boolean DEBUG = Boolean.getBoolean("test.debug");
       
    58 
       
    59     /**
       
    60      * Examine the response headers to figure out the charset used to
       
    61      * encode the body content.
       
    62      * If the content type is not textual, returns an empty Optional.
       
    63      * Otherwise, returns the body content's charset, defaulting to
       
    64      * ISO-8859-1 if none is explicitly specified.
       
    65      * @param headers The response headers.
       
    66      * @return The charset to use for decoding the response body, if
       
    67      *         the response body content is text/...
       
    68      */
       
    69     public static Optional<Charset> getCharset(HttpHeaders headers) {
       
    70         Optional<String> contentType = headers.firstValue("Content-Type");
       
    71         Optional<Charset> charset = Optional.empty();
       
    72         if (contentType.isPresent()) {
       
    73             final String[] values = contentType.get().split(";");
       
    74             if (values[0].startsWith("text/")) {
       
    75                 charset = Optional.of(Stream.of(values)
       
    76                     .map(x -> x.toLowerCase(Locale.ROOT))
       
    77                     .map(String::trim)
       
    78                     .filter(x -> x.startsWith("charset="))
       
    79                     .map(x -> x.substring("charset=".length()))
       
    80                     .findFirst()
       
    81                     .orElse("ISO-8859-1"))
       
    82                     .map(Charset::forName);
       
    83             }
       
    84         }
       
    85         return charset;
       
    86     }
       
    87 
       
    88     public static void main(String[] args) throws Exception {
       
    89         HttpClient client = HttpClient.newHttpClient();
       
    90         HttpRequest request = HttpRequest
       
    91             .newBuilder(new URI("http://hg.openjdk.java.net/jdk9/sandbox/jdk/shortlog/http-client-branch/"))
       
    92             .GET()
       
    93             .build();
       
    94 
       
    95         // This example shows how to return an InputStream that can be used to
       
    96         // start reading the response body before the response is fully received.
       
    97         // In comparison, the snipet below (which uses
       
    98         // HttpResponse.BodyHandler.asString()) obviously will not return before the
       
    99         // response body is fully read:
       
   100         //
       
   101         // System.out.println(
       
   102         //    client.sendAsync(request, HttpResponse.BodyHandler.asString()).get().body());
       
   103 
       
   104         CompletableFuture<HttpResponse<InputStream>> handle =
       
   105             client.sendAsync(request, HttpResponse.BodyHandler.asInputStream());
       
   106         if (DEBUG) err.println("Request sent");
       
   107 
       
   108         HttpResponse<InputStream> pending = handle.get();
       
   109 
       
   110         // At this point, the response headers have been received, but the
       
   111         // response body may not have arrived yet. This comes from
       
   112         // the implementation of HttpResponseInputStream::getBody above,
       
   113         // which returns an already completed completion stage, without
       
   114         // waiting for any data.
       
   115         // We can therefore access the headers - and the body, which
       
   116         // is our live InputStream, without waiting...
       
   117         HttpHeaders responseHeaders = pending.headers();
       
   118 
       
   119         // Get the charset declared in the response headers.
       
   120         // The optional will be empty if the content type is not
       
   121         // of type text/...
       
   122         Optional<Charset> charset = getCharset(responseHeaders);
       
   123 
       
   124         try (InputStream is = pending.body();
       
   125             // We assume a textual content type. Construct an InputStream
       
   126             // Reader with the appropriate Charset.
       
   127             // charset.get() will throw NPE if the content is not textual.
       
   128             Reader r = new InputStreamReader(is, charset.get())) {
       
   129 
       
   130             char[] buff = new char[32];
       
   131             int off=0, n=0;
       
   132             if (DEBUG) err.println("Start receiving response body");
       
   133             if (DEBUG) err.println("Charset: " + charset.get());
       
   134 
       
   135             // Start consuming the InputStream as the data arrives.
       
   136             // Will block until there is something to read...
       
   137             while ((n = r.read(buff, off, buff.length - off)) > 0) {
       
   138                 assert (buff.length - off) > 0;
       
   139                 assert n <= (buff.length - off);
       
   140                 if (n == (buff.length - off)) {
       
   141                     System.out.print(buff);
       
   142                     off = 0;
       
   143                 } else {
       
   144                     off += n;
       
   145                 }
       
   146                 assert off < buff.length;
       
   147             }
       
   148 
       
   149             // last call to read may not have filled 'buff' completely.
       
   150             // flush out the remaining characters.
       
   151             assert off >= 0 && off < buff.length;
       
   152             for (int i=0; i < off; i++) {
       
   153                 System.out.print(buff[i]);
       
   154             }
       
   155 
       
   156             // We're done!
       
   157             System.out.println("Done!");
       
   158         }
       
   159     }
       
   160 
       
   161 }