org.structr.rest.common.HttpHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.structr.rest.common.HttpHelper.java

Source

/**
 * Copyright (C) 2010-2018 Structr GmbH
 *
 * This file is part of Structr <http://structr.org>.
 *
 * Structr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Structr 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 Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Structr.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.structr.rest.common;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
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.config.ConnectionConfig;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.structr.api.config.Settings;
import org.structr.common.error.FrameworkException;

/**
 * Helper class for outbound HTTP requests
 */
public class HttpHelper {

    private static final Logger logger = LoggerFactory.getLogger(HttpHelper.class.getName());

    private static String proxyUrl;
    private static String proxyUsername;
    private static String proxyPassword;
    private static String cookie;

    private static CloseableHttpClient client;
    private static RequestConfig reqConfig;

    private static void configure(final HttpRequestBase req, final String username, final String password,
            final String proxyUrlParameter, final String proxyUsernameParameter,
            final String proxyPasswordParameter, final String cookieParameter, final Map<String, String> headers,
            final boolean followRedirects) {

        if (StringUtils.isBlank(proxyUrlParameter)) {
            proxyUrl = Settings.HttpProxyUrl.getValue();
        } else {
            proxyUrl = proxyUrlParameter;
        }

        if (StringUtils.isBlank(proxyUsernameParameter)) {
            proxyUsername = Settings.HttpProxyUser.getValue();
        } else {
            proxyUsername = proxyUsernameParameter;
        }

        if (StringUtils.isBlank(proxyPasswordParameter)) {
            proxyPassword = Settings.HttpProxyPassword.getValue();
        } else {
            proxyPassword = proxyPasswordParameter;
        }

        if (!StringUtils.isBlank(cookieParameter)) {
            cookie = cookieParameter;
        }

        //final HttpHost target             = HttpHost.create(url.getHost());
        HttpHost proxy = null;
        final CredentialsProvider credsProvider = new BasicCredentialsProvider();

        if (StringUtils.isNoneBlank(username, password)) {

            credsProvider.setCredentials(new AuthScope(new HttpHost(req.getURI().getHost())),
                    new UsernamePasswordCredentials(username, password));
        }

        if (StringUtils.isNotBlank(proxyUrl)) {

            proxy = HttpHost.create(proxyUrl);

            if (StringUtils.isNoneBlank(proxyUsername, proxyPassword)) {

                credsProvider.setCredentials(new AuthScope(proxy),
                        new UsernamePasswordCredentials(proxyUsername, proxyPassword));
            }

        }

        client = HttpClients.custom().setDefaultConnectionConfig(ConnectionConfig.DEFAULT)
                .setUserAgent("curl/7.35.0").setDefaultCredentialsProvider(credsProvider).build();

        reqConfig = RequestConfig.custom().setProxy(proxy).setRedirectsEnabled(followRedirects)
                .setCookieSpec(CookieSpecs.DEFAULT).build();

        req.setConfig(reqConfig);

        if (StringUtils.isNotBlank(cookie)) {

            req.addHeader("Cookie", cookie);
            req.getParams().setParameter("http.protocol.single-cookie-header", true);
        }

        req.addHeader("Connection", "close");

        // add request headers from context
        for (final Map.Entry<String, String> header : headers.entrySet()) {
            req.addHeader(header.getKey(), header.getValue());
        }
    }

    private static String skipBOMIfPresent(final String content) {

        // Skip BOM to workaround this Jsoup bug: https://github.com/jhy/jsoup/issues/348
        if (content != null && content.length() > 1 && content.charAt(0) == 65279) {
            return content.substring(1);
        }

        return content;
    }

    public static String get(final String address) throws FrameworkException {
        return get(address, null, null, null, null, Collections.EMPTY_MAP);
    }

    public static String get(final String address, final Map<String, String> headers) throws FrameworkException {
        return get(address, null, null, headers);
    }

    public static String get(final String address, final String username, final String password,
            final Map<String, String> headers) throws FrameworkException {
        return get(address, username, password, null, null, null, null, headers);
    }

    public static String get(final String address, final String proxyUrl, final String proxyUsername,
            final String proxyPassword, final String cookie, final Map<String, String> headers)
            throws FrameworkException {
        return get(address, null, null, proxyUrl, proxyUsername, proxyPassword, cookie, headers);
    }

    public static String get(final String address, final String username, final String password,
            final String proxyUrl, final String proxyUsername, final String proxyPassword, final String cookie,
            final Map<String, String> headers) throws FrameworkException {

        String content = "";

        try {

            final URI url = URI.create(address);
            final HttpGet req = new HttpGet(url);

            configure(req, username, password, proxyUrl, proxyUsername, proxyPassword, cookie, headers, true);

            final CloseableHttpResponse resp = client.execute(req);

            content = IOUtils.toString(resp.getEntity().getContent(), charset(resp));

            content = skipBOMIfPresent(content);

        } catch (final Throwable t) {
            throw new FrameworkException(422,
                    "Unable to fetch content from address " + address + ": " + t.getMessage());
        }

        return content;
    }

    public static Map<String, String> head(final String address) {
        return head(address, null, null, null, null, Collections.EMPTY_MAP);
    }

    public static Map<String, String> head(final String address, final String username, final String password,
            final Map<String, String> headers) {
        return head(address, username, password, null, null, null, null, headers);
    }

    public static Map<String, String> head(final String address, final String proxyUrl, final String proxyUsername,
            final String proxyPassword, final String cookie, final Map<String, String> headers) {
        return head(address, null, null, proxyUrl, proxyUsername, proxyPassword, cookie, headers);
    }

    public static Map<String, String> head(final String address, final String username, final String password,
            final String proxyUrl, final String proxyUsername, final String proxyPassword, final String cookie,
            final Map<String, String> headers) {

        final Map<String, String> responseHeaders = new HashMap<>();

        try {
            final URI url = URI.create(address);
            final HttpHead req = new HttpHead(url);

            configure(req, username, password, proxyUrl, proxyUsername, proxyPassword, cookie, headers, false);

            final CloseableHttpResponse response = client.execute(req);

            responseHeaders.put("status", Integer.toString(response.getStatusLine().getStatusCode()));
            for (final Header header : response.getAllHeaders()) {

                responseHeaders.put(header.getName(), header.getValue());
            }

        } catch (final Throwable t) {

            logger.error("Unable to get headers from address {}, {}", new Object[] { address, t.getMessage() });
        }

        return responseHeaders;
    }

    public static Map<String, String> post(final String address, final String requestBody) {
        return post(address, requestBody, null, null, null, null, Collections.EMPTY_MAP);
    }

    public static Map<String, String> post(final String address, final String requestBody, final String username,
            final String password, final Map<String, String> headers) {
        return post(address, requestBody, username, password, null, null, null, null, headers);
    }

    public static Map<String, String> post(final String address, final String requestBody, final String username,
            final String password, final Map<String, String> headers, final String charset) {
        return post(address, requestBody, username, password, null, null, null, null, headers, charset);
    }

    public static Map<String, String> post(final String address, final String requestBody, final String proxyUrl,
            final String proxyUsername, final String proxyPassword, final String cookie,
            final Map<String, String> headers) {
        return post(address, requestBody, null, null, proxyUrl, proxyUsername, proxyPassword, cookie, headers);
    }

    public static Map<String, String> post(final String address, final String requestBody, final String username,
            final String password, final String proxyUrl, final String proxyUsername, final String proxyPassword,
            final String cookie, final Map<String, String> headers) {
        return post(address, requestBody, username, password, proxyUrl, proxyUsername, proxyPassword, cookie,
                headers, "UTF-8");
    }

    public static Map<String, String> post(final String address, final String requestBody, final String username,
            final String password, final String proxyUrl, final String proxyUsername, final String proxyPassword,
            final String cookie, final Map<String, String> headers, final String charset) {

        final Map<String, String> responseData = new HashMap<>();

        try {

            final URI url = URI.create(address);
            final HttpPost req = new HttpPost(url);

            configure(req, username, password, proxyUrl, proxyUsername, proxyPassword, cookie, headers, true);

            req.setEntity(new StringEntity(requestBody, charset));

            final CloseableHttpResponse response = client.execute(req);

            String content = IOUtils.toString(response.getEntity().getContent(), charset(response));

            content = skipBOMIfPresent(content);

            responseData.put("body", content);

            responseData.put("status", Integer.toString(response.getStatusLine().getStatusCode()));
            for (final Header header : response.getAllHeaders()) {

                responseData.put(header.getName(), header.getValue());
            }

        } catch (final Throwable t) {

            logger.error("Unable to fetch content from address {}, {}", new Object[] { address, t.getMessage() });
        }

        return responseData;
    }

    public static Map<String, String> put(final String address, final String requestBody) {
        return put(address, requestBody, null, null, null, null, Collections.EMPTY_MAP);
    }

    public static Map<String, String> put(final String address, final String requestBody, final String username,
            final String password, final Map<String, String> headers) {
        return put(address, requestBody, username, password, null, null, null, null, headers);
    }

    public static Map<String, String> put(final String address, final String requestBody, final String username,
            final String password, final Map<String, String> headers, final String charset) {
        return put(address, requestBody, username, password, null, null, null, null, headers, charset);
    }

    public static Map<String, String> put(final String address, final String requestBody, final String proxyUrl,
            final String proxyUsername, final String proxyPassword, final String cookie,
            final Map<String, String> headers) {
        return put(address, requestBody, null, null, proxyUrl, proxyUsername, proxyPassword, cookie, headers);
    }

    public static Map<String, String> put(final String address, final String requestBody, final String username,
            final String password, final String proxyUrl, final String proxyUsername, final String proxyPassword,
            final String cookie, final Map<String, String> headers) {
        return put(address, requestBody, username, password, proxyUrl, proxyUsername, proxyPassword, cookie,
                headers, "UTF-8");
    }

    public static Map<String, String> put(final String address, final String requestBody, final String username,
            final String password, final String proxyUrl, final String proxyUsername, final String proxyPassword,
            final String cookie, final Map<String, String> headers, final String charset) {

        final Map<String, String> responseData = new HashMap<>();

        try {

            final URI url = URI.create(address);
            final HttpPut req = new HttpPut(url);

            configure(req, username, password, proxyUrl, proxyUsername, proxyPassword, cookie, headers, true);

            req.setEntity(new StringEntity(requestBody, charset));

            final CloseableHttpResponse response = client.execute(req);

            String content = IOUtils.toString(response.getEntity().getContent(), charset(response));

            content = skipBOMIfPresent(content);

            responseData.put("body", content);

            responseData.put("status", Integer.toString(response.getStatusLine().getStatusCode()));
            for (final Header header : response.getAllHeaders()) {

                responseData.put(header.getName(), header.getValue());
            }

        } catch (final Throwable t) {

            logger.error("Unable to fetch content from address {}, {}", new Object[] { address, t.getMessage() });
        }

        return responseData;
    }

    public static Map<String, String> delete(final String address) {
        return delete(address, null, null, null, null, Collections.EMPTY_MAP);
    }

    public static Map<String, String> delete(final String address, final String username, final String password,
            final Map<String, String> headers) {
        return delete(address, username, password, null, null, null, null, headers);
    }

    public static Map<String, String> delete(final String address, final String proxyUrl,
            final String proxyUsername, final String proxyPassword, final String cookie,
            final Map<String, String> headers) {
        return delete(address, null, null, proxyUrl, proxyUsername, proxyPassword, cookie, headers);
    }

    public static Map<String, String> delete(final String address, final String username, final String password,
            final String proxyUrl, final String proxyUsername, final String proxyPassword, final String cookie,
            final Map<String, String> headers) {

        final Map<String, String> responseData = new HashMap<>();

        try {

            final URI url = URI.create(address);
            final HttpDelete req = new HttpDelete(url);

            configure(req, username, password, proxyUrl, proxyUsername, proxyPassword, cookie, headers, true);

            final CloseableHttpResponse response = client.execute(req);

            String content = IOUtils.toString(response.getEntity().getContent(), charset(response));

            content = skipBOMIfPresent(content);

            responseData.put("body", content);

            responseData.put("status", Integer.toString(response.getStatusLine().getStatusCode()));
            for (final Header header : response.getAllHeaders()) {

                responseData.put(header.getName(), header.getValue());
            }
        } catch (final Throwable t) {

            logger.error("Unable to issue DELETE command to address {}, {}",
                    new Object[] { address, t.getMessage() });
        }

        return responseData;
    }

    public static InputStream getAsStream(final String address) {

        return getAsStream(address, null, null, null, null, null, null, Collections.EMPTY_MAP);
    }

    public static InputStream getAsStream(final String address, final String username, final String password,
            final String proxyUrl, final String proxyUsername, final String proxyPassword, final String cookie,
            final Map<String, String> headers) {

        try {

            final URI url = URI.create(address);
            final HttpGet req = new HttpGet(url);

            configure(req, username, password, proxyUrl, proxyUsername, proxyPassword, cookie, headers, true);

            final CloseableHttpResponse resp = client.execute(req);

            return resp.getEntity().getContent();

        } catch (final Throwable t) {

            logger.error("Unable to get content stream from address {}, {}",
                    new Object[] { address, t.getMessage() });

        }

        return null;
    }

    public static String charset(final HttpResponse response) {

        final ContentType contentType = ContentType.get(response.getEntity());
        String charset = "UTF-8";
        if (contentType != null && contentType.getCharset() != null) {

            charset = contentType.getCharset().toString();
        }

        return charset;
    }

    public static void streamURLToFile(final String address, final java.io.File fileOnDisk)
            throws FrameworkException {
        streamURLToFile(address, null, null, null, null, Collections.EMPTY_MAP, fileOnDisk);
    }

    public static void streamURLToFile(final String address, final Map<String, String> headers,
            final java.io.File fileOnDisk) throws FrameworkException {
        streamURLToFile(address, null, null, headers, fileOnDisk);
    }

    public static void streamURLToFile(final String address, final String username, final String password,
            final Map<String, String> headers, final java.io.File fileOnDisk) throws FrameworkException {
        streamURLToFile(address, username, password, null, null, null, null, headers, fileOnDisk);
    }

    public static void streamURLToFile(final String address, final String proxyUrl, final String proxyUsername,
            final String proxyPassword, final String cookie, final Map<String, String> headers,
            final java.io.File fileOnDisk) throws FrameworkException {
        streamURLToFile(address, null, null, proxyUrl, proxyUsername, proxyPassword, cookie, headers, fileOnDisk);
    }

    public static void streamURLToFile(final String address, final String username, final String password,
            final String proxyUrl, final String proxyUsername, final String proxyPassword, final String cookie,
            final Map<String, String> headers, final java.io.File fileOnDisk) throws FrameworkException {

        try {

            final URI url = URI.create(address);
            final HttpGet req = new HttpGet(url);

            logger.info("Downloading from {}", address);

            configure(req, username, password, proxyUrl, proxyUsername, proxyPassword, cookie, headers, true);

            req.addHeader("User-Agent", "curl/7.35.0");

            final CloseableHttpResponse resp = client.execute(req);

            final int statusCode = resp.getStatusLine().getStatusCode();

            if (statusCode == 200) {

                try (final InputStream is = resp.getEntity().getContent()) {

                    try (final OutputStream os = new FileOutputStream(fileOnDisk)) {

                        IOUtils.copy(is, os);
                    }
                }

            } else {

                String content = IOUtils.toString(resp.getEntity().getContent(), HttpHelper.charset(resp));

                content = skipBOMIfPresent(content);

                System.out.println("Response body: " + content);
                logger.warn("Unable to create file from URI {}: status code was {}",
                        new Object[] { address, statusCode });
            }

        } catch (final Throwable t) {
            throw new FrameworkException(422,
                    "Unable to fetch file content from address " + address + ": " + t.getMessage());
        }

    }
}