All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.sphere.sdk.http.AsyncHttpClientAdapterImpl Maven / Gradle / Ivy

package io.sphere.sdk.http;

import com.ning.http.client.*;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.concurrent.*;

final class AsyncHttpClientAdapterImpl extends Base implements AsyncHttpClientAdapter {
    private static final Logger LOGGER = LoggerFactory.getLogger(AsyncHttpClientAdapterImpl.class);
    private final AsyncHttpClient asyncHttpClient;
    private final ForkJoinPool threadPool = new ForkJoinPool();

    private AsyncHttpClientAdapterImpl(final AsyncHttpClient asyncHttpClient) {
        this.asyncHttpClient = asyncHttpClient;
    }

    @Override
    public CompletionStage execute(final HttpRequest httpRequest) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("executing " + httpRequest);
        }
        final Request request = asAhcRequest(httpRequest);
        try {
            final CompletionStage future = wrap(asyncHttpClient.executeRequest(request));
            return future.thenApply((Response response) -> {
                final byte[] responseBodyAsBytes = getResponseBodyAsBytes(response);
                final HttpResponse httpResponse = HttpResponse.of(response.getStatusCode(), responseBodyAsBytes, httpRequest, HttpHeaders.of(response.getHeaders()));
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("response " + httpResponse);
                }
                return httpResponse;
            });
        } catch (final IOException e) {
            final CompletableFuture future = new CompletableFuture<>();
            future.completeExceptionally(new HttpException(e));
            return future;
        }
    }

    private byte[] getResponseBodyAsBytes(final Response response) {
        try {
            return response.getResponseBodyAsBytes();
        } catch (IOException e) {
            throw new HttpException(e);
        }
    }

    /* package scope for testing */
     Request asAhcRequest(final HttpRequest request) {
        final RequestBuilder builder = new RequestBuilder()
                .setUrl(request.getUrl())
                .setMethod(request.getHttpMethod().toString());

        request.getHeaders().getHeadersAsMap().forEach((name, values) -> values.forEach(value -> builder.addHeader(name, value)));

        Optional.ofNullable(request.getBody()).ifPresent(body -> {
            if (body instanceof StringHttpRequestBody) {
                final String bodyAsString = ((StringHttpRequestBody) body).getString();
                builder.setBodyEncoding(StandardCharsets.UTF_8.name()).setBody(bodyAsString);
            } else if (body instanceof FileHttpRequestBody) {
                final File file = ((FileHttpRequestBody) body).getFile();
                builder.setBody(out -> FileUtils.copyFile(file, out));
                final long length = file.length();
                builder.addHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
            } else if (body instanceof FormUrlEncodedHttpRequestBody) {
                ((FormUrlEncodedHttpRequestBody) body).getData().forEach((name, value) -> builder.addParameter(name, value));
            }
        });
        final Request ahcRequest = builder.build();
        return ahcRequest;
    }

    @Override
    public void close() {
        asyncHttpClient.close();
        threadPool.shutdown();
    }

    public static AsyncHttpClientAdapterImpl of(final AsyncHttpClient asyncHttpClient) {
        return new AsyncHttpClientAdapterImpl(asyncHttpClient);
    }

    /**
     * Creates a {@link CompletionStage} from a {@link ListenableFuture}.
     * @param listenableFuture the future of the ning library
     * @param executor the executor to run the future in
     * @param  Type of the value that will be returned.
     * @return the Java 8 future implementation
     */
    private static  CompletionStage wrap(final ListenableFuture listenableFuture, final Executor executor) {
        final CompletableFuture result = new CompletableFuture<>();
        final Runnable listener = () -> {
            try {
                final T value = listenableFuture.get();
                result.complete(value);
            } catch (final InterruptedException | ExecutionException e) {
                result.completeExceptionally(e.getCause());
            }
        };
        listenableFuture.addListener(listener, executor);
        return result;
    }

    private CompletionStage wrap(final ListenableFuture listenableFuture) {
        return wrap(listenableFuture, threadPool);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy