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

com.nesscomputing.httpclient.HttpClientRequest Maven / Gradle / Ivy

There is a newer version: 2.0.5
Show newest version
/**
 * Copyright (C) 2012 Ness Computing, Inc.
 *
 * 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.nesscomputing.httpclient;


import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.servlet.http.Cookie;

import org.apache.commons.lang3.StringUtils;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.nesscomputing.httpclient.internal.HttpClientBodySource;
import com.nesscomputing.httpclient.internal.HttpClientFactory;
import com.nesscomputing.httpclient.internal.HttpClientHeader;
import com.nesscomputing.httpclient.internal.HttpClientMethod;


/**
 * A request to a remote server. Composed step-by-step using a builder.
 */
public class HttpClientRequest
{
    private final HttpClientFactory httpClientFactory;

    private final HttpClientMethod httpMethod;
    private final URI url;
    private final HttpClientResponseHandler httpHandler;
    private List headers = Collections.emptyList();
    private List cookies = Collections.emptyList();
    private Map parameters = Collections.emptyMap();
    private String virtualHost = null;
    private int virtualPort = -1;
    private HttpClientBodySource httpBodySource = null;
    private Object content = null;
    private String contentType = null;
    private String contentEncoding = null;
    private List authProviders = null;

    private HttpClientRequest(final HttpClientFactory httpClientFactory,
                              final HttpClientMethod httpMethod,
                              final URI url,
                              final HttpClientResponseHandler httpHandler,
                              @Nonnull final List headers,
                              @Nonnull final List cookies,
                              @Nonnull final Map parameters,
                              final String virtualHost,
                              final int virtualPort,
                              @Nonnull final List authProviders,
                              final Object content,
                              final String contentType,
                              final String contentEncoding)
    {
        Preconditions.checkArgument(headers != null, "headers must not be null!");
        Preconditions.checkArgument(cookies != null, "cookies must not be null!");
        Preconditions.checkArgument(parameters != null, "parameters must not be null!");
        Preconditions.checkArgument(authProviders != null, "authProviders must not be null!");

        this.httpClientFactory = httpClientFactory;

        this.httpMethod = httpMethod;
        this.url = url;
        this.httpHandler = httpHandler;
        this.headers = Collections.unmodifiableList(headers);
        this.cookies = Collections.unmodifiableList(cookies);
        this.parameters = Collections.unmodifiableMap(parameters);

        this.virtualHost = virtualHost;
        this.virtualPort = virtualPort;

        this.authProviders = Collections.unmodifiableList(authProviders);

        this.content = content;
        this.contentType = contentType;
        this.contentEncoding = contentEncoding;

        if (content != null) {
            httpBodySource = httpClientFactory.getHttpBodySourceFor(content);
        }
        if (httpBodySource != null) {

            if (contentType != null) {
                httpBodySource.setContentType(contentType);
            }

            if (contentEncoding != null) {
                httpBodySource.setContentEncoding(contentEncoding);
            }
        }
    }

    public InputStream getContent() throws IOException
    {
        // Gee, thanks a million for an incredibly bad named method.
        return httpBodySource.getContent();
    }

    /**
     * @return the HTTP method for this request.
     */
    public HttpClientMethod getHttpMethod()
    {
        return httpMethod;
    }

    /**
     * @return the URI for this request.
     */
    public URI getUri()
    {
        return url;
    }

    /**
     * @return the Response handler object for this request.
     */
    public HttpClientResponseHandler getHttpHandler()
    {
        return httpHandler;
    }

    /**
     * @return a list of headers that are sent with this request.
     */
    public List getHeaders()
    {
        return headers;
    }

    /**
     * @return a list of Cookies that are sent with this request.
     */
    public List getCookies()
    {
        return cookies;
    }

    public Map getParameters()
    {
        return parameters;
    }

    /**
     * @return the virtual host name for this request.
     */
    public String getVirtualHost()
    {
        return virtualHost;
    }

    /**
     * @return the virtual host port for this request.
     */
    public int getVirtualPort()
    {
        return virtualPort;
    }

    /**
     * @return the authentication providers for this request.
     */
    public List getAuthProviders()
    {
        return authProviders;
    }

    /**
     * @return the source for the body content for POST and PUT requests.
     */
    public HttpClientBodySource getHttpBodySource()
    {
        return httpBodySource;
    }

    /**
     * Execute the HTTP request and return the result.
     */
    public T perform()
        throws IOException
    {
        return httpClientFactory.performRequest(this);
    }

    //
    // =========================================================
    //
    // Methods for recreating a builder from a request
    //
    // =========================================================
    //


    private Object getContentObject()
    {
        return content;
    }

    private String getContentType()
    {
        return contentType;
    }

    private String getContentEncoding()
    {
        return contentEncoding;
    }

    private HttpClientFactory getHttpClientFactory()
    {
        return httpClientFactory;
    }

    public static final class Builder
    {
        private final List headers = Lists.newArrayList();
        private final List cookies = Lists.newArrayList();
        private final Map parameters = Maps.newHashMap();

        private final HttpClientFactory httpClientFactory;
        private final HttpClientResponseHandler httpHandler;

        private URI url;
        private final HttpClientMethod httpMethod;
        private String virtualHost;
        private int virtualPort;

        private Object content;
        private String contentType;
        private String contentEncoding;

        private final List authProviders = Lists.newArrayList();

        public static  Builder fromRequest(final HttpClientRequest request)
        {
            return new Builder(request);
        }

         Builder(final HttpClientFactory httpClientFactory, final HttpClientMethod httpMethod, final URI url, final HttpClientResponseHandler httpHandler)
        {
            this.httpClientFactory = httpClientFactory;
            this.httpMethod = httpMethod;
            this.url = url;
            this.httpHandler = httpHandler;
        }

         Builder(final HttpClientRequest request)
        {
            this (request.getHttpClientFactory(), request.getHttpMethod(), request.getUri(), request.getHttpHandler());

            this.headers.addAll(request.getHeaders());
            this.cookies.addAll(request.getCookies());
            this.parameters.putAll(request.getParameters());
            this.authProviders.addAll(request.getAuthProviders());

            this.virtualHost = request.getVirtualHost();
            this.virtualPort = request.getVirtualPort();
            this.content = request.getContentObject();
            this.contentType = request.getContentType();
            this.contentEncoding = request.getContentEncoding();
        }

        public Builder setUrl(final URI url)
        {
            Preconditions.checkArgument(url != null, "URI must not be null!");
            this.url = url;

            return this;
        }

        /**
         * Add a header to the request.
         * @param header the header name
         * @param value the header value
         */
        public Builder addHeader(final String header, final String value)
        {
            Preconditions.checkArgument(header != null, "Header name must not be null!");
            Preconditions.checkArgument(value != null, "Header value must not be null!");

            headers.add(new HttpClientHeader(header, value));
            return this;
        }

        /**
         * Add a header to the request and remove all other existing headers.
         * @param header the header name
         * @param value the header value
         */
        public Builder replaceHeader(final String header, final String value)
        {
            for (Iterator it = headers.iterator(); it.hasNext(); ) {
                final HttpClientHeader oldHeader = it.next();
                if (StringUtils.equals(header, oldHeader.getName())) {
                    it.remove();
                }
            }
            return addHeader(header, value);
        }

        /**
         * @param cookie cookie to add to the request
         */
        public Builder addCookie(@Nonnull final Cookie cookie)
        {
            Preconditions.checkArgument(cookie != null, "Cookie must not be null!");

            cookies.add(cookie);
            return this;
        }

        /**
         * @param cookie cookie to add to the request
         */
        public Builder replaceCookie(@Nonnull final Cookie cookie)
        {
            for (Iterator it = cookies.iterator(); it.hasNext(); ) {
                final Cookie oldCookie = it.next();
                if (StringUtils.equals(cookie.getName(), oldCookie.getName())) {
                    it.remove();
                }
            }

            return addCookie(cookie);
        }

        /**
         * Context parameters for the HTTP request.
         */
        public Builder setParameter(final String key, final Object value)
        {
            Preconditions.checkArgument(key != null, "key must not be null!");

            parameters.put(key, value);
            return this;
        }



        /**
         * Set the virtual host for this request.
         *
         * @param virtualHost the host
         * @param virtualPort the port. Can be -1 to use the default port.
         */
        public Builder setVirtualHost(final String virtualHost, final int virtualPort)
        {
            this.virtualHost = virtualHost;
            this.virtualPort = virtualPort;
            return this;
        }

        /**
         * Set the content type sent with this request if it is a POST or PUT request.
         */
        public Builder setContentType(@Nonnull final String contentType)
        {
            if (contentType == null) {
                throw new IllegalArgumentException("Content type can not be null!");
            }

            this.contentType = contentType;

            return this;
        }

        /**
         * Set the content encoding sent with this request if it is a POST or PUT request.
         */
        public Builder setContentEncoding(@Nonnull final String contentEncoding)
        {
            if (contentEncoding == null) {
                throw new IllegalArgumentException("Content encoding can not be null!");
            }

            this.contentEncoding = contentEncoding;

            return this;
        }

        public Builder setContent(Multimap kvPairs, String encoding) throws UnsupportedEncodingException {
            StringBuilder sb = new StringBuilder();
            boolean first = true;

            for (Map.Entry entry : kvPairs.entries()) {
                String key = entry.getKey();
                String value = entry.getValue();

                if (!first) {
                    sb.append("&");
                } else {
                    first = false;
                }

                sb.append(URLEncoder.encode(key, encoding));
                sb.append("=");
                if (key != null) {
                    sb.append(URLEncoder.encode(value, encoding));
                }
            }

            setContentEncoding(encoding);
            setContent(sb.toString());
            return this;
        }

        /**
         * Create the content for a POST or PUT request from a String.
         */
        public Builder setContent(final String content)
        {
            this.content = content;
            return this;
        }

        /**
         * Create the content for a POST or PUT request from a byte array.
         */
        public Builder setContent(final byte [] content)
        {
            this.content = content;
            return this;
        }

        /**
         * Create the content for a POST or PUT request from an input stream.
         */
        public Builder setContent(final InputStream content)
        {
            this.content = content;
            return this;
        }

        /**
         * Add basic authentication information.
         * @param user Username to use when authentication is requested.
         * @param password Password to use when authentication is requested.
         */
        public Builder addBasicAuth(final String user, final String password)
        {
            return addAuth(HttpClientDefaultAuthProvider.forUser(user, password));
        }

        /**
         * @param authProvider a custom authentication provider to use when authentication is requested.
         */
        public Builder addAuth(final HttpClientAuthProvider authProvider)
        {
            authProviders.add(authProvider);
            return this;
        }

        /**
         * Create a HttpClientRequest from the builder. The object is disconnected from the builder and the builder can be reused.
         */
        public HttpClientRequest request()
        {
            final HttpClientRequest httpClientRequest = new HttpClientRequest(
                            httpClientFactory,
                            httpMethod,
                            url,
                            httpHandler,
                            headers,
                            cookies,
                            parameters,
                            virtualHost,
                            virtualPort,
                            authProviders,
                            content,
                            contentType,
                            contentEncoding);

            return httpClientRequest;
        }

        /**
         * Builds a HttpClientRequest from the builder an executes it in one go.
         * @return The return value of the request.
         * @throws IOException
         */
        public Type perform() throws IOException
        {
            return request().perform();
        }
    }

    @Override
    public String toString() {
        return String.format("HttpClientRequest [%s %s]", httpMethod, url);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy