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

net.nemerosa.ontrack.client.OTHttpClientImpl Maven / Gradle / Ivy

There is a newer version: 4.4.5
Show newest version
package net.nemerosa.ontrack.client;

import net.nemerosa.ontrack.common.Document;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URL;
import java.util.function.Supplier;

import static java.lang.String.format;
import static org.apache.commons.lang3.StringUtils.stripEnd;

public class OTHttpClientImpl implements OTHttpClient {

    private final URL url;
    private final HttpHost host;
    private final Supplier httpClientSupplier;
    private final HttpClientContext httpContext;
    private final OTHttpClientLogger clientLogger;

    public OTHttpClientImpl(URL url, HttpHost host, Supplier httpClientSupplier, HttpClientContext httpContext, OTHttpClientLogger clientLogger) {
        this.url = url;
        this.host = host;
        this.httpClientSupplier = httpClientSupplier;
        this.httpContext = httpContext;
        this.clientLogger = clientLogger;
    }

    @Override
    public URL getUrl() {
        return url;
    }

    @Override
    public String getUrl(String path, Object... parameters) {
        if (StringUtils.startsWith(path, "http")) {
            return format(path, parameters);
        } else {
            String formattedPath = format(path, parameters);
            if (!formattedPath.startsWith("/")) {
                formattedPath = "/" + formattedPath;
            }
            return format(
                    "%s%s",
                    stripEnd(url.toString(), "/"),
                    formattedPath
            );
        }
    }

    @Override
    public  T get(ResponseParser responseParser, String path, Object... parameters) {
        return request(new HttpGet(getUrl(path, parameters)), responseParser);
    }

    @Override
    public  T delete(ResponseParser responseParser, String path, Object... parameters) {
        return request(new HttpDelete(getUrl(path, parameters)), responseParser);
    }

    @Override
    public  T post(ResponseParser responseParser, HttpEntity data, String path, Object... parameters) {
        HttpPost post = new HttpPost(getUrl(path, parameters));
        if (data != null) {
            post.setEntity(data);
        }
        return request(post, responseParser);
    }

    @Override
    public  T put(ResponseParser responseParser, HttpEntity data, String path, Object... parameters) {
        HttpPut put = new HttpPut(getUrl(path, parameters));
        if (data != null) {
            put.setEntity(data);
        }
        return request(put, responseParser);
    }

    @Override
    public  T upload(ResponseParser responseParser, String name, Document document, String fileName, String path, Object... parameters) {
        HttpPost post = new HttpPost(getUrl(path));
        // Sets the content
        post.setEntity(
                MultipartEntityBuilder.create()
                        .addBinaryBody(
                                name,
                                document.getContent(),
                                ContentType.parse(document.getType()),
                                fileName
                        )
                        .build()
        );
        // OK
        return request(post, responseParser);
    }

    @Override
    public Document download(String path, Object... parameters) {
        HttpGet get = new HttpGet(getUrl(path));
        return request(get, (request, response, entity) -> {
            return handleErrorCode(request, response, () -> {
                // Gets the content as bytes
                byte[] bytes;
                try {
                    bytes = EntityUtils.toByteArray(entity);
                } catch (IOException e) {
                    throw new ClientIOException(request, e);
                }
                if (bytes == null || bytes.length == 0) {
                    return Document.EMPTY;
                }
                // OK
                return new Document(
                        entity.getContentType().getValue(),
                        bytes
                );
            });
        });
    }

    @Override
    public  T request(HttpRequestBase request, final ResponseParser responseParser) {
        return request(
                request,
                (request1, response, entity) -> baseHandleResponse(request1, response, entity,
                        entity1 -> {
                            // Gets the content as a string
                            String content = entity1 != null ? EntityUtils.toString(entity1, "UTF-8") : null;
                            // Parses the response
                            return responseParser.parse(content);
                        })
        );
    }

    @Override
    public CloseableHttpClient getHttpClient() {
        return httpClientSupplier.get();
    }

    @Override
    public HttpHost getHttpHost() {
        return host;
    }

    @Override
    public HttpClientContext getHttpClientContext() {
        return httpContext;
    }

    protected  T request(HttpRequestBase request, ResponseHandler responseHandler) {
        clientLogger.trace("[request] " + request);
        // Executes the call
        try {
            try (CloseableHttpClient http = httpClientSupplier.get()) {
                HttpResponse response = http.execute(host, request, httpContext);
                clientLogger.trace("[response] " + response);
                // Entity response
                HttpEntity entity = response.getEntity();
                try {
                    return responseHandler.handleResponse(request, response, entity);
                } finally {
                    EntityUtils.consume(entity);
                }
            }
        } catch (IOException e) {
            throw new ClientGeneralException(request, e);
        } finally {
            request.releaseConnection();
        }
    }

    protected  T handleErrorCode(HttpRequestBase request, HttpResponse response, Supplier supplier) throws IOException {
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == HttpStatus.SC_OK ||
                statusCode == HttpStatus.SC_CREATED ||
                statusCode == HttpStatus.SC_ACCEPTED) {
            return supplier.get();
        } else if (statusCode == HttpStatus.SC_BAD_REQUEST) {
            throw new ClientValidationException(getMessage(response));
        } else if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
            throw new ClientCannotLoginException(request);
        } else if (statusCode == HttpStatus.SC_FORBIDDEN) {
            throw new ClientForbiddenException(request);
        } else if (statusCode == HttpStatus.SC_NOT_FOUND) {
            throw new ClientNotFoundException(getMessage(response));
        } else if (statusCode == HttpStatus.SC_NO_CONTENT) {
            return null;
        } else if (statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
            String content = getMessage(response);
            if (StringUtils.isNotBlank(content)) {
                throw new ClientMessageException(content);
            } else {
                // Generic error
                throw new ClientServerException(
                        request,
                        statusCode,
                        response.getStatusLine().getReasonPhrase());
            }
        } else {
            // Generic error
            throw new ClientServerException(
                    request,
                    statusCode,
                    response.getStatusLine().getReasonPhrase());
        }
    }

    protected  T baseHandleResponse(HttpRequestBase request, HttpResponse response, HttpEntity entity,
                                       EntityParser entityParser) throws ParseException, IOException {
        return handleErrorCode(request, response, () -> {
            try {
                return entityParser.parse(entity);
            } catch (IOException e) {
                throw new ClientIOException(request, e);
            }
        });
    }

    private static String getMessage(HttpResponse response) throws IOException {
        return EntityUtils.toString(response.getEntity(), "UTF-8");
    }

    @FunctionalInterface
    protected static interface EntityParser {

        T parse(HttpEntity entity) throws IOException;

    }

    @FunctionalInterface
    protected static interface ResponseHandler {

        T handleResponse(HttpRequestBase request, HttpResponse response, HttpEntity entity) throws ParseException, IOException;

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy