Thursday, October 7, 2010

Async HTTP Client 1.2.0

Async HTTP Client 1.2.0

Intro

About month ago we released async-http-client 1.1.0.
During this month we received lots of contributions and user feedback.
We took all of this great feedback into consideration,
and here it is: lots of bug fixes and new features in async-http-client are ready to be released.
You can get it from Maven Central near you.

Highlights

To cut the long story short here are highlights of few new features.
  • JDK based provider

    This release support a new AsyncHttpProvider based on JDK's URLConnection.
    This provider can be used in environments that aren't supporting NIO.
    AsyncHttpClient client = new AsyncHttpClient(new JDKAsyncHttpProvider(config));
  • Authentication

    The library now support 3 authentication scheme: Basic, Digest and NTLM.
    RequestBuilder r = client.prepareGet(url)
    .setRealm((new Realm.RealmBuilder())
    .setScheme(AuthScheme)
    .setPrincipal(user)
    .setPassword(admin)
    .setUsePreemptiveAuth(true).build());
    AuthScheme can be BASIC, DIGEST or NTLM.
  • SSL Tunneling support

    This release also adds support for SSL Tunneling.
    AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder();
    b.setFollowRedirects(true);

    ProxyServer ps = new ProxyServer(ProxyServer.Protocol.HTTPS, "127.0.0.1", port1);
    b.setProxyServer(ps);

    AsyncHttpClientConfig config = b.build();
    AsyncHttpClient asyncHttpClient = new AsyncHttpClient(config);

    RequestBuilder rb = new RequestBuilder("GET").setUrl(url);
    Future<Response> responseFuture = asyncHttpClient.executeRequest(rb.build(), new AsyncCompletionHandlerBase() {

    public void onThrowable(Throwable t) {
    log.debug(t);
    }

    @Override
    public Response onCompleted(Response response) throws Exception {
    return response;
    }
    });
  • WebDav

    WebDav is now supported and can be used with two interfaces.
    • Low level
      AsyncHttpClient c = new AsyncHttpClient();

      Request mkcolRequest = new RequestBuilder("MKCOL").setUrl("http://127.0.0.1:8080/folder1").build();
      Response response = c.executeRequest(mkcolRequest).get();

      Request putRequest = new RequestBuilder("PUT").setUrl("http://127.0.0.1:8080/folder1/Test.txt").setBody("this is a test").build();
      response = c.executeRequest(putRequest).get();

      Request propFindRequest = new RequestBuilder("PROPFIND").setUrl("http://127.0.0.1:8080/folder1/Test.txt").build();
      response = c.executeRequest(propFindRequest).get();

      // Check the response.
      response.getStatusCode(); //Will return 207
      response.getResponseBody().contains("<status>HTTP/1.1 200 OK</status>"));
    • High level

      You can also use a special AsyncHandler which construct a response
      based on the webdav response's code.
      AsyncHttpClient c = new AsyncHttpClient();

      Request mkcolRequest = new RequestBuilder("MKCOL").setUrl("http://127.0.0.1:8080/folder1").build();
      Response response = c.executeRequest(mkcolRequest).get();
      assertEquals(response.getStatusCode(), 201);

      Request propFindRequest = new RequestBuilder("PROPFIND").setUrl("http://127.0.0.1:8080/folder1/").build();
      WebDavResponse webDavResponse = c.executeRequest(propFindRequest, new WebDavCompletionHandlerBase<WebDavResponse>() {

      @Override
      public WebDavResponse onCompleted(WebDavResponse response) throws Exception {
      return response;
      }
      }).get();

      webDavResponse.getStatusCode(); // will return 200.
  • Zero copy

    Sometimes you need to just download some content, with out
    copying/inspecting the bytes in memory, just download and store.
    File file = new File(url.toURI());

    File tmp = new File(System.getProperty("java.io.tmpdir") + File.separator + "zeroCopy.txt");
    final FileOutputStream stream = new FileOutputStream(tmp);
    // Upload a file using setBody(File);
    Future<Response> f = client.preparePost("http://127.0.0.1:" + port1 + "/").setBody(file).execute(new AsyncHandler<Response>() {
    public void onThrowable(Throwable t) {}

    public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
    bodyPart.writeTo(stream);
    // Copy the bytes directly to a File. In our case it is an FileInputStream
    return STATE.CONTINUE;
    }

    public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
    return STATE.CONTINUE;
    }

    public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
    return STATE.CONTINUE;
    }

    public Response onCompleted() throws Exception {
    return null;
    }
    });

    Response resp = f.get();
    stream.close();
  • Automatic HTTPS redirects

    Another new feature is we do support redirect from http to HTTPS automatically:
    AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build();
    AsyncHttpClient c = new AsyncHttpClient(cg);

    Response response = c.preparePost(url).execute().get();
    If the server redirect us to https, we will follow the new url
    without any issue.

Changelog