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.FileNotFoundException; 29 import java.io.InputStream; 30 import java.net.URI; 31 import java.net.URLPermission; 32 import java.nio.ByteBuffer; 33 import java.nio.charset.Charset; 34 import java.nio.charset.StandardCharsets; 35 import java.nio.file.Files; 36 import java.nio.file.Path; 37 import java.security.AccessController; 38 import java.security.PrivilegedAction; 39 import java.time.Duration; 40 import java.util.Iterator; 41 import java.util.Objects; 42 import java.util.Optional; 43 import java.util.concurrent.CompletableFuture; 44 import java.util.concurrent.Executor; 45 import java.util.concurrent.Flow; 46 import java.util.function.Supplier; 47 import static java.nio.charset.StandardCharsets.UTF_8; 48 49 /** 50 * Represents one HTTP request which can be sent to a server. 51 * {@Incubating } 52 * 53 * <p> {@code HttpRequest} instances are built from {@code HttpRequest} 54 * {@linkplain HttpRequest.Builder builders}. {@code HttpRequest} builders 55 * are obtained by calling {@link HttpRequest#newBuilder(URI) HttpRequest.newBuilder}. 56 * A request's {@linkplain URI}, headers and body can be set. Request bodies are 57 * provided through a {@link BodyPublisher} object supplied to the 58 * {@link Builder#DELETE(BodyPublisher) DELETE}, 59 * {@link Builder#POST(BodyPublisher) POST} or 60 * {@link Builder#PUT(BodyPublisher) PUT} methods. 61 * {@link Builder#GET() GET} does not take a body. Once all required 62 * parameters have been set in the builder, {@link Builder#build() } is called 63 * to return the {@code HttpRequest}. Builders can also be copied and modified 64 * multiple times in order to build multiple related requests that differ in 65 * some parameters. 66 * 67 * <p> Two simple, example HTTP interactions are shown below: 68 * <pre> 69 * {@code 70 * HttpClient client = HttpClient.newHttpClient(); 71 * 72 * // GET 73 * HttpResponse<String> response = client.send( 74 * HttpRequest 75 * .newBuilder(new URI("http://www.foo.com/")) 76 * .headers("Foo", "foovalue", "Bar", "barvalue") 77 * .GET() 78 * .build(), 79 * BodyHandler.asString() 80 * ); 81 * int statusCode = response.statusCode(); 82 * String body = response.body(); 83 * 84 * // POST 85 * HttpResponse<Path> response = client.send( 86 * HttpRequest 87 * .newBuilder(new URI("http://www.foo.com/")) 88 * .headers("Foo", "foovalue", "Bar", "barvalue") 89 * .POST(BodyPublisher.fromString("Hello world")) 90 * .build(), 91 * BodyHandler.asFile(Paths.get("/path")) 92 * ); 93 * int statusCode = response.statusCode(); 94 * Path body = response.body(); // should be "/path" 95 * } 96 * </pre> 97 * 98 * <p> The request is sent and the response obtained by calling one of the 99 * following methods in {@link HttpClient}. 100 * <ul><li>{@link HttpClient#send(HttpRequest, HttpResponse.BodyHandler)} blocks 101 * until the entire request has been sent and the response has been received.</li> 102 * <li>{@link HttpClient#sendAsync(HttpRequest,HttpResponse.BodyHandler)} sends the 103 * request and receives the response asynchronously. Returns immediately with a 104 * {@link java.util.concurrent.CompletableFuture CompletableFuture}<{@link 105 * HttpResponse}>.</li> 106 * <li>{@link HttpClient#sendAsync(HttpRequest, HttpResponse.MultiSubscriber) } 107 * sends the request asynchronously, expecting multiple responses. This 108 * capability is of most relevance to HTTP/2 server push, but can be used for 109 * single responses (HTTP/1.1 or HTTP/2) also.</li> 110 * </ul> 111 * 112 * <p> Once a {@link HttpResponse} is received, the headers, response code 113 * and body (typically) are available. Whether the body has been read or not 114 * depends on the type {@code <T>} of the response body. See below. 115 * 116 * <p> See below for discussion of synchronous versus asynchronous usage. 117 * 118 * <p> <b>Request bodies</b> 119 * 120 * <p> Request bodies can be sent using one of the convenience request publisher 121 * implementations below, provided in {@link BodyPublisher}. Alternatively, a 122 * custom Publisher implementation can be used. 123 * <ul> 124 * <li>{@link BodyPublisher#fromByteArray(byte[]) fromByteArray(byte[])} from byte array</li> 125 * <li>{@link BodyPublisher#fromByteArrays(Iterable) fromByteArrays(Iterable)} 126 * from an Iterable of byte arrays</li> 127 * <li>{@link BodyPublisher#fromFile(java.nio.file.Path) fromFile(Path)} from the file located 128 * at the given Path</li> 129 * <li>{@link BodyPublisher#fromString(java.lang.String) fromString(String)} from a String </li> 130 * <li>{@link BodyPublisher#fromInputStream(Supplier) fromInputStream}({@link Supplier}< 131 * {@link InputStream}>) from an InputStream obtained from a Supplier</li> 132 * <li>{@link BodyPublisher#noBody() } no request body is sent</li> 133 * </ul> 134 * 135 * <p> <b>Response bodies</b> 136 * 137 * <p> Responses bodies are handled at two levels. When sending the request, 138 * a response body handler is specified. This is a function ({@linkplain 139 * HttpResponse.BodyHandler}) which will be called with the response status code 140 * and headers, once they are received. This function is then expected to return 141 * a {@link HttpResponse.BodySubscriber}{@code <T>} which is then used to read 142 * the response body, converting it into an instance of T. After this occurs, 143 * the response becomes available in a {@link HttpResponse}, and {@link 144 * HttpResponse#body()} can then be called to obtain the actual body. Some 145 * implementations and examples of usage of both {@link 146 * HttpResponse.BodySubscriber} and {@link HttpResponse.BodyHandler} are 147 * provided in {@link HttpResponse}: 148 * 149 * <p> <b>Some of the pre-defined body handlers</b><br> 150 * <ul> 151 * <li>{@link HttpResponse.BodyHandler#asByteArray() BodyHandler.asByteArray()} 152 * stores the body in a byte array</li> 153 * <li>{@link HttpResponse.BodyHandler#asString() BodyHandler.asString()} 154 * stores the body as a String </li> 155 * <li>{@link HttpResponse.BodyHandler#asFile(java.nio.file.Path) 156 * BodyHandler.asFile(Path)} stores the body in a named file</li> 157 * <li>{@link HttpResponse.BodyHandler#discard(Object) BodyHandler.discard()} 158 * discards the response body and returns the given value instead.</li> 159 * </ul> 160 * 161 * <p> <b>Multi responses</b> 162 * 163 * <p> With HTTP/2 it is possible for a server to return a main response and zero 164 * or more additional responses (known as server pushes) to a client-initiated 165 * request. These are handled using a special response subscriber called {@link 166 * HttpResponse.MultiSubscriber}. 167 * 168 * <p> <b>Blocking/asynchronous behavior and thread usage</b> 169 * 170 * <p> There are two styles of request sending: <i>synchronous</i> and 171 * <i>asynchronous</i>. {@link HttpClient#send(HttpRequest, HttpResponse.BodyHandler) } 172 * blocks the calling thread until the request has been sent and the response received. 173 * 174 * <p> {@link HttpClient#sendAsync(HttpRequest, HttpResponse.BodyHandler)} is 175 * asynchronous and returns immediately with a {@link CompletableFuture}<{@link 176 * HttpResponse}> and when this object completes (possibly in a different 177 * thread) the response has been received. 178 * 179 * <p> {@link HttpClient#sendAsync(HttpRequest, HttpResponse.MultiSubscriber)} 180 * is the variant for multi responses and is also asynchronous. 181 * 182 * <p> Instances of {@code CompletableFuture} can be combined in different ways 183 * to declare the dependencies among several asynchronous tasks, while allowing 184 * for the maximum level of parallelism to be utilized. 185 * 186 * <p> <a id="securitychecks"></a><b>Security checks</b></a> 187 * 188 * <p> If a security manager is present then security checks are performed by 189 * the HTTP Client's sending methods. An appropriate {@link URLPermission} is 190 * required to access the destination server, and proxy server if one has 191 * been configured. The {@code URLPermission} form used to access proxies uses a 192 * method parameter of {@code "CONNECT"} (for all kinds of proxying) and a URL 193 * string of the form {@code "socket://host:port"} where host and port specify 194 * the proxy's address. 195 * 196 * <p> In this implementation, if an explicit {@linkplain 197 * HttpClient.Builder#executor(Executor) executor} has not been set for an 198 * {@code HttpClient}, and a security manager has been installed, then the 199 * default executor will execute asynchronous and dependent tasks in a context 200 * that is granted no permissions. Custom {@linkplain HttpRequest.BodyPublisher 201 * request body publishers}, {@linkplain HttpResponse.BodyHandler response body 202 * handlers}, {@linkplain HttpResponse.BodySubscriber response body subscribers}, 203 * and {@linkplain WebSocket.Listener WebSocket Listeners}, if executing 204 * operations that require privileges, should do so within an appropriate 205 * {@linkplain AccessController#doPrivileged(PrivilegedAction) privileged context}. 206 * 207 * <p> <b>Examples</b> 208 * <pre>{@code 209 * HttpClient client = HttpClient 210 * .newBuilder() 211 * .build(); 212 * 213 * HttpRequest request = HttpRequest 214 * .newBuilder(new URI("http://www.foo.com/")) 215 * .POST(BodyPublisher.fromString("Hello world")) 216 * .build(); 217 * 218 * HttpResponse<Path> response = 219 * client.send(request, BodyHandler.asFile(Paths.get("/path"))); 220 * 221 * Path body = response.body(); 222 * }</pre> 223 * 224 * <p><b>Asynchronous Example</b> 225 * 226 * <p> The above example will work asynchronously, if {@link HttpClient#sendAsync 227 * (HttpRequest, HttpResponse.BodyHandler) sendAsync} is used instead of 228 * {@link HttpClient#send(HttpRequest,HttpResponse.BodyHandler) send} 229 * in which case the returned object is a {@link CompletableFuture}{@code <HttpResponse>} 230 * instead of {@link HttpResponse}. The following example shows how multiple requests 231 * can be sent asynchronously. It also shows how dependent asynchronous operations 232 * (receiving response, and receiving response body) can be chained easily using 233 * one of the many methods in {@code CompletableFuture}. 234 * <pre> 235 * {@code 236 * // fetch a list of target URIs asynchronously and store them in Files. 237 * 238 * List<URI> targets = ... 239 * 240 * List<CompletableFuture<File>> futures = targets 241 * .stream() 242 * .map(target -> client 243 * .sendAsync( 244 * HttpRequest.newBuilder(target) 245 * .GET() 246 * .build(), 247 * BodyHandler.asFile(Paths.get("base", target.getPath()))) 248 * .thenApply(response -> response.body()) 249 * .thenApply(path -> path.toFile())) 250 * .collect(Collectors.toList()); 251 * 252 * // all async operations waited for here 253 * 254 * CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0])) 255 * .join(); 256 * 257 * // all elements of futures have completed and can be examined. 258 * // Use File.exists() to check whether file was successfully downloaded 259 * } 260 * </pre> 261 * 262 * <p> Unless otherwise stated, {@code null} parameter values will cause methods 263 * of this class to throw {@code NullPointerException}. 264 * 265 * @since 9 266 */ 267 public abstract class HttpRequest { 268 269 /** 270 * Creates an HttpRequest. 271 */ 272 protected HttpRequest() {} 273 274 /** 275 * A builder of {@linkplain HttpRequest HTTP Requests}. 276 * {@Incubating} 277 * 278 * <p> Instances of {@code HttpRequest.Builder} are created by calling {@link 279 * HttpRequest#newBuilder(URI)} or {@link HttpRequest#newBuilder()}. 280 * 281 * <p> Each of the setter methods in this class modifies the state of the 282 * builder and returns <i>this</i> (ie. the same instance). The methods are 283 * not synchronized and should not be called from multiple threads without 284 * external synchronization. 285 * 286 * <p> Note, that not all request headers may be set by user code. Some are 287 * restricted for security reasons and others such as the headers relating 288 * to authentication, redirection and cookie management are managed by 289 * specific APIs rather than through directly user set headers. 290 * 291 * <p> The {@linkplain #build() build} method returns a new {@code 292 * HttpRequest} each time it is invoked. 293 * 294 * @since 9 295 */ 296 public abstract static class Builder { 297 298 /** 299 * Creates a Builder. 300 */ 301 protected Builder() {} 302 303 /** 304 * Sets this {@code HttpRequest}'s request {@code URI}. 305 * 306 * @param uri the request URI 307 * @return this request builder 308 * @throws IllegalArgumentException if the {@code URI} scheme is not 309 * supported 310 */ 311 public abstract Builder uri(URI uri); 312 313 /** 314 * Requests the server to acknowledge the request before sending the 315 * body. This is disabled by default. If enabled, the server is 316 * requested to send an error response or a {@code 100 Continue} 317 * response before the client sends the request body. This means the 318 * request publisher for the request will not be invoked until this 319 * interim response is received. 320 * 321 * @param enable {@code true} if Expect continue to be sent 322 * @return this request builder 323 */ 324 public abstract Builder expectContinue(boolean enable); 325 326 /** 327 * Sets the preferred {@link HttpClient.Version} for this request. 328 * 329 * <p> The corresponding {@link HttpResponse} should be checked for the 330 * version that was actually used. If the version is not set in a 331 * request, then the version requested will be that of the sending 332 * {@link HttpClient}. 333 * 334 * @param version the HTTP protocol version requested 335 * @return this request builder 336 */ 337 public abstract Builder version(HttpClient.Version version); 338 339 /** 340 * Adds the given name value pair to the set of headers for this request. 341 * The given value is added to the list of values for that name. 342 * 343 * @param name the header name 344 * @param value the header value 345 * @return this request builder 346 * @throws IllegalArgumentException if the header name or value is not 347 * valid, see <a href="https://tools.ietf.org/html/rfc7230#section-3.2"> 348 * RFC 7230 section-3.2</a> 349 */ 350 public abstract Builder header(String name, String value); 351 352 /** 353 * Adds the given name value pairs to the set of headers for this 354 * request. The supplied {@code String} instances must alternate as 355 * header names and header values. 356 * To add several values to the same name then the same name must 357 * be supplied with each new value. 358 * 359 * @param headers the list of name value pairs 360 * @return this request builder 361 * @throws IllegalArgumentException if there are an odd number of 362 * parameters, or if a header name or value is not valid, see 363 * <a href="https://tools.ietf.org/html/rfc7230#section-3.2"> 364 * RFC 7230 section-3.2</a> 365 */ 366 public abstract Builder headers(String... headers); 367 368 /** 369 * Sets a timeout for this request. If the response is not received 370 * within the specified timeout then a {@link HttpTimeoutException} is 371 * thrown from {@link HttpClient#send(jdk.incubator.http.HttpRequest, 372 * jdk.incubator.http.HttpResponse.BodyHandler) HttpClient::send} or 373 * {@link HttpClient#sendAsync(jdk.incubator.http.HttpRequest, 374 * jdk.incubator.http.HttpResponse.BodyHandler) HttpClient::sendAsync} 375 * completes exceptionally with a {@code HttpTimeoutException}. The effect 376 * of not setting a timeout is the same as setting an infinite Duration, ie. 377 * block forever. 378 * 379 * @param duration the timeout duration 380 * @return this request builder 381 * @throws IllegalArgumentException if the duration is non-positive 382 */ 383 public abstract Builder timeout(Duration duration); 384 385 /** 386 * Sets the given name value pair to the set of headers for this 387 * request. This overwrites any previously set values for name. 388 * 389 * @param name the header name 390 * @param value the header value 391 * @return this request builder 392 * @throws IllegalArgumentException if the header name or value is not valid, 393 * see <a href="https://tools.ietf.org/html/rfc7230#section-3.2"> 394 * RFC 7230 section-3.2</a> 395 */ 396 public abstract Builder setHeader(String name, String value); 397 398 /** 399 * Sets the request method of this builder to GET. 400 * This is the default. 401 * 402 * @return a {@code HttpRequest} 403 */ 404 public abstract Builder GET(); 405 406 /** 407 * Sets the request method of this builder to POST and sets its 408 * request body publisher to the given value. 409 * 410 * @param bodyPublisher the body publisher 411 * 412 * @return a {@code HttpRequest} 413 */ 414 public abstract Builder POST(BodyPublisher bodyPublisher); 415 416 /** 417 * Sets the request method of this builder to PUT and sets its 418 * request body publisher to the given value. 419 * 420 * @param bodyPublisher the body publisher 421 * 422 * @return a {@code HttpRequest} 423 */ 424 public abstract Builder PUT(BodyPublisher bodyPublisher); 425 426 /** 427 * Sets the request method of this builder to DELETE and sets its 428 * request body publisher to the given value. 429 * 430 * @param bodyPublisher the body publisher 431 * 432 * @return a {@code HttpRequest} 433 */ 434 435 public abstract Builder DELETE(BodyPublisher bodyPublisher); 436 437 /** 438 * Sets the request method and request body of this builder to the 439 * given values. 440 * 441 * @apiNote The {@linkplain BodyPublisher#noBody() noBody} request 442 * body publisher can be used where no request body is required or 443 * appropriate. 444 * 445 * @param method the method to use 446 * @param bodyPublisher the body publisher 447 * @return a {@code HttpRequest} 448 * @throws IllegalArgumentException if the method is unrecognised 449 */ 450 public abstract Builder method(String method, BodyPublisher bodyPublisher); 451 452 /** 453 * Builds and returns a {@link HttpRequest}. 454 * 455 * @return the request 456 * @throws IllegalStateException if a URI has not been set 457 */ 458 public abstract HttpRequest build(); 459 460 /** 461 * Returns an exact duplicate copy of this {@code Builder} based on 462 * current state. The new builder can then be modified independently of 463 * this builder. 464 * 465 * @return an exact copy of this Builder 466 */ 467 public abstract Builder copy(); 468 } 469 470 /** 471 * Creates a {@code HttpRequest} builder. 472 * 473 * @param uri the request URI 474 * @return a new request builder 475 * @throws IllegalArgumentException if the URI scheme is not supported. 476 */ 477 public static HttpRequest.Builder newBuilder(URI uri) { 478 return new HttpRequestBuilderImpl(uri); 479 } 480 481 /** 482 * Creates a {@code HttpRequest} builder. 483 * 484 * @return a new request builder 485 */ 486 public static HttpRequest.Builder newBuilder() { 487 return new HttpRequestBuilderImpl(); 488 } 489 490 /** 491 * Returns an {@code Optional} containing the {@link BodyPublisher} set on 492 * this request. If no {@code BodyPublisher} was set in the requests's 493 * builder, then the {@code Optional} is empty. 494 * 495 * @return an {@code Optional} containing this request's {@code BodyPublisher} 496 */ 497 public abstract Optional<BodyPublisher> bodyPublisher(); 498 499 /** 500 * Returns the request method for this request. If not set explicitly, 501 * the default method for any request is "GET". 502 * 503 * @return this request's method 504 */ 505 public abstract String method(); 506 507 /** 508 * Returns an {@code Optional} containing this request's timeout duration. 509 * If the timeout duration was not set in the request's builder, then the 510 * {@code Optional} is empty. 511 * 512 * @return an {@code Optional} containing this request's timeout duration 513 */ 514 public abstract Optional<Duration> timeout(); 515 516 /** 517 * Returns this request's {@link HttpRequest.Builder#expectContinue(boolean) 518 * expect continue } setting. 519 * 520 * @return this request's expect continue setting 521 */ 522 public abstract boolean expectContinue(); 523 524 /** 525 * Returns this request's request {@code URI}. 526 * 527 * @return this request's URI 528 */ 529 public abstract URI uri(); 530 531 /** 532 * Returns an {@code Optional} containing the HTTP protocol version that 533 * will be requested for this {@code HttpRequest}. If the version was not 534 * set in the request's builder, then the {@code Optional} is empty. 535 * In that case, the version requested will be that of the sending 536 * {@link HttpClient}. The corresponding {@link HttpResponse} should be 537 * queried to determine the version that was actually used. 538 * 539 * @return HTTP protocol version 540 */ 541 public abstract Optional<HttpClient.Version> version(); 542 543 /** 544 * The (user-accessible) request headers that this request was (or will be) 545 * sent with. 546 * 547 * @return this request's HttpHeaders 548 */ 549 public abstract HttpHeaders headers(); 550 551 /** 552 * Tests this HTTP request instance for equality with the given object. 553 * 554 * <p> If the given object is not an {@code HttpRequest} then this 555 * method returns {@code false}. Two HTTP requests are equal if their URI, 556 * method, and headers fields are all equal. 557 * 558 * <p> This method satisfies the general contract of the {@link 559 * Object#equals(Object) Object.equals} method. 560 * 561 * @param obj the object to which this object is to be compared 562 * @return {@code true} if, and only if, the given object is an {@code 563 * HttpRequest} that is equal to this HTTP request 564 */ 565 @Override 566 public final boolean equals(Object obj) { 567 if (! (obj instanceof HttpRequest)) 568 return false; 569 HttpRequest that = (HttpRequest)obj; 570 if (!that.method().equals(this.method())) 571 return false; 572 if (!that.uri().equals(this.uri())) 573 return false; 574 if (!that.headers().equals(this.headers())) 575 return false; 576 return true; 577 } 578 579 /** 580 * Computes a hash code for this HTTP request instance. 581 * 582 * <p> The hash code is based upon the HTTP request's URI, method, and 583 * header components, and satisfies the general contract of the 584 * {@link Object#hashCode Object.hashCode} method. 585 * 586 * @return the hash-code value for this HTTP request 587 */ 588 public final int hashCode() { 589 return method().hashCode() 590 + uri().hashCode() 591 + headers().hashCode(); 592 } 593 594 /** 595 * A Publisher which converts high level Java objects into flows of 596 * byte buffers suitable for sending as request bodies. 597 * {@Incubating} 598 * 599 * <p> The {@code BodyPublisher} class implements {@link Flow.Publisher 600 * Flow.Publisher<ByteBuffer>} which means that a {@code BodyPublisher} 601 * acts as a publisher of {@linkplain ByteBuffer byte buffers}. 602 * 603 * <p> The HTTP client implementation subscribes to the publisher in order 604 * to receive the flow of outgoing data buffers. The normal semantics of 605 * {@link Flow.Subscriber} and {@link Flow.Publisher} are implemented by the 606 * library and are expected from publisher implementations. Each outgoing 607 * request results in one {@code Subscriber} subscribing to the {@code 608 * BodyPublisher} in order to provide the sequence of byte buffers 609 * containing the request body. 610 * Instances of {@code ByteBuffer} published by the publisher must be 611 * allocated by the publisher, and must not be accessed after being handed 612 * over to the library. 613 * These subscriptions complete normally when the request is fully sent, 614 * and can be canceled or terminated early through error. If a request 615 * needs to be resent for any reason, then a new subscription is created 616 * which is expected to generate the same data as before. 617 * 618 * <p> A publisher that reports a {@linkplain #contentLength() content 619 * length} of {@code 0} may not be subscribed to by the HTTP client 620 * implementation, as it has effectively no data to publish. 621 */ 622 public interface BodyPublisher extends Flow.Publisher<ByteBuffer> { 623 624 /** 625 * Returns a request body publisher whose body is the given {@code 626 * String}, converted using the {@link StandardCharsets#UTF_8 UTF_8} 627 * character set. 628 * 629 * @param body the String containing the body 630 * @return a BodyPublisher 631 */ 632 static BodyPublisher fromString(String body) { 633 return fromString(body, UTF_8); 634 } 635 636 /** 637 * Returns a request body publisher whose body is the given {@code 638 * String}, converted using the given character set. 639 * 640 * @param s the String containing the body 641 * @param charset the character set to convert the string to bytes 642 * @return a BodyPublisher 643 */ 644 static BodyPublisher fromString(String s, Charset charset) { 645 return new RequestPublishers.StringPublisher(s, charset); 646 } 647 648 /** 649 * A request body publisher that reads its data from an {@link 650 * InputStream}. A {@link Supplier} of {@code InputStream} is used in 651 * case the request needs to be repeated, as the content is not buffered. 652 * The {@code Supplier} may return {@code null} on subsequent attempts, 653 * in which case the request fails. 654 * 655 * @param streamSupplier a Supplier of open InputStreams 656 * @return a BodyPublisher 657 */ 658 // TODO (spec): specify that the stream will be closed 659 static BodyPublisher fromInputStream(Supplier<? extends InputStream> streamSupplier) { 660 return new RequestPublishers.InputStreamPublisher(streamSupplier); 661 } 662 663 /** 664 * Returns a request body publisher whose body is the given byte array. 665 * 666 * @param buf the byte array containing the body 667 * @return a BodyPublisher 668 */ 669 static BodyPublisher fromByteArray(byte[] buf) { 670 return new RequestPublishers.ByteArrayPublisher(buf); 671 } 672 673 /** 674 * Returns a request body publisher whose body is the content of the 675 * given byte array of {@code length} bytes starting from the specified 676 * {@code offset}. 677 * 678 * @param buf the byte array containing the body 679 * @param offset the offset of the first byte 680 * @param length the number of bytes to use 681 * @return a BodyPublisher 682 * @throws IndexOutOfBoundsException if the sub-range is defined to be 683 * out-of-bounds 684 */ 685 static BodyPublisher fromByteArray(byte[] buf, int offset, int length) { 686 Objects.checkFromIndexSize(offset, length, buf.length); 687 return new RequestPublishers.ByteArrayPublisher(buf, offset, length); 688 } 689 690 private static String pathForSecurityCheck(Path path) { 691 return path.toFile().getPath(); 692 } 693 694 /** 695 * A request body publisher that takes data from the contents of a File. 696 * 697 * @param path the path to the file containing the body 698 * @return a BodyPublisher 699 * @throws java.io.FileNotFoundException if the path is not found 700 * @throws SecurityException if a security manager has been installed 701 * and it denies {@link SecurityManager#checkRead(String) 702 * read access} to the given file 703 */ 704 static BodyPublisher fromFile(Path path) throws FileNotFoundException { 705 Objects.requireNonNull(path); 706 SecurityManager sm = System.getSecurityManager(); 707 if (sm != null) 708 sm.checkRead(pathForSecurityCheck(path)); 709 if (Files.notExists(path)) 710 throw new FileNotFoundException(path + " not found"); 711 return new RequestPublishers.FilePublisher(path); 712 } 713 714 /** 715 * A request body publisher that takes data from an {@code Iterable} 716 * of byte arrays. An {@link Iterable} is provided which supplies 717 * {@link Iterator} instances. Each attempt to send the request results 718 * in one invocation of the {@code Iterable}. 719 * 720 * @param iter an Iterable of byte arrays 721 * @return a BodyPublisher 722 */ 723 static BodyPublisher fromByteArrays(Iterable<byte[]> iter) { 724 return new RequestPublishers.IterablePublisher(iter); 725 } 726 727 /** 728 * A request body publisher which sends no request body. 729 * 730 * @return a BodyPublisher which completes immediately and sends 731 * no request body. 732 */ 733 static BodyPublisher noBody() { 734 return new RequestPublishers.EmptyPublisher(); 735 } 736 737 /** 738 * Returns the content length for this request body. May be zero 739 * if no request body being sent, greater than zero for a fixed 740 * length content, or less than zero for an unknown content length. 741 * 742 * This method may be invoked before the publisher is subscribed to. 743 * This method may be invoked more than once by the HTTP client 744 * implementation, and MUST return the same constant value each time. 745 * 746 * @return the content length for this request body, if known 747 */ 748 long contentLength(); 749 } 750 }