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

com.tinypass.client.common.ApacheApiInvoker Maven / Gradle / Ivy

There is a newer version: 16.331.0
Show newest version
package com.tinypass.client.common;

import com.tinypass.client.TinypassClientApi;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.entity.mime.FileBody;
import org.apache.hc.client5.http.entity.mime.InputStreamBody;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.http.protocol.BasicHttpContext;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.ssl.TLS;
import org.apache.hc.core5.net.URIBuilder;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class ApacheApiInvoker extends ApiInvoker {

    private JsonParser jsonParser;
    private CloseableHttpClient httpClient;
    private boolean closed = false;

    /**
     * Create instance of ApacheApiInvoker and initialize apache http client
     *
     * @param jsonParser     Implementation of JsonParser
     * @param maxConnections Max connection in pool
     * @param timeout        Timeout in ms
     */
    public ApacheApiInvoker(JsonParser jsonParser, int maxConnections, int timeout) {
        this.jsonParser = jsonParser;

        if (jsonParser == null || maxConnections < 1 || timeout < 100) {
            throw new RuntimeException("incorrect parameter");
        }


        ConnectionConfig connectionConfig = ConnectionConfig.custom().setConnectTimeout(timeout, TimeUnit.MILLISECONDS).build();

        PoolingHttpClientConnectionManager manager = PoolingHttpClientConnectionManagerBuilder.create()
                .setDefaultTlsConfig(TlsConfig.custom()
                        .setSupportedProtocols(TLS.V_1_2,
                                TLS.V_1_3).build())
                .setConnectionConfigResolver(httpRoute -> {
                    if (httpRoute.isSecure()) {
                        return connectionConfig;
                    } else {
                        return ConnectionConfig.custom().setConnectTimeout(timeout, TimeUnit.MILLISECONDS).build();
                    }
                })
                .build();
        httpClient = HttpClients.custom()
                .setConnectionManager(manager)
                .setUserAgent("Piano/VX API JVM SDK v." + TinypassClientApi.VERSION)
                .build();
    }

    @Override
    public  T invokeAPI(String host, String path, String method, String token,
                           Map> queryParams, Object body, Map headerParams,
                           Map> formParams, String resultContainerType, Class resultClass)
            throws ApiException {
        try {

            //Always add the api_token to each request
            headerParams.put("api_token", token);

            HttpUriRequestBase request = getHttpRequest(host, path, method, queryParams, body, headerParams,
                    formParams);

            HttpContext httpContext = new BasicHttpContext();

            //Send the request; It will immediately return the response in HttpResponse object if any
            try (ClassicHttpResponse response = httpClient.execute(request, httpContext)) {
                int statusCode = response.getCode();
                if (statusCode != 200) {
                    throw new ApiException(statusCode, "Error sending REST Request. Status code: " +
                            statusCode);
                }
                return jsonParser.deserialize(EntityUtils.toString(response.getEntity()), resultContainerType, resultClass);
            }

        } catch (ApiException ae) {
            throw ae;
        } catch (Exception e) {
            throw new ApiException(500, e.getMessage(), e);
        }
    }

    /**
     * Helper method to convert our parameter map into NameValuePairs list
     * that can be added to the request
     */

    private List convertToPairs(Map> params) {
        return params.entrySet().stream()
                .flatMap(
                        e -> e.getValue().stream().map(v -> new BasicNameValuePair(e.getKey(), v))
                )
                .collect(Collectors.toList());
    }

    /**
     * Build the actual HTTP request.  Thanks to httpclient this
     * method is more then ugly.
     * 

* We have to differenciate between the different requests GET vs POST * but also different POST parameter options. *

* POSTs can be: *

* multi-part * form-encoded * body content *

* By default, POST will do a standard form-urlencoded request. *

* If a file is one of the body parameters then instead * the request will become a multipart *

* NOTE: Because of the lameness of jersey, a multipart * request will add the non file based parameters to the URL query string */ private HttpUriRequestBase getHttpRequest(String host, String path, String method, Map> queryParams, Object body, Map headerParams, Map> formParams) throws UnsupportedEncodingException, URISyntaxException, ApiException { HttpUriRequestBase request; if (method.equals("POST")) { URIBuilder uriBuilder = new URIBuilder(host + path); HttpPost postRequest = new HttpPost(host + path); request = postRequest; // Combine all outstanding form / query params and attach them // to the query string List nameValuePairs = convertToPairs(queryParams); if (body != null) { nameValuePairs.addAll(convertToPairs(formParams)); } for (BasicNameValuePair nameValuePair : nameValuePairs) { uriBuilder.addParameter(nameValuePair.getName(), nameValuePair.getValue()); } postRequest.setUri(uriBuilder.build().normalize()); if (body == null) { if (!formParams.isEmpty()) { //urlencoded List formNameValuePairs = convertToPairs(formParams); postRequest.setEntity(new UrlEncodedFormEntity(formNameValuePairs, StandardCharsets.UTF_8)); request.addHeader("content-type", "application/x-www-form-urlencoded"); } } else if (body instanceof InputStream || body instanceof File) { //Multi-part request MultipartEntityBuilder builder = MultipartEntityBuilder.create(); if (body instanceof InputStream) { InputStreamBody bin = new InputStreamBody((InputStream) body, "file"); builder.addPart("file", bin); } else { FileBody bin = new FileBody((File) body); builder.addPart("file", bin); } postRequest.setEntity(builder.build()); } else { //Set the request post body StringEntity userEntity = new StringEntity(jsonParser.serialize(body), ContentType.APPLICATION_JSON); postRequest.setEntity(userEntity); request.addHeader("content-type", "application/json"); } } else { URIBuilder builder = new URIBuilder(host + path); //builder.setScheme(host.substring(0, host.indexOf("://"))) // .setHost(host.substring(host.indexOf("://") + 3)).setPath(path); for (String name : queryParams.keySet()) { for (String value : queryParams.get(name)) { builder.addParameter(name, value); } } URI uri = builder.build().normalize(); request = new HttpGet(uri); request.addHeader("content-type", "application/json"); } for (String name : headerParams.keySet()) { request.addHeader(name, headerParams.get(name)); } request.addHeader("cv", "java-"); return request; } @Override public void close() throws IOException { closed = true; httpClient.close(); System.out.println(" connection pool of http client has been closed "); } public boolean isClosed() { return closed; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy