
org.asynchttpclient.DefaultAsyncHttpClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of async-http-client-api Show documentation
Show all versions of async-http-client-api Show documentation
The Async Http Client (AHC) API classes.
The newest version!
/*
* Copyright 2010 Ning, Inc.
*
* Ning licenses this file 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.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import org.asynchttpclient.filter.FilterContext;
import org.asynchttpclient.filter.FilterException;
import org.asynchttpclient.filter.RequestFilter;
import org.asynchttpclient.handler.resumable.ResumableAsyncHandler;
import org.asynchttpclient.netty.NettyAsyncHttpProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DefaultAsyncHttpClient implements AsyncHttpClient {
private final AsyncHttpProvider httpProvider;
private final AsyncHttpClientConfig config;
private final static Logger logger = LoggerFactory.getLogger(DefaultAsyncHttpClient.class);
private final AtomicBoolean isClosed = new AtomicBoolean(false);
/**
* Default signature calculator to use for all requests constructed by this client instance.
*
* @since 1.1
*/
protected SignatureCalculator signatureCalculator;
/**
* Create a new HTTP Asynchronous Client using the default {@link AsyncHttpClientConfig} configuration. The
* default {@link AsyncHttpProvider} that will be used will be based on the classpath configuration.
*
* If none of those providers are found, then the engine will throw an IllegalStateException.
*/
public DefaultAsyncHttpClient() {
this(new AsyncHttpClientConfig.Builder().build());
}
/**
* Create a new HTTP Asynchronous Client using an implementation of {@link AsyncHttpProvider} and
* the default {@link AsyncHttpClientConfig} configuration.
*
* @param provider a {@link AsyncHttpProvider}
*/
public DefaultAsyncHttpClient(AsyncHttpProvider provider) {
this(provider, new AsyncHttpClientConfig.Builder().build());
}
/**
* Create a new HTTP Asynchronous Client using the specified {@link AsyncHttpClientConfig} configuration.
* This configuration will be passed to the default {@link AsyncHttpProvider} that will be selected based on
* the classpath configuration.
*
* @param config a {@link AsyncHttpClientConfig}
*/
public DefaultAsyncHttpClient(AsyncHttpClientConfig config) {
this(new NettyAsyncHttpProvider(config), config);
}
/**
* Create a new HTTP Asynchronous Client using a {@link AsyncHttpClientConfig} configuration and
* and a {@link AsyncHttpProvider}.
*
* @param config a {@link AsyncHttpClientConfig}
* @param httpProvider a {@link AsyncHttpProvider}
*/
public DefaultAsyncHttpClient(AsyncHttpProvider httpProvider, AsyncHttpClientConfig config) {
this.config = config;
this.httpProvider = httpProvider;
}
@Override
public AsyncHttpProvider getProvider() {
return httpProvider;
}
@Override
public void close() {
if (isClosed.compareAndSet(false, true))
httpProvider.close();
}
@Override
public void closeAsynchronously() {
final ExecutorService e = Executors.newSingleThreadExecutor();
e.submit(new Runnable() {
public void run() {
try {
close();
} catch (Throwable t) {
logger.warn("", t);
} finally {
e.shutdown();
}
}
});
}
@Override
protected void finalize() throws Throwable {
try {
if (!isClosed.get()) {
logger.error("AsyncHttpClient.close() hasn't been invoked, which may produce file descriptor leaks");
}
} finally {
super.finalize();
}
}
@Override
public boolean isClosed() {
return isClosed.get();
}
@Override
public AsyncHttpClientConfig getConfig() {
return config;
}
@Override
public DefaultAsyncHttpClient setSignatureCalculator(SignatureCalculator signatureCalculator) {
this.signatureCalculator = signatureCalculator;
return this;
}
@Override
public BoundRequestBuilder prepareGet(String url) {
return requestBuilder("GET", url);
}
@Override
public BoundRequestBuilder prepareConnect(String url) {
return requestBuilder("CONNECT", url);
}
@Override
public BoundRequestBuilder prepareOptions(String url) {
return requestBuilder("OPTIONS", url);
}
@Override
public BoundRequestBuilder prepareHead(String url) {
return requestBuilder("HEAD", url);
}
@Override
public BoundRequestBuilder preparePost(String url) {
return requestBuilder("POST", url);
}
@Override
public BoundRequestBuilder preparePut(String url) {
return requestBuilder("PUT", url);
}
@Override
public BoundRequestBuilder prepareDelete(String url) {
return requestBuilder("DELETE", url);
}
@Override
public BoundRequestBuilder preparePatch(String url) {
return requestBuilder("PATCH", url);
}
@Override
public BoundRequestBuilder prepareTrace(String url) {
return requestBuilder("TRACE", url);
}
@Override
public BoundRequestBuilder prepareRequest(Request request) {
return requestBuilder(request);
}
@Override
public ListenableFuture executeRequest(Request request, AsyncHandler handler) {
if (config.getRequestFilters().isEmpty()) {
return httpProvider.execute(request, handler);
} else {
FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(handler).request(request).build();
try {
fc = preProcessRequest(fc);
} catch (Exception e) {
handler.onThrowable(e);
return new ListenableFuture.CompletedFailure<>("preProcessRequest failed", e);
}
return httpProvider.execute(fc.getRequest(), fc.getAsyncHandler());
}
}
@Override
public ListenableFuture executeRequest(Request request) {
return executeRequest(request, new AsyncCompletionHandlerBase());
}
/**
* Configure and execute the associated {@link RequestFilter}. This class may decorate the {@link Request} and {@link AsyncHandler}
*
* @param fc {@link FilterContext}
* @return {@link FilterContext}
*/
private FilterContext preProcessRequest(FilterContext fc) throws FilterException {
for (RequestFilter asyncFilter : config.getRequestFilters()) {
fc = asyncFilter.filter(fc);
if (fc == null) {
throw new NullPointerException("FilterContext is null");
}
}
Request request = fc.getRequest();
if (fc.getAsyncHandler() instanceof ResumableAsyncHandler) {
request = ResumableAsyncHandler.class.cast(fc.getAsyncHandler()).adjustRequestRange(request);
}
if (request.getRangeOffset() != 0) {
RequestBuilder builder = new RequestBuilder(request);
builder.setHeader("Range", "bytes=" + request.getRangeOffset() + "-");
request = builder.build();
}
fc = new FilterContext.FilterContextBuilder<>(fc).request(request).build();
return fc;
}
protected BoundRequestBuilder requestBuilder(String method, String url) {
return new BoundRequestBuilder(this, method, config.isDisableUrlEncodingForBoundRequests()).setUrl(url).setSignatureCalculator(signatureCalculator);
}
protected BoundRequestBuilder requestBuilder(Request prototype) {
return new BoundRequestBuilder(this, prototype).setSignatureCalculator(signatureCalculator);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy