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

io.ultreia.java4all.http.HResponseBuilder Maven / Gradle / Ivy

There is a newer version: 2.0.6
Show newest version
package io.ultreia.java4all.http;

/*
 * #%L
 * Http :: Api
 * %%
 * Copyright (C) 2017 - 2020 Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * @author Tony Chemit - [email protected]
 */
public class HResponseBuilder implements Closeable {

    private static final Logger log = LogManager.getLogger(HResponseBuilder.class);
    private final CloseableHttpClient client;
    private final Supplier gson;

    private HResponseBuilder(CloseableHttpClient client, Supplier gson) {
        this.client = client;
        this.gson = gson == null ? () -> new GsonBuilder().setPrettyPrinting().create() : gson;
    }

    public static HResponseBuilder create() {
        return create(null);
    }

    public static HResponseBuilder create(Supplier gson, CloseableHttpClient build) {
        return new HResponseBuilder(build, gson);
    }

    public static HResponseBuilder create(Supplier gson) {
        return create(gson, HttpClientBuilder.create()
                .setDefaultCookieStore(new BasicCookieStore())
                .setMaxConnTotal(1000)
                .setMaxConnPerRoute(1000)
//                .setConnectionTimeToLive(45, TimeUnit.SECONDS)
                .build());
    }

    public Supplier getGson() {
        return gson;
    }

    public HResponse executeRequest(HRequest request, int expectedStatusCode) throws IOException {
        HResponse response = executeRequest(request);

        Integer statusCode = response.getStatusCode();
        if (Objects.equals(statusCode, expectedStatusCode)) {
            return response;
        }

        String baseUrl = request.getBaseUrl();
        String responseAsString = response.toString();


        if (log.isWarnEnabled()) {
            log.warn(String.format("Unexpected status code for url: %s\n%s", baseUrl, responseAsString));
        }

        if (statusCode >= 400 && statusCode < 500) {

            throw new HResponseNotAvailableException(new URL(baseUrl));

        }

        if (statusCode >= 500) {
            HResponseError error;

            try {
                error = getGson().get().fromJson(responseAsString, HResponseError.class);
            } catch (Exception e) {
                error = new HResponseError(statusCode, null, responseAsString, null);
            }

            throw new HResponseErrorException(error);
        }

        throw new HttpResponseBadStatusCodeException(expectedStatusCode, statusCode);
    }

    public HResponse executeRequest(HRequest request) throws IOException {

        if (log.isInfoEnabled() && !request.isQuiet()) {
            log.info(String.format("execute request: [%s] %s", request.getRequestMethod(), request.getBaseUrl()));
        }
        if (log.isDebugEnabled()) {
            log.debug("request params: " + request.getParameters());
        }

        String requestMethod = request.getRequestMethod();
        HResponse response;
        switch (requestMethod) {
            case HttpGet.METHOD_NAME:
                response = get0(request);
                break;
            case HttpPost.METHOD_NAME:
                response = post0(request);
                break;
            case HttpPut.METHOD_NAME:
                response = put0(request);
                break;
            case HttpDelete.METHOD_NAME:
                response = delete0(request);
                break;
            case HttpPatch.METHOD_NAME:
                response = patch0(request);
                break;
            default:
                throw new IllegalStateException("Can't come here!");
        }

        log.debug("status: " + response.getStatusCode());
        for (Header header : response.getResponse().getAllHeaders()) {
            log.debug("response header: " + header);
        }
        return response;
    }

    private HResponse get0(HRequest request) throws IOException {

        String baseUrl = request.getBaseUrl();
        String url = buildUrlWithParameters(baseUrl, request.getParameters());

        HttpGet getMethod = new HttpGet(url);
        addTimeoutToRequest(getMethod, request.getTimeout(),request.getSocketTimeout());
        addHeaders(getMethod, request.getHeaders());

        HttpResponse response = executeRequest(getMethod);

        if (log.isDebugEnabled()) {
            log.debug("GET '" + baseUrl + "' return status code : " + response.getStatusLine().getStatusCode());
        }

        return consumeResponse(request, getMethod, response);

    }

    private HResponse post0(HRequest request) throws IOException {

        String baseUrl = request.getBaseUrl();
        String contentType = request.getContentType();
        String requestBody = request.getRequestBody();

        HttpPost postMethod = new HttpPost(baseUrl);

        addTimeoutToRequest(postMethod, request.getTimeout(),request.getSocketTimeout());
        addHeaders(postMethod, request.getHeaders());
        addRequestBody(postMethod, contentType, requestBody);

        if (postMethod.getEntity() == null) {

            HttpEntity entity;

            if (request.isUseMultipartForm()) {
                MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();

                if (contentType == null || contentType.trim().isEmpty()) {
                    contentType = ContentType.TEXT_PLAIN.getMimeType();
                }

                if (request.withoutFiles()) {

                    for (NameValuePair param : request.getParameters()) {
                        entityBuilder.addTextBody(param.getName(), param.getValue(), ContentType.create(contentType, StandardCharsets.UTF_8));
                    }
                } else {

                    for (Map.Entry paramFile : request.getFiles().entrySet()) {
                        byte[] content = Files.readAllBytes(paramFile.getValue().toPath());
                        ContentType contentType1 = ContentType.create(Files.probeContentType(paramFile.getValue().toPath()));
                        entityBuilder.addBinaryBody(paramFile.getKey(), content, contentType1, paramFile.getValue().getName());
                    }
                    for (NameValuePair param : request.getParameters()) {
                        entityBuilder.addTextBody(param.getName(), param.getValue(), ContentType.create(contentType, StandardCharsets.UTF_8));
                    }

                }

                entity = entityBuilder.build();

            } else {

                String url = URLEncodedUtils.format(request.getParameters(), StandardCharsets.UTF_8);
                StringEntity stringEntity = new StringEntity(url, StandardCharsets.UTF_8);
                stringEntity.setContentType("application/x-www-form-urlencoded");
                entity = stringEntity;
            }

            postMethod.setEntity(entity);

        }
        HttpResponse response = executeRequest(postMethod);

        if (log.isDebugEnabled()) {
            log.debug("POST '" + baseUrl + "' return status code : " + response.getStatusLine().getStatusCode());
        }

        return consumeResponse(request, postMethod, response);

    }

    private HResponse put0(HRequest request) throws IOException {

        String baseUrl = request.getBaseUrl();
        String contentType = request.getContentType();
        String requestBody = request.getRequestBody();

        HttpPut putMethod = new HttpPut(baseUrl);

        addHeaders(putMethod, request.getHeaders());
        addTimeoutToRequest(putMethod, request.getTimeout(),request.getSocketTimeout());
        addParameters(putMethod, contentType, request.getParameters());
        addRequestBody(putMethod, contentType, requestBody);

        HttpResponse response = executeRequest(putMethod);

        if (log.isDebugEnabled()) {
            log.debug("PUT '" + baseUrl + "' return status code : " + response.getStatusLine().getStatusCode());
        }

        return consumeResponse(request, putMethod, response);
    }

    private HResponse delete0(HRequest request) throws IOException {

        String baseUrl = request.getBaseUrl();

        HttpDelete deleteMethod = new HttpDelete(buildUrlWithParameters(baseUrl, request.getParameters()));

        addHeaders(deleteMethod, request.getHeaders());
        addTimeoutToRequest(deleteMethod, request.getTimeout(),request.getSocketTimeout());
        HttpResponse response = executeRequest(deleteMethod);

        if (log.isDebugEnabled()) {
            log.debug("DELETE '" + baseUrl + "' return status code : " + response.getStatusLine().getStatusCode());
        }

        return consumeResponse(request, deleteMethod, response);

    }

    private HResponse patch0(HRequest request) throws IOException {

        String baseUrl = request.getBaseUrl();

        HttpPatch patchMethod = new HttpPatch(buildUrlWithParameters(baseUrl, request.getParameters()));

        addHeaders(patchMethod, request.getHeaders());
        addTimeoutToRequest(patchMethod, request.getTimeout(),request.getSocketTimeout());
        HttpResponse response = executeRequest(patchMethod);

        if (log.isDebugEnabled()) {
            log.debug("PATCH '" + baseUrl + "' return status code : " + response.getStatusLine().getStatusCode());
        }

        return consumeResponse(request, patchMethod, response);

    }

    private HttpResponse executeRequest(HttpRequestBase request) throws IOException, HResponseNotAvailableException {

        try {
            return client.execute(request);
        } catch (UnknownHostException | ConnectException e) {
            // Le service n'est pas accessible
            throw new HResponseNotAvailableException(request.getURI().toURL());
        } catch (Exception e) {
            log.error("something is wrong here...", e);
            throw e;
        }

    }

    private HResponse consumeResponse(HRequest request, HttpRequestBase httpRequestBase, HttpResponse response) throws IOException {

        String baseUrl = request.getBaseUrl();

        Header[] responseHeaders = response.getAllHeaders();
        int statusCode = response.getStatusLine().getStatusCode();
        if (log.isDebugEnabled()) {
            log.debug(request.getRequestMethod() + " '" + baseUrl + "' return status code : " + statusCode);
        }

        String responseAsString;

        try (InputStream inputStream = response.getEntity().getContent()) {
            responseAsString = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
        }
        return new HResponse(httpRequestBase, response, statusCode, responseAsString, gson.get(), responseHeaders);
    }

    private String buildUrlWithParameters(String baseUrl, List parameters) {
        String result = baseUrl;
        if (!parameters.isEmpty()) {
            result += "?" + URLEncodedUtils.format(parameters, StandardCharsets.UTF_8);
        }
        return result;
    }

    private  void addHeaders(M httpMethod, Map headers) {
        for (Map.Entry entry : headers.entrySet()) {
            httpMethod.setHeader(entry.getKey(), entry.getValue());
        }
    }

    private  void addParameters(M method, String contentType, List parameters) {
        UrlEncodedFormEntity encodedFormEntity = new UrlEncodedFormEntity(parameters, StandardCharsets.UTF_8);
        if (!contentType.trim().isEmpty()) {
            encodedFormEntity.setContentType(contentType);
        }
        method.setEntity(encodedFormEntity);
    }

    private  void addRequestBody(M method, String contentType, String requestBody) {
        if (requestBody != null && !requestBody.trim().isEmpty()) {
            if (!contentType.trim().isEmpty()) {
                method.setEntity(new StringEntity(requestBody, ContentType.create(contentType, StandardCharsets.UTF_8)));
            } else {
                method.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));
            }
        }
    }

    public void close() throws IOException {
        client.close();
    }

    @Override
    protected void finalize() throws Throwable {

        try {
            client.close();
        } finally {
            super.finalize();
        }

    }

    private void addTimeoutToRequest(HttpRequestBase httpRequestBase, long timeout, long socketTimeout) {

        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout((int) timeout).setSocketTimeout((int)socketTimeout).build();
        if (log.isDebugEnabled()) {
            log.debug("Add custom timeout: " + timeout);
        }
        httpRequestBase.setConfig(requestConfig);

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy