jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java
changeset 42483 3850c235c3fb
parent 42482 15297dde0d55
parent 42479 a80dbf731cbe
child 42489 a9e4de33da2e
equal deleted inserted replaced
42482:15297dde0d55 42483:3850c235c3fb
     1 /*
       
     2  * Copyright (c) 2015, 2016, 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 java.net.http;
       
    27 
       
    28 import java.io.IOException;
       
    29 import java.io.InputStream;
       
    30 import java.io.UncheckedIOException;
       
    31 import java.net.URI;
       
    32 import java.net.ProxySelector;
       
    33 import java.nio.ByteBuffer;
       
    34 import java.nio.channels.FileChannel;
       
    35 import java.nio.charset.*;
       
    36 import java.nio.file.Path;
       
    37 import java.util.Iterator;
       
    38 import java.util.concurrent.CompletableFuture;
       
    39 import java.util.concurrent.TimeUnit;
       
    40 import java.util.function.LongConsumer;
       
    41 
       
    42 /**
       
    43  * Represents one HTTP request which can be sent to a server. {@code
       
    44  * HttpRequest}s are built from {@code HttpRequest} {@link HttpRequest.Builder
       
    45  * builder}s. {@code HttpRequest} builders are obtained from a {@link HttpClient}
       
    46  * by calling {@link HttpClient#request(java.net.URI) HttpClient.request}, or
       
    47  * by calling {@link #create(java.net.URI) HttpRequest.create} which returns a
       
    48  * builder on the <a href="HttpClient.html#defaultclient">default</a> client.
       
    49  * A request's {@link java.net.URI}, headers and body can be set. Request bodies
       
    50  * are provided through a {@link BodyProcessor} object. Once all required
       
    51  * parameters have been set in the builder, one of the builder methods should be
       
    52  * called, which sets the request method and returns a {@code HttpRequest}.
       
    53  * These methods are {@link Builder#GET() GET}, {@link HttpRequest.Builder#POST()
       
    54  * POST} and {@link HttpRequest.Builder#PUT() PUT} which return a GET, POST or
       
    55  * PUT request respectively. Alternatively, {@link
       
    56  * HttpRequest.Builder#method(String) method} can be called to set an arbitrary
       
    57  * method type (and return a {@code HttpRequest}). Builders can also be copied
       
    58  * and modified multiple times in order to build multiple related requests that
       
    59  * differ in some parameters.
       
    60  *
       
    61  * <p> Two simple, example HTTP interactions are shown below:
       
    62  * <pre>
       
    63  * {@code
       
    64  *      // GET
       
    65  *      HttpResponse response = HttpRequest
       
    66  *          .create(new URI("http://www.foo.com"))
       
    67  *          .headers("Foo", "foovalue", "Bar", "barvalue")
       
    68  *          .GET()
       
    69  *          .response();
       
    70  *
       
    71  *      int statusCode = response.statusCode();
       
    72  *      String responseBody = response.body(asString());
       
    73  *
       
    74  *      // POST
       
    75  *      response = HttpRequest
       
    76  *          .create(new URI("http://www.foo.com"))
       
    77  *          .body(fromString("param1=foo,param2=bar"))
       
    78  *          .POST()
       
    79  *          .response();}
       
    80  * </pre>
       
    81  *
       
    82  * <p> The request is sent and the response obtained by calling one of the
       
    83  * following methods.
       
    84  * <ul><li>{@link #response() response} blocks until the entire request has been
       
    85  * sent and the response status code and headers have been received.</li>
       
    86  * <li>{@link #responseAsync() responseAsync} sends the request and receives the
       
    87  * response asynchronously. Returns immediately with a
       
    88  * {@link java.util.concurrent.CompletableFuture CompletableFuture}&lt;{@link
       
    89  * HttpResponse}&gt;.</li>
       
    90  * <li>{@link #multiResponseAsync(HttpResponse.MultiProcessor) multiResponseAsync}
       
    91  * sends the request asynchronously, expecting multiple responses. This
       
    92  * capability is of most relevance to HTTP/2 server push, but can be used for
       
    93  * single responses (HTTP/1.1 or HTTP/2) also.</li>
       
    94  * </ul>
       
    95  *
       
    96  * <p> Once a request has been sent, it is an error to try and send it again.
       
    97  *
       
    98  * <p> Once a {@code HttpResponse} is received, the headers and response code are
       
    99  * available. The body can then be received by calling one of the body methods
       
   100  * on {@code HttpResponse}.
       
   101  *
       
   102  * <p> See below for discussion of synchronous versus asynchronous usage.
       
   103  *
       
   104  * <p> <b>Request bodies</b>
       
   105  *
       
   106  * <p> Request bodies are sent using one of the request processor implementations
       
   107  * below provided in {@code HttpRequest}, or else a custom implementation can be
       
   108  * used.
       
   109  * <ul>
       
   110  * <li>{@link #fromByteArray(byte[]) } from byte array</li>
       
   111  * <li>{@link #fromByteArrays(java.util.Iterator) fromByteArrays(Iterator)}
       
   112  *      from an iterator of byte arrays</li>
       
   113  * <li>{@link #fromFile(java.nio.file.Path) fromFile(Path)} from the file located
       
   114  *     at the given Path</li>
       
   115  * <li>{@link #fromString(java.lang.String) fromString(String)} from a String </li>
       
   116  * <li>{@link #fromInputStream(java.io.InputStream) fromInputStream(InputStream)}
       
   117  *      request body from InputStream</li>
       
   118  * <li>{@link #noBody() } no request body is sent</li>
       
   119  * </ul>
       
   120  *
       
   121  * <p> <b>Response bodies</b>
       
   122  *
       
   123  * <p> Responses bodies are handled by the {@link HttpResponse.BodyProcessor}
       
   124  * {@code <T>} supplied to the {@link HttpResponse#body(HttpResponse.BodyProcessor)
       
   125  * HttpResponse.body} and {@link HttpResponse#bodyAsync(HttpResponse.BodyProcessor)
       
   126  * HttpResponse.bodyAsync} methods. Some implementations of {@code
       
   127  * HttpResponse.BodyProcessor} are provided in {@link HttpResponse}:
       
   128  * <ul>
       
   129  * <li>{@link HttpResponse#asByteArray() } stores the body in a byte array</li>
       
   130  * <li>{@link HttpResponse#asString()} stores the body as a String </li>
       
   131  * <li>{@link HttpResponse#asFile(java.nio.file.Path) } stores the body in a
       
   132  * named file</li>
       
   133  * <li>{@link HttpResponse#ignoreBody() } ignores any received response body</li>
       
   134  * </ul>
       
   135  *
       
   136  * <p> The output of a response processor is the response body, and its
       
   137  * parameterized type {@code T} determines the type of the body object returned
       
   138  * from {@code HttpResponse.body} and {@code HttpResponse.bodyAsync}. Therefore,
       
   139  * as an example, the second response processor in the list above has the type
       
   140  * {@code HttpResponse.BodyProcessor<String>} which means the type returned by
       
   141  * {@code HttpResponse.body()} is a String. Response processors can be defined
       
   142  * to return potentially any type as body.
       
   143  *
       
   144  * <p> <b>Multi responses</b>
       
   145  *
       
   146  * <p> With HTTP/2 it is possible for a server to return a main response and zero
       
   147  * or more additional responses (known as server pushes) to a client-initiated
       
   148  * request. These are handled using a special response processor called {@link
       
   149  * HttpResponse.MultiProcessor}.
       
   150  *
       
   151  * <p> <b>Blocking/asynchronous behavior and thread usage</b>
       
   152  *
       
   153  * <p> There are two styles of request sending: <i>synchronous</i> and
       
   154  * <i>asynchronous</i>. {@link #response() response} blocks the calling thread
       
   155  * until the request has been sent and the response received.
       
   156  *
       
   157  * <p> {@link #responseAsync() responseAsync} is asynchronous and returns
       
   158  * immediately with a {@link java.util.concurrent.CompletableFuture}&lt;{@link
       
   159  * HttpResponse}&gt; and when this object completes (in a background thread) the
       
   160  * response has been received.
       
   161  *
       
   162  * <p> {@link #multiResponseAsync(HttpResponse.MultiProcessor) multiResponseAsync}
       
   163  * is the variant for multi responses and is also asynchronous.
       
   164  *
       
   165  * <p> CompletableFutures can be combined in different ways to declare the
       
   166  * dependencies among several asynchronous tasks, while allowing for the maximum
       
   167  * level of parallelism to be utilized.
       
   168  *
       
   169  * <p> <b>Security checks</b>
       
   170  *
       
   171  * <p> If a security manager is present then security checks are performed by
       
   172  * the {@link #response() } and {@link #responseAsync() } methods. A {@link
       
   173  * java.net.URLPermission} or {@link java.net.SocketPermission} is required to
       
   174  * access any destination origin server and proxy server utilised. URLPermissions
       
   175  * should be preferred in policy files over SocketPermissions given the more
       
   176  * limited scope of URLPermission. Permission is always implicitly granted to a
       
   177  * system's default proxies. The URLPermission form used to access proxies uses
       
   178  * a method parameter of "CONNECT" (for all kinds of proxying) and a url string
       
   179  * of the form "socket://host:port" where host and port specify the proxy's
       
   180  * address.
       
   181  *
       
   182  * <p> <b>Examples</b>
       
   183  * <pre>
       
   184  *     import static java.net.http.HttpRequest.*;
       
   185  *     import static java.net.http.HttpResponse.*;
       
   186  *
       
   187  *     //Simple blocking
       
   188  *
       
   189  *     HttpResponse r1 = HttpRequest.create(new URI("http://www.foo.com/"))
       
   190  *                                  .GET()
       
   191  *                                 .response();
       
   192  *     int responseCode = r1.statusCode());
       
   193  *     String body = r1.body(asString());
       
   194  *
       
   195  *     HttpResponse r2 = HttpRequest.create(new URI("http://www.foo.com/"))
       
   196  *                                  .GET()
       
   197  *                                  .response();
       
   198  *
       
   199  *     System.out.println("Response was " + r1.statusCode());
       
   200  *     Path body1 = r2.body(asFile(Paths.get("/tmp/response.txt")));
       
   201  *     // Content stored in /tmp/response.txt
       
   202  *
       
   203  *     HttpResponse r3 = HttpRequest.create(new URI("http://www.foo.com/"))
       
   204  *                                  .body(fromString("param1=1, param2=2"))
       
   205  *                                  .POST()
       
   206  *                                  .response();
       
   207  *
       
   208  *     Void body2 = r3.body(ignoreBody()); // body is Void in this case
       
   209  * </pre>
       
   210  *
       
   211  * <p><b>Asynchronous Example</b>
       
   212  *
       
   213  * <p> All of the above examples will work asynchronously, if {@link
       
   214  * #responseAsync()} is used instead of {@link #response()} in which case the
       
   215  * returned object is a {@code CompletableFuture<HttpResponse>} instead of
       
   216  * {@code HttpResponse}. The following example shows how multiple requests can
       
   217  * be sent asynchronously. It also shows how dependent asynchronous operations
       
   218  * (receiving response, and receiving response body) can be chained easily using
       
   219  * one of the many methods in {@code CompletableFuture}.
       
   220  * <pre>
       
   221  * {@code
       
   222  *      // fetch a list of target URIs asynchronously and store them in Files.
       
   223  *
       
   224  *      List<URI> targets = ...
       
   225  *
       
   226  *      List<CompletableFuture<File>> futures = targets
       
   227  *          .stream()
       
   228  *          .map(target -> {
       
   229  *              return HttpRequest
       
   230  *                  .create(target)
       
   231  *                  .GET()
       
   232  *                  .responseAsync()
       
   233  *                  .thenCompose(response -> {
       
   234  *                      Path dest = Paths.get("base", target.getPath());
       
   235  *                      if (response.statusCode() == 200) {
       
   236  *                          return response.bodyAsync(asFile(dest));
       
   237  *                      } else {
       
   238  *                          return CompletableFuture.completedFuture(dest);
       
   239  *                      }
       
   240  *                  })
       
   241  *                  // convert Path -> File
       
   242  *                  .thenApply((Path dest) -> {
       
   243  *                      return dest.toFile();
       
   244  *                  });
       
   245  *              })
       
   246  *          .collect(Collectors.toList());
       
   247  *
       
   248  *      // all async operations waited for here
       
   249  *
       
   250  *      CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0]))
       
   251  *          .join();
       
   252  *
       
   253  *      // all elements of futures have completed and can be examined.
       
   254  *      // Use File.exists() to check whether file was successfully downloaded
       
   255  * }
       
   256  * </pre>
       
   257  *
       
   258  * @since 9
       
   259  */
       
   260 public abstract class HttpRequest {
       
   261 
       
   262     HttpRequest() {}
       
   263 
       
   264     /**
       
   265      * A builder of {@link HttpRequest}s. {@code HttpRequest.Builder}s are
       
   266      * created by calling {@link HttpRequest#create(URI)} or {@link
       
   267      * HttpClient#request(URI)}.
       
   268      *
       
   269      * <p> Each of the setter methods in this class modifies the state of the
       
   270      * builder and returns <i>this</i> (ie. the same instance). The methods are
       
   271      * not synchronized and should not be called from multiple threads without
       
   272      * external synchronization.
       
   273      *
       
   274      * <p> The build methods return a new {@code HttpRequest} each time they are
       
   275      * called.
       
   276      *
       
   277      * @since 9
       
   278      */
       
   279     public abstract static class Builder {
       
   280 
       
   281         Builder() {}
       
   282 
       
   283         /**
       
   284          * Sets this HttpRequest's request URI.
       
   285          *
       
   286          * @param uri the request URI
       
   287          * @return this request builder
       
   288          */
       
   289         public abstract Builder uri(URI uri);
       
   290 
       
   291         /**
       
   292          * Specifies whether this request will automatically follow redirects
       
   293          * issued by the server. The default value for this setting is the value
       
   294          * of {@link HttpClient#followRedirects() }
       
   295          *
       
   296          * @param policy the redirection policy
       
   297          * @return this request builder
       
   298          */
       
   299         public abstract Builder followRedirects(HttpClient.Redirect policy);
       
   300 
       
   301         /**
       
   302          * Request server to acknowledge request before sending request
       
   303          * body. This is disabled by default. If enabled, the server is requested
       
   304          * to send an error response or a 100-Continue response before the client
       
   305          * sends the request body. This means the request processor for the
       
   306          * request will not be invoked until this interim response is received.
       
   307          *
       
   308          * @param enable {@code true} if Expect continue to be sent
       
   309          * @return this request builder
       
   310          */
       
   311         public abstract Builder expectContinue(boolean enable);
       
   312 
       
   313         /**
       
   314          * Overrides the {@link HttpClient#version()  } setting for this
       
   315          * request.
       
   316          *
       
   317          * @param version the HTTP protocol version requested
       
   318          * @return this request builder
       
   319          */
       
   320         public abstract Builder version(HttpClient.Version version);
       
   321 
       
   322         /**
       
   323          * Adds the given name value pair to the set of headers for this request.
       
   324          *
       
   325          * @param name the header name
       
   326          * @param value the header value
       
   327          * @return this request builder
       
   328          */
       
   329         public abstract Builder header(String name, String value);
       
   330 
       
   331         /**
       
   332          * Overrides the ProxySelector set on the request's client for this
       
   333          * request.
       
   334          *
       
   335          * @param proxy the ProxySelector to use
       
   336          * @return this request builder
       
   337          */
       
   338         public abstract Builder proxy(ProxySelector proxy);
       
   339 
       
   340         /**
       
   341          * Adds the given name value pairs to the set of headers for this
       
   342          * request. The supplied Strings must alternate as names and values.
       
   343          *
       
   344          * @param headers the list of String name value pairs
       
   345          * @return this request builder
       
   346          * @throws IllegalArgumentException if there is an odd number of
       
   347          *                                  parameters
       
   348          */
       
   349         public abstract Builder headers(String... headers);
       
   350 
       
   351         /**
       
   352          * Sets a timeout for this request. If the response is not received
       
   353          * within the specified timeout then a {@link HttpTimeoutException} is
       
   354          * thrown from {@link #response() } or {@link #responseAsync() }
       
   355          * completes exceptionally with a {@code HttpTimeoutException}.
       
   356          *
       
   357          * @param unit the timeout units
       
   358          * @param timeval the number of units to wait for
       
   359          * @return this request builder
       
   360          */
       
   361         public abstract Builder timeout(TimeUnit unit, long timeval);
       
   362 
       
   363         /**
       
   364          * Sets the given name value pair to the set of headers for this
       
   365          * request. This overwrites any previously set values for name.
       
   366          *
       
   367          * @param name the header name
       
   368          * @param value the header value
       
   369          * @return this request builder
       
   370          */
       
   371         public abstract Builder setHeader(String name, String value);
       
   372 
       
   373         /**
       
   374          * Sets a request body for this builder. See {@link HttpRequest}
       
   375          * for example {@code BodyProcessor} implementations.
       
   376          * If no body is specified, then no body is sent with the request.
       
   377          *
       
   378          * @param reqproc the request body processor
       
   379          * @return this request builder
       
   380          */
       
   381         public abstract Builder body(BodyProcessor reqproc);
       
   382 
       
   383         /**
       
   384          * Builds and returns a GET {@link HttpRequest} from this builder.
       
   385          *
       
   386          * @return a {@code HttpRequest}
       
   387          */
       
   388         public abstract HttpRequest GET();
       
   389 
       
   390         /**
       
   391          * Builds and returns a POST {@link HttpRequest} from this builder.
       
   392          *
       
   393          * @return a {@code HttpRequest}
       
   394          */
       
   395         public abstract HttpRequest POST();
       
   396 
       
   397         /**
       
   398          * Builds and returns a PUT {@link HttpRequest} from this builder.
       
   399          *
       
   400          * @return a {@code HttpRequest}
       
   401          */
       
   402         public abstract HttpRequest PUT();
       
   403 
       
   404         /**
       
   405          * Builds and returns a {@link HttpRequest} from this builder using
       
   406          * the given method String. The method string is case-sensitive, and
       
   407          * may be rejected if an upper-case string is not used.
       
   408          *
       
   409          * @param method the method to use
       
   410          * @return a {@code HttpRequest}
       
   411          * @throws IllegalArgumentException if an unrecognised method is used
       
   412          */
       
   413         public abstract HttpRequest method(String method);
       
   414 
       
   415         /**
       
   416          * Returns an exact duplicate copy of this Builder based on current
       
   417          * state. The new builder can then be modified independently of this
       
   418          * builder.
       
   419          *
       
   420          * @return an exact copy of this Builder
       
   421          */
       
   422         public abstract Builder copy();
       
   423     }
       
   424 
       
   425     /**
       
   426      * Creates a HttpRequest builder from the <i>default</i> HttpClient.
       
   427      *
       
   428      * @param uri the request URI
       
   429      * @return a new request builder
       
   430      */
       
   431     public static HttpRequest.Builder create(URI uri) {
       
   432         return HttpClient.getDefault().request(uri);
       
   433     }
       
   434 
       
   435     /**
       
   436      * Returns the follow-redirects setting for this request.
       
   437      *
       
   438      * @return follow redirects setting
       
   439      */
       
   440     public abstract HttpClient.Redirect followRedirects();
       
   441 
       
   442     /**
       
   443      * Returns the response to this request, by sending it and blocking if
       
   444      * necessary to get the response. The {@link HttpResponse} contains the
       
   445      * response status and headers.
       
   446      *
       
   447      * @return a HttpResponse for this request
       
   448      * @throws IOException if an I/O error occurs
       
   449      * @throws InterruptedException if the operation was interrupted
       
   450      * @throws SecurityException if the caller does not have the required
       
   451      *                           permission
       
   452      * @throws IllegalStateException if called more than once or if
       
   453      *                               responseAsync() called previously
       
   454      */
       
   455     public abstract HttpResponse response()
       
   456         throws IOException, InterruptedException;
       
   457 
       
   458     /**
       
   459      * Sends the request and returns the response asynchronously. This method
       
   460      * returns immediately with a {@link CompletableFuture}&lt;{@link
       
   461      * HttpResponse}&gt;
       
   462      *
       
   463      * @return a {@code CompletableFuture<HttpResponse>}
       
   464      * @throws IllegalStateException if called more than once or if response()
       
   465      *                               called previously.
       
   466      */
       
   467     public abstract CompletableFuture<HttpResponse> responseAsync();
       
   468 
       
   469     /**
       
   470      * Sends the request asynchronously expecting multiple responses.
       
   471      *
       
   472      * <p> This method must be given a {@link HttpResponse.MultiProcessor} to
       
   473      * handle the multiple responses.
       
   474      *
       
   475      * <p> If a security manager is set, the caller must possess a {@link
       
   476      * java.net.URLPermission} for the request's URI, method and any user set
       
   477      * headers. The security manager is also checked for each incoming
       
   478      * additional server generated request/response. Any request that fails the
       
   479      * security check, is canceled and ignored.
       
   480      *
       
   481      * <p> This method can be used for both HTTP/1.1 and HTTP/2, but in cases
       
   482      * where multiple responses are not supported, the MultiProcessor
       
   483      * only receives the main response.
       
   484      *
       
   485      * <p> The aggregate {@code CompletableFuture} returned from this method
       
   486      * returns a {@code <U>} defined by the {@link HttpResponse.MultiProcessor}
       
   487      * implementation supplied. This will typically be a Collection of
       
   488      * HttpResponses or of some response body type.
       
   489      *
       
   490      * @param <U> the aggregate response type
       
   491      * @param rspproc the MultiProcessor for the request
       
   492      * @return a {@code CompletableFuture<U>}
       
   493      * @throws IllegalStateException if the request has already been sent.
       
   494      */
       
   495     public abstract <U> CompletableFuture<U>
       
   496     multiResponseAsync(HttpResponse.MultiProcessor<U> rspproc);
       
   497 
       
   498     /**
       
   499      * Returns the request method for this request. If not set explicitly,
       
   500      * the default method for any request is "GET".
       
   501      *
       
   502      * @return this request's method
       
   503      */
       
   504     public abstract String method();
       
   505 
       
   506     /**
       
   507      * Returns this request's {@link HttpRequest.Builder#expectContinue(boolean)
       
   508      * expect continue } setting.
       
   509      *
       
   510      * @return this request's expect continue setting
       
   511      */
       
   512     public abstract boolean expectContinue();
       
   513 
       
   514     /**
       
   515      * Returns this request's request URI.
       
   516      *
       
   517      * @return this request's URI
       
   518      */
       
   519     public abstract URI uri();
       
   520 
       
   521     /**
       
   522      * Returns this request's {@link HttpClient}.
       
   523      *
       
   524      * @return this request's HttpClient
       
   525      */
       
   526     public abstract HttpClient client();
       
   527 
       
   528     /**
       
   529      * Returns the HTTP protocol version that this request will use or used.
       
   530      *
       
   531      * @return HTTP protocol version
       
   532      */
       
   533     public abstract HttpClient.Version version();
       
   534 
       
   535     /**
       
   536      * The (user-accessible) request headers that this request was (or will be)
       
   537      * sent with.
       
   538      *
       
   539      * @return this request's HttpHeaders
       
   540      */
       
   541     public abstract HttpHeaders headers();
       
   542 
       
   543     /**
       
   544      * Returns a request processor whose body is the given String, converted
       
   545      * using the {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1}
       
   546      * character set.
       
   547      *
       
   548      * @param body the String containing the body
       
   549      * @return a BodyProcessor
       
   550      */
       
   551     public static BodyProcessor fromString(String body) {
       
   552         return fromString(body, StandardCharsets.ISO_8859_1);
       
   553     }
       
   554 
       
   555     /**
       
   556      * A request processor that takes data from the contents of a File.
       
   557      *
       
   558      * @param path the path to the file containing the body
       
   559      * @return a BodyProcessor
       
   560      */
       
   561     public static BodyProcessor fromFile(Path path) {
       
   562         FileChannel fc;
       
   563         long size;
       
   564 
       
   565         try {
       
   566             fc = FileChannel.open(path);
       
   567             size = fc.size();
       
   568         } catch (IOException e) {
       
   569             throw new UncheckedIOException(e);
       
   570         }
       
   571 
       
   572         return new BodyProcessor() {
       
   573             LongConsumer flow;
       
   574 
       
   575             @Override
       
   576             public long onRequestStart(HttpRequest hr, LongConsumer flow) {
       
   577                 // could return exact file length, but for now -1
       
   578                 this.flow = flow;
       
   579                 flow.accept(1);
       
   580                 if (size != 0) {
       
   581                     return size;
       
   582                 } else {
       
   583                     return -1;
       
   584                 }
       
   585             }
       
   586 
       
   587             @Override
       
   588             public boolean onRequestBodyChunk(ByteBuffer buffer) throws IOException {
       
   589                 int n = fc.read(buffer);
       
   590                 if (n == -1) {
       
   591                     fc.close();
       
   592                     return true;
       
   593                 }
       
   594                 flow.accept(1);
       
   595                 return false;
       
   596             }
       
   597 
       
   598             @Override
       
   599             public void onRequestError(Throwable t) {
       
   600                 try {
       
   601                     fc.close();
       
   602                 } catch (IOException ex) {
       
   603                     Log.logError(ex.toString());
       
   604                 }
       
   605             }
       
   606         };
       
   607     }
       
   608 
       
   609     /**
       
   610      * Returns a request processor whose body is the given String, converted
       
   611      * using the given character set.
       
   612      *
       
   613      * @param s the String containing the body
       
   614      * @param charset the character set to convert the string to bytes
       
   615      * @return a BodyProcessor
       
   616      */
       
   617     public static BodyProcessor fromString(String s, Charset charset) {
       
   618         return fromByteArray(s.getBytes(charset));
       
   619     }
       
   620 
       
   621     /**
       
   622      * Returns a request processor whose body is the given byte array.
       
   623      *
       
   624      * @param buf the byte array containing the body
       
   625      * @return a BodyProcessor
       
   626      */
       
   627     public static BodyProcessor fromByteArray(byte[] buf) {
       
   628         return fromByteArray(buf, 0, buf.length);
       
   629     }
       
   630 
       
   631     /**
       
   632      * Returns a request processor whose body is the content of the given byte
       
   633      * array length bytes starting from the specified offset.
       
   634      *
       
   635      * @param buf the byte array containing the body
       
   636      * @param offset the offset of the first byte
       
   637      * @param length the number of bytes to use
       
   638      * @return a BodyProcessor
       
   639      */
       
   640     public static BodyProcessor fromByteArray(byte[] buf, int offset, int length) {
       
   641 
       
   642         return new BodyProcessor() {
       
   643             LongConsumer flow;
       
   644             byte[] barray;
       
   645             int index;
       
   646             int sent;
       
   647 
       
   648             @Override
       
   649             public long onRequestStart(HttpRequest hr, LongConsumer flow) {
       
   650                 this.flow = flow;
       
   651                 flow.accept(1);
       
   652                 barray = buf;
       
   653                 index = offset;
       
   654                 return length;
       
   655             }
       
   656 
       
   657             @Override
       
   658             public boolean onRequestBodyChunk(ByteBuffer buffer)
       
   659                 throws IOException
       
   660             {
       
   661                 if (sent == length) {
       
   662                     return true;
       
   663                 }
       
   664 
       
   665                 int remaining = buffer.remaining();
       
   666                 int left = length - sent;
       
   667                 int n = remaining > left ? left : remaining;
       
   668                 buffer.put(barray, index, n);
       
   669                 index += n;
       
   670                 sent += n;
       
   671                 flow.accept(1);
       
   672                 return sent == length;
       
   673             }
       
   674 
       
   675             @Override
       
   676             public void onRequestError(Throwable t) {
       
   677                 Log.logError(t.toString());
       
   678             }
       
   679         };
       
   680     }
       
   681 
       
   682     /**
       
   683      * A request processor that takes data from an Iterator of byte arrays.
       
   684      *
       
   685      * @param iter an Iterator of byte arrays
       
   686      * @return a BodyProcessor
       
   687      */
       
   688     public static BodyProcessor fromByteArrays(Iterator<byte[]> iter) {
       
   689 
       
   690         return new BodyProcessor() {
       
   691             LongConsumer flow;
       
   692             byte[] current;
       
   693             int curIndex;
       
   694 
       
   695             @Override
       
   696             public long onRequestStart(HttpRequest hr, LongConsumer flow) {
       
   697                 this.flow = flow;
       
   698                 flow.accept(1);
       
   699                 return -1;
       
   700             }
       
   701 
       
   702             @Override
       
   703             public boolean onRequestBodyChunk(ByteBuffer buffer)
       
   704                 throws IOException
       
   705             {
       
   706                 int remaining;
       
   707 
       
   708                 while ((remaining = buffer.remaining()) > 0) {
       
   709                     if (current == null) {
       
   710                         if (!iter.hasNext()) {
       
   711                             return true;
       
   712                         }
       
   713                         current = iter.next();
       
   714                         curIndex = 0;
       
   715                     }
       
   716                     int n = Math.min(remaining, current.length - curIndex);
       
   717                     buffer.put(current, curIndex, n);
       
   718                     curIndex += n;
       
   719 
       
   720                     if (curIndex == current.length) {
       
   721                         current = null;
       
   722                         flow.accept(1);
       
   723                         return false;
       
   724                     }
       
   725                 }
       
   726                 flow.accept(1);
       
   727                 return false;
       
   728             }
       
   729 
       
   730             @Override
       
   731             public void onRequestError(Throwable t) {
       
   732                 Log.logError(t.toString());
       
   733             }
       
   734         };
       
   735     }
       
   736 
       
   737     /**
       
   738      * A request processor that reads its data from an InputStream.
       
   739      *
       
   740      * @param stream an InputStream
       
   741      * @return a BodyProcessor
       
   742      */
       
   743     public static BodyProcessor fromInputStream(InputStream stream) {
       
   744         // for now, this blocks. It could be offloaded to a separate thread
       
   745         // to do reading and guarantee that onRequestBodyChunk() won't block
       
   746         return new BodyProcessor() {
       
   747             LongConsumer flow;
       
   748 
       
   749             @Override
       
   750             public long onRequestStart(HttpRequest hr, LongConsumer flow) {
       
   751                 this.flow = flow;
       
   752                 flow.accept(1);
       
   753                 return -1;
       
   754             }
       
   755 
       
   756             @Override
       
   757             public boolean onRequestBodyChunk(ByteBuffer buffer)
       
   758                 throws IOException
       
   759             {
       
   760                 int remaining = buffer.remaining();
       
   761                 int n = stream.read(buffer.array(), buffer.arrayOffset(), remaining);
       
   762                 if (n == -1) {
       
   763                     stream.close();
       
   764                     return true;
       
   765                 }
       
   766                 buffer.position(buffer.position() + n);
       
   767                 flow.accept(1);
       
   768                 return false;
       
   769             }
       
   770 
       
   771             @Override
       
   772             public void onRequestError(Throwable t) {
       
   773                 Log.logError(t.toString());
       
   774             }
       
   775         };
       
   776     }
       
   777 
       
   778     /**
       
   779      * A request processor which sends no request body.
       
   780      *
       
   781      * @return a BodyProcessor
       
   782      */
       
   783     public static BodyProcessor noBody() {
       
   784         return new BodyProcessor() {
       
   785 
       
   786             @Override
       
   787             public long onRequestStart(HttpRequest hr, LongConsumer flow) {
       
   788                 return 0;
       
   789             }
       
   790 
       
   791             @Override
       
   792             public boolean onRequestBodyChunk(ByteBuffer buffer)
       
   793                 throws IOException
       
   794             {
       
   795                 throw new InternalError("should never reach here");
       
   796             }
       
   797 
       
   798             @Override
       
   799             public void onRequestError(Throwable t) {
       
   800                 Log.logError(t.toString());
       
   801             }
       
   802         };
       
   803     }
       
   804 
       
   805     /**
       
   806      * A request processor which obtains the request body from some source.
       
   807      * Implementations of this interface are provided which allow request bodies
       
   808      * to be supplied from standard types, such as {@code String, byte[], File,
       
   809      * InputStream}. Other implementations can be provided.
       
   810      *
       
   811      * <p> The methods of this interface may be called from multiple threads,
       
   812      * but only one method is invoked at a time, and behaves as if called from
       
   813      * one thread.
       
   814      *
       
   815      * <p> See {@link HttpRequest} for implementations that take request bodies
       
   816      * from {@code byte arrays, Strings, Paths} etc.
       
   817      *
       
   818      * @since 9
       
   819      */
       
   820     public interface BodyProcessor {
       
   821 
       
   822         /**
       
   823          * Called before a request is sent. Is expected to return the content
       
   824          * length of the request body. Zero means no content. Less than zero
       
   825          * means an unknown positive content-length, and the body will be
       
   826          * streamed.
       
   827          *
       
   828          * <p> The flowController object must be used to manage the flow of
       
   829          * calls to {@link #onRequestBodyChunk(ByteBuffer)}. The typical usage
       
   830          * for a non-blocking processor is to call it once inside
       
   831          * onRequestStart() and once during each call to onRequestBodyChunk().
       
   832          *
       
   833          * @param hr the request
       
   834          * @param flowController the HttpFlowController
       
   835          * @return the content length
       
   836          * @throws IOException if an I/O error occurs
       
   837          */
       
   838         long onRequestStart(HttpRequest hr, LongConsumer flowController)
       
   839             throws IOException;
       
   840 
       
   841         /**
       
   842          * Called if sending a request body fails.
       
   843          *
       
   844          * @implSpec The default implementation does nothing.
       
   845          *
       
   846          * @param t the Throwable that caused the failure
       
   847          */
       
   848         default void onRequestError(Throwable t) { }
       
   849 
       
   850         /**
       
   851          * Called to obtain a buffer of data to send. The data must be placed
       
   852          * in the provided buffer. The implementation should not block. The
       
   853          * boolean return code notifies the protocol implementation if the
       
   854          * supplied buffer is the final one (or not).
       
   855          *
       
   856          * @param buffer a ByteBuffer to write data into
       
   857          * @return whether or not this is the last buffer
       
   858          * @throws IOException if an I/O error occurs
       
   859          */
       
   860         boolean onRequestBodyChunk(ByteBuffer buffer) throws IOException;
       
   861 
       
   862         /**
       
   863          * Called when the request body has been completely sent.
       
   864          *
       
   865          * @implSpec The default implementation does nothing
       
   866          */
       
   867         default void onComplete() {
       
   868             // TODO: need to call this
       
   869         }
       
   870     }
       
   871 }