+ * It is recommended to create a new instance instead. + *+ * AsyncHandler ah = new AsyncHandler() {....}; + * AsyncHttpClient client = new AsyncHttpClient(); + * client.prepareGet("http://.../").execute(ah); + * client.prepareGet("http://.../").execute(ah); + *
+ * Do NOT perform any blocking operations in any of these methods. A typical example would be trying to send another
+ * request and calling get() on its future.
+ * There's a chance you might end up in a deadlock.
+ * If you really need to perform a blocking operation, execute it in a different dedicated thread pool.
+ *
+ * @param
+ * Might be called several times if the name was resolved to multiple addresses, and we failed to connect to the first(s) one(s).
+ *
+ * @param remoteAddress the address we try to connect to
+ */
+ default void onTcpConnectAttempt(InetSocketAddress remoteAddress) {
+ }
+
+ /**
+ * Notify the callback after a successful connect
+ *
+ * @param remoteAddress the address we try to connect to
+ * @param connection the connection
+ */
+ default void onTcpConnectSuccess(InetSocketAddress remoteAddress, Channel connection) {
+ }
+
+ /**
+ * Notify the callback after a failed connect.
+ *
+ * Might be called several times, or be followed by onTcpConnectSuccess when the name was resolved to multiple addresses.
+ *
+ * @param remoteAddress the address we try to connect to
+ * @param cause the cause of the failure
+ */
+ default void onTcpConnectFailure(InetSocketAddress remoteAddress, Throwable cause) {
+ }
+
+ // ////////////// TLS ///////////////
+
+ /**
+ * Notify the callback before TLS handshake
+ */
+ default void onTlsHandshakeAttempt() {
+ }
+
+ /**
+ * Notify the callback after the TLS was successful
+ */
+ default void onTlsHandshakeSuccess(SSLSession sslSession) {
+ }
+
+ /**
+ * Notify the callback after the TLS failed
+ *
+ * @param cause the cause of the failure
+ */
+ default void onTlsHandshakeFailure(Throwable cause) {
+ }
+
+ // /////////// POOLING /////////////
+
+ /**
+ * Notify the callback when trying to fetch a connection from the pool.
+ */
+ default void onConnectionPoolAttempt() {
+ }
+
+ /**
+ * Notify the callback when a new connection was successfully fetched from the pool.
+ *
+ * @param connection the connection
+ */
+ default void onConnectionPooled(Channel connection) {
+ }
+
+ /**
+ * Notify the callback when trying to offer a connection to the pool.
+ *
+ * @param connection the connection
+ */
+ default void onConnectionOffer(Channel connection) {
+ }
+
+ // //////////// SENDING //////////////
+
+ /**
+ * Notify the callback when a request is being written on the channel. If the original request causes multiple requests to be sent, for example, because of authorization or
+ * retry, it will be notified multiple times.
+ *
+ * @param request the real request object as passed to the provider
+ */
+ default void onRequestSend(NettyRequest request) {
+ }
+
+ /**
+ * Notify the callback every time a request is being retried.
+ */
+ default void onRetry() {
+ }
+
+ enum State {
+
+ /**
+ * Stop the processing.
+ */
+ ABORT,
+ /**
+ * Continue the processing
+ */
+ CONTINUE
+ }
+}
diff --git a/client/src/main/java/org/asynchttpclient/AsyncHttpClient.java b/client/src/main/java/org/asynchttpclient/AsyncHttpClient.java
new file mode 100755
index 0000000000..01a3ecf734
--- /dev/null
+++ b/client/src/main/java/org/asynchttpclient/AsyncHttpClient.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2010 Ning, Inc.
+ *
+ * This program is licensed to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.asynchttpclient;
+
+import java.io.Closeable;
+import java.util.concurrent.Future;
+import java.util.function.Predicate;
+
+/**
+ * This class support asynchronous and synchronous HTTP requests.
+ *
+ * This class can also be used without the need of {@link AsyncHandler}.
+ *
+ * Finally, you can configure the AsyncHttpClient using an {@link DefaultAsyncHttpClientConfig} instance.
+ *
+ * Gets always invoked as last callback method.
+ *
+ * @return T Value that will be returned by the associated {@link Future}
+ * @throws Exception if something wrong happens
+ */
+ @Nullable
+ T onCompleted() throws Exception;
+
+ /**
+ * Notify the callback before hostname resolution
+ *
+ * @param name the name to be resolved
+ */
+ default void onHostnameResolutionAttempt(String name) {
+ }
+
+ // ////////// DNS /////////////////
+
+ /**
+ * Notify the callback after hostname resolution was successful.
+ *
+ * @param name the name to be resolved
+ * @param addresses the resolved addresses
+ */
+ default void onHostnameResolutionSuccess(String name, List
+ * To execute a synchronous HTTP request, you just need to do
+ *
+ *
+ * AsyncHttpClient c = new AsyncHttpClient();
+ * Future<Response> f = c.prepareGet(TARGET_URL).execute();
+ *
+ * The code above will block until the response is fully received. To execute an asynchronous HTTP request, you
+ * create an {@link AsyncHandler} or its abstract implementation, {@link AsyncCompletionHandler}
+ *
+ *
+ * The {@link AsyncCompletionHandler#onCompleted(Response)} method will be invoked once the http response has been fully read.
+ * The {@link Response} object includes the http headers and the response body. Note that the entire response will be buffered in memory.
+ *
+ * AsyncHttpClient c = new AsyncHttpClient();
+ * Future<Response> f = c.prepareGet(TARGET_URL).execute(new AsyncCompletionHandler<Response>() {
+ *
+ * @Override
+ * public Response onCompleted(Response response) throws IOException {
+ * // Do something
+ * return response;
+ * }
+ *
+ * @Override
+ * public void onThrowable(Throwable t) {
+ * }
+ * });
+ * Response response = f.get();
+ *
+ * // We are just interested in retrieving the status code.
+ * Future<Integer> f = c.prepareGet(TARGET_URL).execute(new AsyncCompletionHandler<Integer>() {
+ *
+ * @Override
+ * public Integer onCompleted(Response response) throws IOException {
+ * // Do something
+ * return response.getStatusCode();
+ * }
+ *
+ * @Override
+ * public void onThrowable(Throwable t) {
+ * }
+ * });
+ * Integer statusCode = f.get();
+ *
+ * You can also have more control about how the response is asynchronously processed by using an {@link AsyncHandler}
+ *
+ * You can asynchronously process the response status, headers and body and decide when to
+ * stop processing the response by returning a new {@link AsyncHandler.State#ABORT} at any moment.
+ *
+ * AsyncHttpClient c = new AsyncHttpClient();
+ * Future<String> f = c.prepareGet(TARGET_URL).execute(new AsyncHandler<String>() {
+ * private StringBuilder builder = new StringBuilder();
+ *
+ * @Override
+ * public STATE onStatusReceived(HttpResponseStatus s) throws Exception {
+ * // return STATE.CONTINUE or STATE.ABORT
+ * return STATE.CONTINUE
+ * }
+ *
+ * @Override
+ * public STATE onHeadersReceived(HttpResponseHeaders bodyPart) throws Exception {
+ * // return STATE.CONTINUE or STATE.ABORT
+ * return STATE.CONTINUE
+ *
+ * }
+ * @Override
+ *
+ * public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
+ * builder.append(new String(bodyPart));
+ * // return STATE.CONTINUE or STATE.ABORT
+ * return STATE.CONTINUE
+ * }
+ *
+ * @Override
+ * public String onCompleted() throws Exception {
+ * // Will be invoked once the response has been fully read or a ResponseComplete exception
+ * // has been thrown.
+ * return builder.toString();
+ * }
+ *
+ * @Override
+ * public void onThrowable(Throwable t) {
+ * }
+ * });
+ *
+ * String bodyResponse = f.get();
+ *
+ *
+ *
+ * AsyncHttpClient c = new AsyncHttpClient();
+ * Future<Response> f = c.prepareGet(TARGET_URL).execute();
+ * Response r = f.get();
+ *
+ *
+ *
+ * AsyncHttpClient c = new AsyncHttpClient(new DefaultAsyncHttpClientConfig.Builder().setRequestTimeout(...).build());
+ * Future<Response> f = c.prepareGet(TARGET_URL).execute();
+ * Response r = f.get();
+ *
+ * An instance of this class will cache every HTTP 1.1 connection and close them when the {@link DefaultAsyncHttpClientConfig#getReadTimeout()}
+ * expires. This object can hold many persistent connections to different hosts.
+ */
+public interface AsyncHttpClient extends Closeable {
+
+ /**
+ * Return true if closed
+ *
+ * @return true if closed
+ */
+ boolean isClosed();
+
+ /**
+ * Set default signature calculator to use for requests built by this client instance
+ *
+ * @param signatureCalculator a signature calculator
+ * @return {@link RequestBuilder}
+ */
+ AsyncHttpClient setSignatureCalculator(SignatureCalculator signatureCalculator);
+
+ /**
+ * Prepare an HTTP client request.
+ *
+ * @param method HTTP request method type. MUST BE in upper case
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder prepare(String method, String url);
+
+
+ /**
+ * Prepare an HTTP client GET request.
+ *
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder prepareGet(String url);
+
+ /**
+ * Prepare an HTTP client CONNECT request.
+ *
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder prepareConnect(String url);
+
+ /**
+ * Prepare an HTTP client OPTIONS request.
+ *
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder prepareOptions(String url);
+
+ /**
+ * Prepare an HTTP client HEAD request.
+ *
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder prepareHead(String url);
+
+ /**
+ * Prepare an HTTP client POST request.
+ *
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder preparePost(String url);
+
+ /**
+ * Prepare an HTTP client PUT request.
+ *
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder preparePut(String url);
+
+ /**
+ * Prepare an HTTP client DELETE request.
+ *
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder prepareDelete(String url);
+
+ /**
+ * Prepare an HTTP client PATCH request.
+ *
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder preparePatch(String url);
+
+ /**
+ * Prepare an HTTP client TRACE request.
+ *
+ * @param url A well-formed URL.
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder prepareTrace(String url);
+
+ /**
+ * Construct a {@link RequestBuilder} using a {@link Request}
+ *
+ * @param request a {@link Request}
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder prepareRequest(Request request);
+
+ /**
+ * Construct a {@link RequestBuilder} using a {@link RequestBuilder}
+ *
+ * @param requestBuilder a {@link RequestBuilder}
+ * @return {@link RequestBuilder}
+ */
+ BoundRequestBuilder prepareRequest(RequestBuilder requestBuilder);
+
+ /**
+ * Execute an HTTP request.
+ *
+ * @param request {@link Request}
+ * @param handler an instance of {@link AsyncHandler}
+ * @param