lucee.commons.net.http.httpclient.HTTPEngine4Impl.java Source code

Java tutorial

Introduction

Here is the source code for lucee.commons.net.http.httpclient.HTTPEngine4Impl.java

Source

/**
 *
 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 **/
package lucee.commons.net.http.httpclient;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import lucee.commons.io.IOUtil;
import lucee.commons.io.TemporaryStream;
import lucee.commons.io.res.Resource;
import lucee.commons.lang.ExceptionUtil;
import lucee.commons.lang.StringUtil;
import lucee.commons.net.http.Entity;
import lucee.commons.net.http.HTTPEngine;
import lucee.commons.net.http.HTTPResponse;
import lucee.commons.net.http.httpclient.entity.ByteArrayHttpEntity;
import lucee.commons.net.http.httpclient.entity.EmptyHttpEntity;
import lucee.commons.net.http.httpclient.entity.ResourceHttpEntity;
import lucee.commons.net.http.httpclient.entity.TemporaryStreamHttpEntity;
import lucee.runtime.PageContextImpl;
import lucee.runtime.engine.ThreadLocalPageContext;
import lucee.runtime.exp.PageException;
import lucee.runtime.net.http.ReqRspUtil;
import lucee.runtime.net.proxy.ProxyData;
import lucee.runtime.net.proxy.ProxyDataImpl;
import lucee.runtime.op.Caster;
import lucee.runtime.op.Decision;
import lucee.runtime.tag.Http;
import lucee.runtime.type.dt.TimeSpanImpl;
import lucee.runtime.type.util.CollectionUtil;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpMessage;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
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.HttpUriRequest;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;

public class HTTPEngine4Impl {

    private static PoolingHttpClientConnectionManager connMan;

    /**
     * does a http get request
     * 
     * @param url
     * @param username
     * @param password
     * @param timeout
     * @param charset
     * @param useragent
     * @param proxyserver
     * @param proxyport
     * @param proxyuser
     * @param proxypassword
     * @param headers
     * @return
     * @throws IOException
     */
    public static HTTPResponse get(URL url, String username, String password, long timeout, boolean redirect,
            String charset, String useragent, ProxyData proxy, lucee.commons.net.http.Header[] headers)
            throws IOException {
        HttpGet get = new HttpGet(url.toExternalForm());
        return _invoke(url, get, username, password, timeout, redirect, charset, useragent, proxy, headers, null);
    }

    /**
     * does a http post request
     * 
     * @param url
     * @param username
     * @param password
     * @param timeout
     * @param charset
     * @param useragent
     * @param proxyserver
     * @param proxyport
     * @param proxyuser
     * @param proxypassword
     * @param headers
     * @return
     * @throws IOException
     */
    public static HTTPResponse post(URL url, String username, String password, long timeout, boolean redirect,
            String charset, String useragent, ProxyData proxy, lucee.commons.net.http.Header[] headers)
            throws IOException {
        HttpPost post = new HttpPost(url.toExternalForm());
        return _invoke(url, post, username, password, timeout, redirect, charset, useragent, proxy, headers, null);
    }

    public static HTTPResponse post(URL url, String username, String password, long timeout, boolean redirect,
            String charset, String useragent, ProxyData proxy, lucee.commons.net.http.Header[] headers,
            Map<String, String> formfields) throws IOException {
        HttpPost post = new HttpPost(url.toExternalForm());

        return _invoke(url, post, username, password, timeout, redirect, charset, useragent, proxy, headers,
                formfields);
    }

    /**
     * does a http put request
     * 
     * @param url
     * @param username
     * @param password
     * @param timeout
     * @param charset
     * @param useragent
     * @param proxyserver
     * @param proxyport
     * @param proxyuser
     * @param proxypassword
     * @param headers
     * @param body
     * @return
     * @throws IOException
     * @throws PageException
     */
    public static HTTPResponse put(URL url, String username, String password, long timeout, boolean redirect,
            String mimetype, String charset, String useragent, ProxyData proxy,
            lucee.commons.net.http.Header[] headers, Object body) throws IOException {
        HttpPut put = new HttpPut(url.toExternalForm());
        setBody(put, body, mimetype, charset);
        return _invoke(url, put, username, password, timeout, redirect, charset, useragent, proxy, headers, null);

    }

    /**
     * does a http delete request
     * 
     * @param url
     * @param username
     * @param password
     * @param timeout
     * @param charset
     * @param useragent
     * @param proxyserver
     * @param proxyport
     * @param proxyuser
     * @param proxypassword
     * @param headers
     * @return
     * @throws IOException
     */
    public static HTTPResponse delete(URL url, String username, String password, long timeout, boolean redirect,
            String charset, String useragent, ProxyData proxy, lucee.commons.net.http.Header[] headers)
            throws IOException {
        HttpDelete delete = new HttpDelete(url.toExternalForm());
        return _invoke(url, delete, username, password, timeout, redirect, charset, useragent, proxy, headers,
                null);
    }

    /**
     * does a http head request
     * 
     * @param url
     * @param username
     * @param password
     * @param timeout
     * @param charset
     * @param useragent
     * @param proxyserver
     * @param proxyport
     * @param proxyuser
     * @param proxypassword
     * @param headers
     * @return
     * @throws IOException
     */
    public static HTTPResponse head(URL url, String username, String password, long timeout, boolean redirect,
            String charset, String useragent, ProxyData proxy, lucee.commons.net.http.Header[] headers)
            throws IOException {
        HttpHead head = new HttpHead(url.toExternalForm());
        return _invoke(url, head, username, password, timeout, redirect, charset, useragent, proxy, headers, null);
    }

    public static lucee.commons.net.http.Header header(String name, String value) {
        return new HeaderImpl(name, value);
    }

    private static Header toHeader(lucee.commons.net.http.Header header) {
        if (header instanceof Header)
            return (Header) header;
        if (header instanceof HeaderWrap)
            return ((HeaderWrap) header).header;
        return new HeaderImpl(header.getName(), header.getValue());
    }

    public static HttpClientBuilder getHttpClientBuilder() {
        HttpClientBuilder builder = HttpClients.custom();
        /*
         * if(connMan==null) { connMan = new PoolingHttpClientConnectionManager(); // Increase max total connection to 200 connMan.setMaxTotal(200); // Increase
         * default max connection per route to 20 connMan.setDefaultMaxPerRoute(20); // Increase max connections for localhost:80 to 50 //HttpHost localhost =
         * new HttpHost("locahost", 80); //cm.setMaxPerRoute(new HttpRoute(localhost), 50); } builder.setConnectionManager(connMan);
         */
        return builder;
    }

    public static void releaseConnectionManager() {
        /*
         * if(connMan!=null) { connMan.close(); connMan=null; }
         */
    }

    private static HTTPResponse _invoke(URL url, HttpUriRequest request, String username, String password,
            long timeout, boolean redirect, String charset, String useragent, ProxyData proxy,
            lucee.commons.net.http.Header[] headers, Map<String, String> formfields) throws IOException {

        HttpClientBuilder builder = getHttpClientBuilder();

        // redirect
        if (redirect)
            builder.setRedirectStrategy(new DefaultRedirectStrategy());
        else
            builder.disableRedirectHandling();

        HttpHost hh = new HttpHost(url.getHost(), url.getPort());
        setHeader(request, headers);
        if (CollectionUtil.isEmpty(formfields))
            setContentType(request, charset);
        setFormFields(request, formfields, charset);
        setUserAgent(request, useragent);
        if (timeout > 0)
            Http.setTimeout(builder, TimeSpanImpl.fromMillis(timeout));
        HttpContext context = setCredentials(builder, hh, username, password, false);
        setProxy(builder, request, proxy);
        CloseableHttpClient client = builder.build();
        if (context == null)
            context = new BasicHttpContext();
        return new HTTPResponse4Impl(url, context, request, client.execute(request, context));
    }

    private static void setFormFields(HttpUriRequest request, Map<String, String> formfields, String charset)
            throws IOException {
        if (!CollectionUtil.isEmpty(formfields)) {
            if (!(request instanceof HttpPost))
                throw new IOException("form fields are only suppported for post request");
            HttpPost post = (HttpPost) request;
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            Iterator<Entry<String, String>> it = formfields.entrySet().iterator();
            Entry<String, String> e;
            while (it.hasNext()) {
                e = it.next();
                list.add(new BasicNameValuePair(e.getKey(), e.getValue()));
            }
            if (StringUtil.isEmpty(charset))
                charset = ((PageContextImpl) ThreadLocalPageContext.get()).getWebCharset().name();

            post.setEntity(new org.apache.http.client.entity.UrlEncodedFormEntity(list, charset));
        }
    }

    private static void setUserAgent(HttpMessage hm, String useragent) {
        if (useragent != null)
            hm.setHeader("User-Agent", useragent);
    }

    private static void setContentType(HttpMessage hm, String charset) {
        if (charset != null)
            hm.setHeader("Content-type", "text/html; charset=" + charset);
    }

    private static void setHeader(HttpMessage hm, lucee.commons.net.http.Header[] headers) {
        addHeader(hm, headers);
    }

    private static void addHeader(HttpMessage hm, lucee.commons.net.http.Header[] headers) {
        if (headers != null) {
            for (int i = 0; i < headers.length; i++)
                hm.addHeader(toHeader(headers[i]));
        }
    }

    public static BasicHttpContext setCredentials(HttpClientBuilder builder, HttpHost httpHost, String username,
            String password, boolean preAuth) {
        // set Username and Password
        if (!StringUtil.isEmpty(username, true)) {
            if (password == null)
                password = "";
            CredentialsProvider cp = new BasicCredentialsProvider();
            builder.setDefaultCredentialsProvider(cp);

            cp.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
                    new UsernamePasswordCredentials(username, password));

            BasicHttpContext httpContext = new BasicHttpContext();
            if (preAuth) {
                AuthCache authCache = new BasicAuthCache();
                authCache.put(httpHost, new BasicScheme());
                httpContext.setAttribute(ClientContext.AUTH_CACHE, authCache);
            }
            return httpContext;
        }
        return null;
    }

    public static void setNTCredentials(HttpClientBuilder builder, String username, String password,
            String workStation, String domain) {
        // set Username and Password
        if (!StringUtil.isEmpty(username, true)) {
            if (password == null)
                password = "";
            CredentialsProvider cp = new BasicCredentialsProvider();
            builder.setDefaultCredentialsProvider(cp);

            cp.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
                    new NTCredentials(username, password, workStation, domain));
        }
    }

    public static void setBody(HttpEntityEnclosingRequest req, Object body, String mimetype, String charset)
            throws IOException {
        if (body != null)
            req.setEntity(toHttpEntity(body, mimetype, charset));
    }

    public static void setProxy(HttpClientBuilder builder, HttpUriRequest request, ProxyData proxy) {
        // set Proxy
        if (ProxyDataImpl.isValid(proxy)) {
            HttpHost host = new HttpHost(proxy.getServer(), proxy.getPort() == -1 ? 80 : proxy.getPort());
            builder.setProxy(host);

            // username/password
            if (!StringUtil.isEmpty(proxy.getUsername())) {
                CredentialsProvider cp = new BasicCredentialsProvider();
                builder.setDefaultCredentialsProvider(cp);
                cp.setCredentials(new AuthScope(proxy.getServer(), proxy.getPort()),
                        new UsernamePasswordCredentials(proxy.getUsername(), proxy.getPassword()));
            }
        }
    }

    public static void addCookie(CookieStore cookieStore, String domain, String name, String value, String path,
            String charset) {
        if (ReqRspUtil.needEncoding(name, false))
            name = ReqRspUtil.encode(name, charset);
        if (ReqRspUtil.needEncoding(value, false))
            value = ReqRspUtil.encode(value, charset);
        BasicClientCookie cookie = new BasicClientCookie(name, value);
        if (!StringUtil.isEmpty(domain, true))
            cookie.setDomain(domain);
        if (!StringUtil.isEmpty(path, true))
            cookie.setPath(path);
        cookieStore.addCookie(cookie);
    }

    /**
     * convert input to HTTP Entity
     * 
     * @param value
     * @param mimetype
     *            not used for binary input
     * @param charset
     *            not used for binary input
     * @return
     * @throws IOException
     */
    private static HttpEntity toHttpEntity(Object value, String mimetype, String charset) throws IOException {
        if (value instanceof HttpEntity)
            return (HttpEntity) value;

        // content type
        ContentType ct = HTTPEngine.toContentType(mimetype, charset);
        try {
            if (value instanceof TemporaryStream) {
                if (ct != null)
                    return new TemporaryStreamHttpEntity((TemporaryStream) value, ct);
                return new TemporaryStreamHttpEntity((TemporaryStream) value, null);
            } else if (value instanceof InputStream) {
                if (ct != null)
                    return new ByteArrayEntity(IOUtil.toBytes((InputStream) value), ct);
                return new ByteArrayEntity(IOUtil.toBytes((InputStream) value));
            } else if (Decision.isCastableToBinary(value, false)) {
                if (ct != null)
                    return new ByteArrayEntity(Caster.toBinary(value), ct);
                return new ByteArrayEntity(Caster.toBinary(value));
            } else {
                boolean wasNull = false;
                if (ct == null) {
                    wasNull = true;
                    ct = ContentType.APPLICATION_OCTET_STREAM;
                }
                String str = Caster.toString(value);
                if (str.equals("<empty>")) {
                    return new EmptyHttpEntity(ct);
                }
                if (wasNull && !StringUtil.isEmpty(charset, true))
                    return new StringEntity(str, charset.trim());
                else
                    return new StringEntity(str, ct);
            }
        } catch (Exception e) {
            throw ExceptionUtil.toIOException(e);
        }
    }

    public static Entity getEmptyEntity(ContentType contentType) {
        return new EmptyHttpEntity(contentType);
    }

    public static Entity getByteArrayEntity(byte[] barr, ContentType contentType) {
        return new ByteArrayHttpEntity(barr, contentType);
    }

    public static Entity getTemporaryStreamEntity(TemporaryStream ts, ContentType contentType) {
        return new TemporaryStreamHttpEntity(ts, contentType);
    }

    public static Entity getResourceEntity(Resource res, ContentType contentType) {
        return new ResourceHttpEntity(res, contentType);
    }

}