gribbit.util.RequestBuilder.java Source code

Java tutorial

Introduction

Here is the source code for gribbit.util.RequestBuilder.java

Source

/**
 * This file is part of the Gribbit Web Framework.
 * 
 *     https://github.com/lukehutch/gribbit
 * 
 * @author Luke Hutchison
 * 
 * --
 * 
 * @license Apache 2.0 
 * 
 * Copyright 2015 Luke Hutchison
 *
 * 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 gribbit.util;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.commons.io.IOUtils;
import org.json.simple.JSONValue;

import io.netty.handler.codec.http.HttpResponseStatus;

public class RequestBuilder {

    /**
     * Make a GET or POST request, handling up to 6 redirects, and return the response. If isBinaryResponse is true,
     * returns a byte[] array, otherwise returns the response as a String.
     */
    private static Object makeRequest(String url, String[] keyValuePairs, boolean isGET, boolean isBinaryResponse,
            int redirDepth) {
        if (redirDepth > 6) {
            throw new IllegalArgumentException("Too many redirects");
        }
        HttpURLConnection connection = null;
        try {
            // Add the URL query params if this is a GET request
            String reqURL = isGET ? url + "?" + WebUtils.buildQueryString(keyValuePairs) : url;
            connection = (HttpURLConnection) new URL(reqURL).openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setInstanceFollowRedirects(false);
            connection.setRequestMethod(isGET ? "GET" : "POST");
            connection.setUseCaches(false);
            connection.setRequestProperty("User-Agent",
                    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) "
                            + "Chrome/43.0.2357.125 Safari/537.36");
            if (!isGET) {
                // Send the body if this is a POST request
                connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                connection.setRequestProperty("charset", "utf-8");
                String params = WebUtils.buildQueryString(keyValuePairs);
                connection.setRequestProperty("Content-Length", Integer.toString(params.length()));
                try (DataOutputStream w = new DataOutputStream(connection.getOutputStream())) {
                    w.writeBytes(params);
                    w.flush();
                }
            }
            if (connection.getResponseCode() == HttpResponseStatus.FOUND.code()) {
                // Follow a redirect. For safety, the params are not passed on, and the method is forced to GET.
                return makeRequest(connection.getHeaderField("Location"), /* keyValuePairs = */null, /* isGET = */
                        true, isBinaryResponse, redirDepth + 1);
            } else if (connection.getResponseCode() == HttpResponseStatus.OK.code()) {
                // For 200 OK, return the text of the response
                if (isBinaryResponse) {
                    ByteArrayOutputStream output = new ByteArrayOutputStream(32768);
                    IOUtils.copy(connection.getInputStream(), output);
                    return output.toByteArray();
                } else {
                    StringWriter writer = new StringWriter(1024);
                    IOUtils.copy(connection.getInputStream(), writer, "UTF-8");
                    return writer.toString();
                }
            } else {
                throw new IllegalArgumentException(
                        "Got non-OK HTTP response code: " + connection.getResponseCode());
            }
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    "Exception during " + (isGET ? "GET" : "POST") + " request: " + e.getMessage(), e);
        } finally {
            if (connection != null) {
                try {
                    connection.disconnect();
                } catch (Exception e) {
                }
            }
        }
    }

    /**
     * Make a GET or POST request, handling up to 6 redirects, and return the response. If isBinaryResponse is true,
     * returns a byte[] array, otherwise returns the response as a String.
     */
    private static Object makeRequest(String url, String[] keyValuePairs, boolean isGET, boolean isBinaryResponse) {
        return makeRequest(url, keyValuePairs, isGET, isBinaryResponse, 0);
    }

    /**
     * Send a POST request to a given URL with the given key-value POST parameters (with keys in the even indices
     * and values in the following odd indices), and parse the JSON result by mapping to a new object of the
     * requested response type.
     * 
     * @throws IllegalArgumentException
     *             if request could not be completed or JSON could not be mapped to the response type.
     */
    public static <T> T postToURLWithJSONResponse(Class<T> responseType, String url, String... keyValuePairs)
            throws IllegalArgumentException {
        String jsonStr = (String) makeRequest(url, keyValuePairs, /* isGET = */false, /* isBinaryResponse = */
                false);
        try {
            return JSONJackson.jsonToObject(jsonStr, responseType);
        } catch (Exception e) {
            throw new IllegalArgumentException("Could not parse JSON response: " + e.getMessage(), e);
        }
    }

    /**
     * Send a POST request to a given URL with the given key-value POST parameters (with keys in the even indices
     * and values in the following odd indices). Result is a json-simple object, see
     * https://code.google.com/p/json-simple/wiki/DecodingExamples
     * 
     * @throws IllegalArgumentException
     *             if request could not be completed or JSON could not be parsed.
     */
    public static Object postToURLWithJSONResponse(String url, String... keyValuePairs)
            throws IllegalArgumentException {
        String jsonStr = (String) makeRequest(url, keyValuePairs, /* isGET = */false, /* isBinaryResponse = */
                false);
        try {
            return JSONValue.parse(jsonStr);
        } catch (Exception e) {
            throw new IllegalArgumentException("Could not parse JSON response: " + e.getMessage(), e);
        }
    }

    /**
     * Send a POST request to a given URL with the given key-value POST parameters (with keys in the even indices
     * and values in the following odd indices). Returns the result as a string.
     */
    public static String postToURLWithStringResponse(String url, String... keyValuePairs)
            throws IllegalArgumentException {
        return (String) makeRequest(url, keyValuePairs, /* isGET = */false, /* isBinaryResponse = */false);
    }

    /**
     * Send a POST request to a given URL with the given key-value POST parameters. Returns the result as a byte[]
     * array.
     */
    public static byte[] postToURLWithBinaryResponse(String url, String... keyValuePairs)
            throws IllegalArgumentException {
        return (byte[]) makeRequest(url, keyValuePairs, /* isGET = */false, /* isBinaryResponse = */true);
    }

    /**
     * Send a GET request to a given URL with the given key-value URL parameters (with keys in the even indices and
     * values in the following odd indices), and parse the JSON result by mapping to a new object of the requested
     * response type.
     * 
     * @throws IllegalArgumentException
     *             if request could not be completed or JSON could not be mapped to the response type.
     */
    public static <T> T getFromURLWithJSONResponse(Class<T> responseType, String url, String... keyValuePairs)
            throws IllegalArgumentException {
        String jsonStr = (String) makeRequest(url, keyValuePairs, /* isGET = */true, /* isBinaryResponse = */
                false);
        try {
            return JSONJackson.jsonToObject(jsonStr, responseType);
        } catch (Exception e) {
            throw new IllegalArgumentException("Could not parse JSON response: " + e.getMessage(), e);
        }
    }

    /**
     * Send a GET request to a given URL with the given key-value URL parameters (with keys in the even indices and
     * values in the following odd indices). Result is a json-simple object, see
     * https://code.google.com/p/json-simple/wiki/DecodingExamples
     * 
     * @throws IllegalArgumentException
     *             if request could not be completed or JSON could not be parsed.
     */
    public static Object getFromURLWithJSONResponse(String url, String... keyValuePairs)
            throws IllegalArgumentException {
        String jsonStr = (String) makeRequest(url, keyValuePairs, /* isGET = */true, /* isBinaryResponse = */
                false);
        try {
            return JSONValue.parse(jsonStr);
        } catch (Exception e) {
            throw new IllegalArgumentException("Could not parse JSON response: " + e.getMessage(), e);
        }
    }

    /**
     * Send a POST request to a given URL with the given key-value URL parameters (with keys in the even indices and
     * values in the following odd indices). Returns the result as a string.
     */
    public static String getFromURLWithStringResponse(String url, String... keyValuePairs)
            throws IllegalArgumentException {
        return (String) makeRequest(url, keyValuePairs, /* isGET = */true, /* isBinaryResponse = */false);
    }

    /**
     * Send a GET request to a given URL with the given key-value URL parameters (with keys in the even indices and
     * values in the following odd indices). Returns the result as a byte[] array.
     */
    public static byte[] getFromURLWithBinaryResponse(String url, String... keyValuePairs)
            throws IllegalArgumentException {
        return (byte[]) makeRequest(url, keyValuePairs, /* isGET = */true, /* isBinaryResponse = */true);
    }
}