Class HttpRequest


  • public abstract class HttpRequest
    extends Object
    Represents one HTTP request which can be sent to a server.
    Incubating Feature. Will be removed in a future release.

    HttpRequest instances are built from HttpRequest builders. HttpRequest builders are obtained by calling HttpRequest.newBuilder. A request's URI, headers and body can be set. Request bodies are provided through a HttpRequest.BodyPublisher object supplied to the DELETE, POST or PUT methods. GET does not take a body. Once all required parameters have been set in the builder, HttpRequest.Builder.build() is called to return the HttpRequest. Builders can also be copied and modified multiple times in order to build multiple related requests that differ in some parameters.

    Two simple, example HTTP interactions are shown below:

     
          HttpClient client = HttpClient.newHttpClient();
    
          // GET
          HttpResponse<String> response = client.send(
              HttpRequest
                  .newBuilder(new URI("http://www.foo.com/"))
                  .headers("Foo", "foovalue", "Bar", "barvalue")
                  .GET()
                  .build(),
              BodyHandler.asString()
          );
          int statusCode = response.statusCode();
          String body = response.body();
    
          // POST
          HttpResponse<Path> response = client.send(
              HttpRequest
                  .newBuilder(new URI("http://www.foo.com/"))
                  .headers("Foo", "foovalue", "Bar", "barvalue")
                  .POST(BodyPublisher.fromString("Hello world"))
                  .build(),
              BodyHandler.asFile(Paths.get("/path"))
          );
          int statusCode = response.statusCode();
          Path body = response.body(); // should be "/path"
     
     

    The request is sent and the response obtained by calling one of the following methods in HttpClient.

    Once a HttpResponse is received, the headers, response code and body (typically) are available. Whether the body has been read or not depends on the type <T> of the response body. See below.

    See below for discussion of synchronous versus asynchronous usage.

    Request bodies

    Request bodies can be sent using one of the convenience request publisher implementations below, provided in HttpRequest.BodyPublisher. Alternatively, a custom Publisher implementation can be used.

    Response bodies

    Responses bodies are handled at two levels. When sending the request, a response body handler is specified. This is a function (HttpResponse.BodyHandler) which will be called with the response status code and headers, once they are received. This function is then expected to return a HttpResponse.BodySubscriber<T> which is then used to read the response body, converting it into an instance of T. After this occurs, the response becomes available in a HttpResponse, and HttpResponse.body() can then be called to obtain the actual body. Some implementations and examples of usage of both HttpResponse.BodySubscriber and HttpResponse.BodyHandler are provided in HttpResponse:

    Some of the pre-defined body handlers

    Multi responses

    With HTTP/2 it is possible for a server to return a main response and zero or more additional responses (known as server pushes) to a client-initiated request. These are handled using a special response subscriber called HttpResponse.MultiSubscriber.

    Blocking/asynchronous behavior and thread usage

    There are two styles of request sending: synchronous and asynchronous. HttpClient.send(HttpRequest, HttpResponse.BodyHandler) blocks the calling thread until the request has been sent and the response received.

    HttpClient.sendAsync(HttpRequest, HttpResponse.BodyHandler) is asynchronous and returns immediately with a CompletableFuture<HttpResponse> and when this object completes (possibly in a different thread) the response has been received.

    HttpClient.sendAsync(HttpRequest, HttpResponse.MultiSubscriber) is the variant for multi responses and is also asynchronous.

    Instances of CompletableFuture can be combined in different ways to declare the dependencies among several asynchronous tasks, while allowing for the maximum level of parallelism to be utilized.

    Security checks

    If a security manager is present then security checks are performed by the HTTP Client's sending methods. An appropriate URLPermission is required to access the destination server, and proxy server if one has been configured. The URLPermission form used to access proxies uses a method parameter of "CONNECT" (for all kinds of proxying) and a URL string of the form "socket://host:port" where host and port specify the proxy's address.

    In this implementation, if an explicit executor has not been set for an HttpClient, and a security manager has been installed, then the default executor will execute asynchronous and dependent tasks in a context that is granted no permissions. Custom request body publishers, response body handlers, response body subscribers, and WebSocket Listeners, if executing operations that require privileges, should do so within an appropriate privileged context.

    Examples

    
          HttpClient client = HttpClient
                  .newBuilder()
                  .build();
    
          HttpRequest request = HttpRequest
                  .newBuilder(new URI("http://www.foo.com/"))
                  .POST(BodyPublisher.fromString("Hello world"))
                  .build();
    
          HttpResponse<Path> response =
              client.send(request, BodyHandler.asFile(Paths.get("/path")));
    
          Path body = response.body();
     

    Asynchronous Example

    The above example will work asynchronously, if (HttpRequest, HttpResponse.BodyHandler) sendAsync is used instead of send in which case the returned object is a CompletableFuture<HttpResponse> instead of HttpResponse. The following example shows how multiple requests can be sent asynchronously. It also shows how dependent asynchronous operations (receiving response, and receiving response body) can be chained easily using one of the many methods in CompletableFuture.

     
      // fetch a list of target URIs asynchronously and store them in Files.
    
          List<URI> targets = ...
    
          List<CompletableFuture<File>> futures = targets
              .stream()
              .map(target -> client
                      .sendAsync(
                          HttpRequest.newBuilder(target)
                                     .GET()
                                     .build(),
                          BodyHandler.asFile(Paths.get("base", target.getPath())))
                      .thenApply(response -> response.body())
                      .thenApply(path -> path.toFile()))
              .collect(Collectors.toList());
    
          // all async operations waited for here
    
          CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0]))
              .join();
    
          // all elements of futures have completed and can be examined.
          // Use File.exists() to check whether file was successfully downloaded
     
     

    Unless otherwise stated, null parameter values will cause methods of this class to throw NullPointerException.

    Since:
    9
    • Constructor Detail

      • HttpRequest

        protected HttpRequest()
        Creates an HttpRequest.
    • Method Detail

      • newBuilder

        public static HttpRequest.Builder newBuilder​(URI uri)
        Creates a HttpRequest builder.
        Parameters:
        uri - the request URI
        Returns:
        a new request builder
        Throws:
        IllegalArgumentException - if the URI scheme is not supported.
      • newBuilder

        public static HttpRequest.Builder newBuilder()
        Creates a HttpRequest builder.
        Returns:
        a new request builder
      • bodyPublisher

        public abstract Optional<HttpRequest.BodyPublisher> bodyPublisher()
        Returns an Optional containing the HttpRequest.BodyPublisher set on this request. If no BodyPublisher was set in the requests's builder, then the Optional is empty.
        Returns:
        an Optional containing this request's BodyPublisher
      • method

        public abstract String method()
        Returns the request method for this request. If not set explicitly, the default method for any request is "GET".
        Returns:
        this request's method
      • timeout

        public abstract Optional<Duration> timeout()
        Returns an Optional containing this request's timeout duration. If the timeout duration was not set in the request's builder, then the Optional is empty.
        Returns:
        an Optional containing this request's timeout duration
      • expectContinue

        public abstract boolean expectContinue()
        Returns this request's expect continue setting.
        Returns:
        this request's expect continue setting
      • uri

        public abstract URI uri()
        Returns this request's request URI.
        Returns:
        this request's URI
      • version

        public abstract Optional<HttpClient.Version> version()
        Returns an Optional containing the HTTP protocol version that will be requested for this HttpRequest. If the version was not set in the request's builder, then the Optional is empty. In that case, the version requested will be that of the sending HttpClient. The corresponding HttpResponse should be queried to determine the version that was actually used.
        Returns:
        HTTP protocol version
      • headers

        public abstract HttpHeaders headers()
        The (user-accessible) request headers that this request was (or will be) sent with.
        Returns:
        this request's HttpHeaders
      • equals

        public final boolean equals​(Object obj)
        Tests this HTTP request instance for equality with the given object.

        If the given object is not an HttpRequest then this method returns false. Two HTTP requests are equal if their URI, method, and headers fields are all equal.

        This method satisfies the general contract of the Object.equals method.

        Overrides:
        equals in class Object
        Parameters:
        obj - the object to which this object is to be compared
        Returns:
        true if, and only if, the given object is an HttpRequest that is equal to this HTTP request
        See Also:
        Object.hashCode(), HashMap