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

com.tomtom.http.HttpClient.groovy Maven / Gradle / Ivy

/*
 * Copyright (C) 2017. TomTom International BV (http://tomtom.com).
 *
 * Licensed 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 com.tomtom.http

import com.fasterxml.jackson.databind.ObjectMapper
import com.tomtom.http.response.Response
import org.apache.http.client.HttpClient as ApacheHttpClient
import org.apache.http.conn.ssl.NoopHostnameVerifier
import org.apache.http.conn.ssl.TrustStrategy
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.ssl.SSLContexts

import java.security.cert.CertificateException
import java.security.cert.X509Certificate

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES

class HttpClient {

    private static ApacheHttpClient client

    final RequestBuilder builder
    final ResponseParser parser

    /**
     * Builds {@link HttpClient} with a number of (optional) parameters.
     * @param baseUrl a url prefix for request {@code path} parameter
     * @param client a custom {@link org.apache.http.client.HttpClient}
     * @param mapper a custom {@link ObjectMapper}
     */
    HttpClient(Map properties = [:]) {
        client = properties['client'] as ApacheHttpClient ?: defaultClient()

        def mapper = properties['mapper'] as ObjectMapper ?: defaultMapper()
        def builderParams = [mapper: mapper]
        def baseUrl = properties['baseUrl'] as String
        if (baseUrl) builderParams += [baseUrl: baseUrl]

        builder = properties['builder'] as RequestBuilder ?: new RequestBuilder(builderParams)
        parser = properties['parser'] as ResponseParser ?: new ResponseParser(mapper: mapper)
    }

    /**
     * Builds {@link HttpClient} with a base URL.
     * @param baseUrl a url prefix for request {@code path} parameter
     */
    HttpClient(String baseUrl) {
        this(baseUrl: baseUrl)
    }

    /**
     * Builds {@link HttpClient} with a base URL.
     * @param baseUrl a url prefix for request {@code path} parameter
     */
    HttpClient(URI baseUrl) {
        this(baseUrl.toString())
    }

    /**
     * Builds {@link HttpClient} with a base URL.
     * @param baseUrl a url prefix for request {@code path} parameter
     */
    HttpClient(URL baseUrl) {
        this(baseUrl.toString())
    }

    private static ObjectMapper defaultMapper() {
        new ObjectMapper().disable(FAIL_ON_UNKNOWN_PROPERTIES)
    }

    private static ApacheHttpClient defaultClient() {
        def context = SSLContexts
                .custom()
                .loadTrustMaterial(null, new TrustStrategy() {
                    @Override
                    boolean isTrusted(
                            X509Certificate[] chain,
                            String authType) throws CertificateException {
                        true
                    }
                }).build()

        HttpClientBuilder
                .create()
                .setSSLContext(context)
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .disableAuthCaching()
                .disableAutomaticRetries()
                .disableCookieManagement()
                .disableRedirectHandling()
                .build()
    }

    /**
     * Possible properties:
*  path - a request path (appended to a base url defined at {@link #HttpClient(Map)} constructor)
*  url - a full request url (overrides path and base url)
*  headers as {@link Map}
*  body - a request body. Anything except {@link String} is serialized to a json.
*  expecting - a class to deserialize response body to. If not specified, response body is a {@link String}
*  of - a subclass to deserialize response body to. Use to deserialize generic responses like {@link Collection}<{@link Map}>. */ Response head(Map properties) { def all = properties + [method: 'head'] performRequest all } def RequestBuilder.UrlBuilder head() { new RequestBuilder.UrlBuilder<>(method: { Map p -> head(p) }) } /** * Possible properties:
*  path - a request path (appended to a base url defined at {@link #HttpClient(Map)} constructor)
*  url - a full request url (overrides path and base url)
*  headers as {@link Map}
*  body - a request body. Anything except {@link String} is serialized to a json.
*  expecting - a class to deserialize response body to. If not specified, response body is a {@link String}
*  of - a subclass to deserialize response body to. Use to deserialize generic responses like {@link Collection}<{@link Map}>. */ Response get(Map properties) { def all = properties + [method: 'get'] performRequest all } def RequestBuilder.UrlBuilder get() { new RequestBuilder.UrlBuilder<>(method: { Map p -> get(p) }) } /** * Possible properties:
*  path - a request path (appended to a base url defined at {@link #HttpClient(Map)} constructor)
*  url - a full request url (overrides path and base url)
*  headers as {@link Map}
*  body - a request body. Anything except {@link String} is serialized to a json.
*  expecting - a class to deserialize response body to. If not specified, response body is a {@link String}
*  of - a subclass to deserialize response body to. Use to deserialize generic responses like {@link Collection}<{@link Map}>. */ Response post(Map properties) { def all = properties + [method: 'post'] performRequest all } def RequestBuilder.UrlBuilder post() { new RequestBuilder.UrlBuilder<>(method: { Map p -> post(p) }) } /** * Possible properties:
*  path - a request path (appended to a base url defined at {@link #HttpClient(Map)} constructor)
*  url - a full request url (overrides path and base url)
*  headers as {@link Map}
*  body - a request body. Anything except {@link String} is serialized to a json.
*  expecting - a class to deserialize response body to. If not specified, response body is a {@link String}
*  of - a subclass to deserialize response body to. Use to deserialize generic responses like {@link Collection}<{@link Map}>. */ Response put(Map properties) { def all = properties + [method: 'put'] performRequest all } def RequestBuilder.UrlBuilder put() { new RequestBuilder.UrlBuilder<>(method: { Map p -> put(p) }) } /** * Possible properties:
*  path - a request path (appended to a base url defined at {@link #HttpClient(Map)} constructor)
*  url - a full request url (overrides path and base url)
*  headers as {@link Map}
*  body - a request body. Anything except {@link String} is serialized to a json.
*  expecting - a class to deserialize response body to. If not specified, response body is a {@link String}
*  of - a subclass to deserialize response body to. Use to deserialize generic responses like {@link Collection}<{@link Map}>. */ Response delete(Map properties) { def all = properties + [method: 'delete'] performRequest all } def RequestBuilder.UrlBuilder delete() { new RequestBuilder.UrlBuilder<>(method: { Map p -> delete(p) }) } /** * Possible properties:
*  path - a request path (appended to a base url defined at {@link #HttpClient(Map)} constructor)
*  url - a full request url (overrides path and base url)
*  headers as {@link Map}
*  body - a request body. Anything except {@link String} is serialized to a json.
*  expecting - a class to deserialize response body to. If not specified, response body is a {@link String}
*  of - a subclass to deserialize response body to. Use to deserialize generic responses like {@link Collection}<{@link Map}>. */ Response trace(Map properties) { def all = properties + [method: 'trace'] performRequest all } def RequestBuilder.UrlBuilder trace() { new RequestBuilder.UrlBuilder<>(method: { Map p -> trace(p) }) } /** * Possible properties:
*  path - a request path (appended to a base url defined at {@link #HttpClient(Map)} constructor)
*  url - a full request url (overrides path and base url)
*  headers as {@link Map}
*  body - a request body. Anything except {@link String} is serialized to a json.
*  expecting - a class to deserialize response body to. If not specified, response body is a {@link String}
*  of - a subclass to deserialize response body to. Use to deserialize generic responses like {@link Collection}<{@link Map}>. */ Response patch(Map properties) { def all = properties + [method: 'patch'] performRequest all } def RequestBuilder.UrlBuilder patch() { new RequestBuilder.UrlBuilder<>(method: { Map p -> patch(p) }) } /** * Possible properties:
*  path - a request path (appended to a base url defined at {@link #HttpClient(Map)} constructor)
*  url - a full request url (overrides path and base url)
*  headers as {@link Map}
*  body - a request body. Anything except {@link String} is serialized to a json.
*  expecting - a class to deserialize response body to. If not specified, response body is a {@link String}
*  of - a subclass to deserialize response body to. Use to deserialize generic responses like {@link Collection}<{@link Map}>. */ Response options(Map properties) { def all = properties + [method: 'options'] performRequest all } def RequestBuilder.UrlBuilder options() { new RequestBuilder.UrlBuilder<>(method: { Map p -> options(p) }) } private Response performRequest(Map properties) { def request = builder.request properties def response = client.execute request parser.parse( response, properties['expecting'] as Class, properties['of'] as Class) } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy