12

I am trying to experiment with Java 9's HttpClient.

The basic example as in HttpRequest's javadoc works without problems:

HttpResponse response = HttpRequest.create(new URI("http://stackoverflow.com/"))
       .version(java.net.http.HttpClient.Version.HTTP_2)
       .followRedirects(HttpClient.Redirect.ALWAYS)
       .GET()
       .response();

       int statusCode = response.statusCode();
       String responseBody = response.body(HttpResponse.asString());

       System.out.println("statusCode = " + statusCode);
       System.out.println("responseBody = " + responseBody);

However, when trying to use sendAsyncMulti, it does not work. No files are created in E:\foo, the println after join is not reached, there is also no exception, although I basically copied the example from HttpResponse.multiFile's Javadoc. I expected that some HTTP responses will be saved in that directory. I also tried to remove the HTTP2 and followRedirects, other URLs like google etc, but it did not change anything. What am I doing wrong?

CompletableFuture<Map<URI,Path>> cf =
    HttpRequest.create(new URI("http://stackoverflow.com/"))
        .version(java.net.http.HttpClient.Version.HTTP_2)
        .followRedirects(HttpClient.Redirect.ALWAYS)
        .GET()
        .multiResponseAsync(HttpResponse.multiFile(Paths.get("E:\\foo")));
Map<URI,Path> results = cf.join();
System.out.println("after join");

If it is relevant, this is the version I am using (latest version of JDK 9):

java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+126)
Java HotSpot(TM) Server VM (build 9-ea+126, mixed mode)
Krzysztof Krasoń
  • 26,515
  • 16
  • 89
  • 115
user140547
  • 7,750
  • 3
  • 28
  • 80

1 Answers1

4

The method sendAsyncMulti makes use of an HTTP2-feature named server push.

Most http2 clients, i.e. modern browsers and also the implementation in jdk9, only use the new features if the host is contacted via https.

Most http2-servers will only send push promises, if the initial client request was an http2 request.

The following snippet works with java 9 build 9-ea-153:

URI uri = new URI("https://blog.cloudflare.com/announcing-support-for-http-2-server-push-2/");
HttpRequest request = ExampleUtils.createHttpRequest(uri);
HttpClient client = ExampleUtils.createHttpClient();

MultiMapResult<String> multiMapResult = client.sendAsync(request, MultiProcessor.asMap((req) -> {
            Optional<BodyHandler<String>> optional = Optional.of(HttpResponse.BodyHandler.asString());
            if (optional.isPresent()) {
                System.out.println(" - " + req.uri());
            }
            return optional;
        }, false))

        .orTimeout(2, TimeUnit.SECONDS)
        .join();

The full working example can be found at github: https://github.com/janweinschenker/jdk9-jigsaw-http2

The snippet is taken from https://github.com/janweinschenker/jdk9-jigsaw-http2/blob/master/src/main/java/de/holisticon/jdk9showcase/http2client/ResponseAsyncMultiExample.java

Erunafailaro
  • 1,835
  • 16
  • 21
  • 1
    +1 for making the connection to push promises and the github links. However, a better test URL for the example would be https://http2-push.io/ That's a HTTP/2 push test site that (currently) gives me *3* entries in the `MultiMapResult`: the html, a .css and a .js resource. – Stefan Zobel Mar 30 '18 at 00:55