- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-package com.github.kevinsawicki.http;
-
-import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
-import static java.net.HttpURLConnection.HTTP_CREATED;
-import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
-import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
-import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
-import static java.net.HttpURLConnection.HTTP_NOT_MODIFIED;
-import static java.net.HttpURLConnection.HTTP_OK;
-import static java.net.Proxy.Type.HTTP;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.Flushable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintStream;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.net.HttpURLConnection;
-import java.net.InetSocketAddress;
-import java.net.MalformedURLException;
-import java.net.Proxy;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.security.AccessController;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.PrivilegedAction;
-import java.security.SecureRandom;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.zip.GZIPInputStream;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-import android.text.TextUtils;
-
-/**
- * A fluid interface for making HTTP requests using an underlying
- * {@link HttpURLConnection} (or sub-class).
- *
- * Each instance supports making a single request and cannot be reused for
- * further requests.
- */
-public class HttpRequest {
-
- /**
- * 'UTF-8' charset name
- */
- public static final String CHARSET_UTF8 = "UTF-8";
-
- /**
- * 'ISO-8859-1' charset name
- */
- public static final String CHARSET_LATIN1 = "ISO-8859-1";
-
- /**
- * 'application/x-www-form-urlencoded' content type header value
- */
- public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
-
- /**
- * 'application/json' content type header value
- */
- public static final String CONTENT_TYPE_JSON = "application/json";
-
- /**
- * 'gzip' encoding header value
- */
- public static final String ENCODING_GZIP = "gzip";
-
- /**
- * 'Accept' header name
- */
- public static final String HEADER_ACCEPT = "Accept";
-
- /**
- * 'Accept-Charset' header name
- */
- public static final String HEADER_ACCEPT_CHARSET = "Accept-Charset";
-
- /**
- * 'Accept-Encoding' header name
- */
- public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
-
- /**
- * 'Authorization' header name
- */
- public static final String HEADER_AUTHORIZATION = "Authorization";
-
- /**
- * 'Cache-Control' header name
- */
- public static final String HEADER_CACHE_CONTROL = "Cache-Control";
-
- /**
- * 'Content-Encoding' header name
- */
- public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
-
- /**
- * 'Content-Length' header name
- */
- public static final String HEADER_CONTENT_LENGTH = "Content-Length";
-
- /**
- * 'Content-Type' header name
- */
- public static final String HEADER_CONTENT_TYPE = "Content-Type";
-
- /**
- * 'Date' header name
- */
- public static final String HEADER_DATE = "Date";
-
- /**
- * 'ETag' header name
- */
- public static final String HEADER_ETAG = "ETag";
-
- /**
- * 'Expires' header name
- */
- public static final String HEADER_EXPIRES = "Expires";
-
- /**
- * 'If-None-Match' header name
- */
- public static final String HEADER_IF_NONE_MATCH = "If-None-Match";
-
- /**
- * 'Last-Modified' header name
- */
- public static final String HEADER_LAST_MODIFIED = "Last-Modified";
-
- /**
- * 'Location' header name
- */
- public static final String HEADER_LOCATION = "Location";
-
- /**
- * 'Proxy-Authorization' header name
- */
- public static final String HEADER_PROXY_AUTHORIZATION = "Proxy-Authorization";
-
- /**
- * 'Referer' header name
- */
- public static final String HEADER_REFERER = "Referer";
-
- /**
- * 'Server' header name
- */
- public static final String HEADER_SERVER = "Server";
-
- /**
- * 'User-Agent' header name
- */
- public static final String HEADER_USER_AGENT = "User-Agent";
-
- /**
- * 'DELETE' request method
- */
- public static final String METHOD_DELETE = "DELETE";
-
- /**
- * 'GET' request method
- */
- public static final String METHOD_GET = "GET";
-
- /**
- * 'HEAD' request method
- */
- public static final String METHOD_HEAD = "HEAD";
-
- /**
- * 'OPTIONS' options method
- */
- public static final String METHOD_OPTIONS = "OPTIONS";
-
- /**
- * 'POST' request method
- */
- public static final String METHOD_POST = "POST";
-
- /**
- * 'PATCH' request method
- */
- public static final String METHOD_PATCH = "PATCH";
-
- /**
- * 'PUT' request method
- */
- public static final String METHOD_PUT = "PUT";
-
- /**
- * 'TRACE' request method
- */
- public static final String METHOD_TRACE = "TRACE";
-
- /**
- * 'charset' header value parameter
- */
- public static final String PARAM_CHARSET = "charset";
-
- public static final String CERT_MODE_DEFAULT = "default";
-
- public static final String CERT_MODE_PINNED = "pinned";
-
- public static final String CERT_MODE_TRUSTALL = "trustall";
-
- private static final String BOUNDARY = "00content0boundary00";
-
- private static final String CONTENT_TYPE_MULTIPART = "multipart/form-data; boundary="
- + BOUNDARY;
-
- private static final String CRLF = "\r\n";
-
- private static final String[] EMPTY_STRINGS = new String[0];
-
- private static SSLSocketFactory SOCKET_FACTORY;
-
- private static String CURRENT_CERT_MODE = CERT_MODE_DEFAULT;
-
- private static ArrayList PINNED_CERTS;
-
- private static HostnameVerifier HOSTNAME_VERIFIER;
-
- private static String getValidCharset(final String charset) {
- if (charset != null && charset.length() > 0)
- return charset;
- else
- return CHARSET_UTF8;
- }
-
- /**
- * Configure SSL cert handling for all future HTTPS connections
- *
- * @param mode
- */
- public static void setSSLCertMode(String mode) {
- try {
- if (mode == CERT_MODE_TRUSTALL) {
- SOCKET_FACTORY = createSocketFactory(getNoopTrustManagers());
- HOSTNAME_VERIFIER = getTrustedVerifier();
- } else if (mode == CERT_MODE_PINNED) {
- SOCKET_FACTORY = createSocketFactory(getPinnedTrustManagers());
- HOSTNAME_VERIFIER = null;
- } else {
- SOCKET_FACTORY = null;
- HOSTNAME_VERIFIER = null;
- }
-
- CURRENT_CERT_MODE = mode;
- } catch(IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- private static TrustManager[] getPinnedTrustManagers() throws IOException {
- if (PINNED_CERTS == null) {
- throw new IOException("You must add at least 1 certificate in order to pin to certificates");
- }
-
- try {
- String keyStoreType = KeyStore.getDefaultType();
- KeyStore keyStore = KeyStore.getInstance(keyStoreType);
- keyStore.load(null, null);
-
- for (int i = 0; i < PINNED_CERTS.size(); i++) {
- keyStore.setCertificateEntry("CA" + i, PINNED_CERTS.get(i));
- }
-
- // Create a TrustManager that trusts the CAs in our KeyStore
- String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
- tmf.init(keyStore);
-
- return tmf.getTrustManagers();
- } catch (GeneralSecurityException e) {
- IOException ioException = new IOException("Security exception configuring SSL trust managers");
- ioException.initCause(e);
- throw new HttpRequestException(ioException);
- }
- }
-
- private static TrustManager[] getNoopTrustManagers() {
- return new TrustManager[] { new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
-
- public void checkClientTrusted(X509Certificate[] chain, String authType) {
- // Intentionally left blank
- }
-
- public void checkServerTrusted(X509Certificate[] chain, String authType) {
- // Intentionally left blank
- }
- }};
- }
-
- private static SSLSocketFactory createSocketFactory(TrustManager[] trustManagers)
- throws HttpRequestException {
- try {
- SSLContext context = SSLContext.getInstance("TLS");
- context.init(keyManagers, trustManagers, new SecureRandom());
-
- if (android.os.Build.VERSION.SDK_INT < 20) {
- return new TLSSocketFactory(context);
- } else {
- return context.getSocketFactory();
- }
- } catch (GeneralSecurityException e) {
- IOException ioException = new IOException("Security exception configuring SSL context");
- ioException.initCause(e);
- throw new HttpRequestException(ioException);
- }
- }
-
- private static HostnameVerifier getTrustedVerifier() {
- return new HostnameVerifier() {
- public boolean verify(String hostname, SSLSession session) {
- return true;
- }
- };
- }
-
- private static StringBuilder addPathSeparator(final String baseUrl,
- final StringBuilder result) {
- // Add trailing slash if the base URL doesn't have any path segments.
- //
- // The following test is checking for the last slash not being part of
- // the protocol to host separator: '://'.
- if (baseUrl.indexOf(':') + 2 == baseUrl.lastIndexOf('/'))
- result.append('/');
- return result;
- }
-
- private static StringBuilder addParamPrefix(final String baseUrl,
- final StringBuilder result) {
- // Add '?' if missing and add '&' if params already exist in base url
- final int queryStart = baseUrl.indexOf('?');
- final int lastChar = result.length() - 1;
- if (queryStart == -1)
- result.append('?');
- else if (queryStart < lastChar && baseUrl.charAt(lastChar) != '&')
- result.append('&');
- return result;
- }
-
- private static StringBuilder addParam(final Object key, Object value,
- final StringBuilder result) throws HttpRequestException {
- return addParam(key, value, result, CHARSET_UTF8);
- }
-
- private static StringBuilder addParam(final Object key, Object value,
- final StringBuilder result, String charset) throws HttpRequestException {
- if (value != null && value.getClass().isArray())
- value = arrayToList(value);
-
- try {
- if (value instanceof Iterable>) {
- Iterator> iterator = ((Iterable>) value).iterator();
- while (iterator.hasNext()) {
- result.append(URLEncoder.encode(key.toString(), charset));
- result.append("[]=");
- Object element = iterator.next();
- if (element != null)
- result.append(URLEncoder.encode(element.toString(), charset));
- if (iterator.hasNext())
- result.append("&");
- }
- } else {
- result.append(URLEncoder.encode(key.toString(), charset));
- result.append("=");
- if (value != null)
- result.append(URLEncoder.encode(value.toString(), charset));
- }
- } catch (UnsupportedEncodingException e) {
- throw new HttpRequestException(e);
- }
-
- return result;
- }
-
- /**
- * Creates {@link HttpURLConnection HTTP connections} for
- * {@link URL urls}.
- */
- public interface ConnectionFactory {
- /**
- * Open an {@link HttpURLConnection} for the specified {@link URL}.
- *
- * @throws IOException
- */
- HttpURLConnection create(URL url) throws IOException;
-
- /**
- * Open an {@link HttpURLConnection} for the specified {@link URL}
- * and {@link Proxy}.
- *
- * @throws IOException
- */
- HttpURLConnection create(URL url, Proxy proxy) throws IOException;
-
- /**
- * A {@link ConnectionFactory} which uses the built-in
- * {@link URL#openConnection()}
- */
- ConnectionFactory DEFAULT = new OkConnectionFactory();
- }
-
- private static ConnectionFactory CONNECTION_FACTORY = ConnectionFactory.DEFAULT;
-
- /**
- * Specify the {@link ConnectionFactory} used to create new requests.
- */
- public static void setConnectionFactory(final ConnectionFactory connectionFactory) {
- if (connectionFactory == null)
- CONNECTION_FACTORY = ConnectionFactory.DEFAULT;
- else
- CONNECTION_FACTORY = connectionFactory;
- }
-
-
- /**
- * Add a certificate to test against when using ssl pinning.
- *
- * @param ca
- * The Certificate to add
- * @throws GeneralSecurityException
- * @throws IOException
- */
- public static void addCert(Certificate ca) throws GeneralSecurityException, IOException {
- if (PINNED_CERTS == null) {
- PINNED_CERTS = new ArrayList();
- }
-
- PINNED_CERTS.add(ca);
-
- if (CURRENT_CERT_MODE == CERT_MODE_PINNED) {
- SOCKET_FACTORY = createSocketFactory(getPinnedTrustManagers());
- }
- }
-
- /**
- * Add a certificate to test against when using ssl pinning.
- *
- * @param in
- * An InputStream to read a certificate from
- * @throws GeneralSecurityException
- * @throws IOException
- */
- public static void addCert(InputStream in) throws GeneralSecurityException, IOException {
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- Certificate ca;
- try {
- ca = cf.generateCertificate(in);
- addCert(ca);
- } finally {
- in.close();
- }
- }
-
- /**
- * Clear certs which were added to test against when using ssl pinning.
- */
- public static void clearCerts() {
- PINNED_CERTS = null;
- }
-
- /**
- * Callback interface for reporting upload progress for a request.
- */
- public interface UploadProgress {
- /**
- * Callback invoked as data is uploaded by the request.
- *
- * @param uploaded The number of bytes already uploaded
- * @param total The total number of bytes that will be uploaded or -1 if
- * the length is unknown.
- */
- void onUpload(long uploaded, long total);
-
- UploadProgress DEFAULT = new UploadProgress() {
- public void onUpload(long uploaded, long total) {
- }
- };
- }
-
- /**
- *
- * Encodes and decodes to and from Base64 notation.
- *
- *
- * I am placing this code in the Public Domain. Do with it as you will. This
- * software comes with no guarantees or warranties but with plenty of
- * well-wishing instead! Please visit http://iharder.net/base64 periodically
- * to check for updates or to contribute improvements.
- *
- *
- * @author Robert Harder
- * @author rob@iharder.net
- * @version 2.3.7
- */
- public static class Base64 {
-
- /** The equals sign (=) as a byte. */
- private final static byte EQUALS_SIGN = (byte) '=';
-
- /** Preferred encoding. */
- private final static String PREFERRED_ENCODING = "US-ASCII";
-
- /** The 64 valid Base64 values. */
- private final static byte[] _STANDARD_ALPHABET = { (byte) 'A', (byte) 'B',
- (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H',
- (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N',
- (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T',
- (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
- (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
- (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l',
- (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r',
- (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x',
- (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
- (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9',
- (byte) '+', (byte) '/' };
-
- /** Defeats instantiation. */
- private Base64() {
- }
-
- /**
- *
- * Encodes up to three bytes of the array source and writes the
- * resulting four Base64 bytes to destination . The source and
- * destination arrays can be manipulated anywhere along their length by
- * specifying srcOffset and destOffset . This method
- * does not check to make sure your arrays are large enough to accomodate
- * srcOffset + 3 for the source array or
- * destOffset + 4 for the destination array. The
- * actual number of significant bytes in your array is given by
- * numSigBytes .
- *
- *
- * This is the lowest level of the encoding methods with all possible
- * parameters.
- *
- *
- * @param source
- * the array to convert
- * @param srcOffset
- * the index where conversion begins
- * @param numSigBytes
- * the number of significant bytes in your array
- * @param destination
- * the array to hold the conversion
- * @param destOffset
- * the index where output will be put
- * @return the destination array
- * @since 1.3
- */
- private static byte[] encode3to4(byte[] source, int srcOffset,
- int numSigBytes, byte[] destination, int destOffset) {
-
- byte[] ALPHABET = _STANDARD_ALPHABET;
-
- int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
- | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
- | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
-
- switch (numSigBytes) {
- case 3:
- destination[destOffset] = ALPHABET[(inBuff >>> 18)];
- destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
- destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
- destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];
- return destination;
-
- case 2:
- destination[destOffset] = ALPHABET[(inBuff >>> 18)];
- destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
- destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
- destination[destOffset + 3] = EQUALS_SIGN;
- return destination;
-
- case 1:
- destination[destOffset] = ALPHABET[(inBuff >>> 18)];
- destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
- destination[destOffset + 2] = EQUALS_SIGN;
- destination[destOffset + 3] = EQUALS_SIGN;
- return destination;
-
- default:
- return destination;
- }
- }
-
- /**
- * Encode string as a byte array in Base64 annotation.
- *
- * @param string
- * @return The Base64-encoded data as a string
- */
- public static String encode(String string) {
- byte[] bytes;
- try {
- bytes = string.getBytes(PREFERRED_ENCODING);
- } catch (UnsupportedEncodingException e) {
- bytes = string.getBytes();
- }
- return encodeBytes(bytes);
- }
-
- /**
- * Encodes a byte array into Base64 notation.
- *
- * @param source
- * The data to convert
- * @return The Base64-encoded data as a String
- * @throws NullPointerException
- * if source array is null
- * @throws IllegalArgumentException
- * if source array, offset, or length are invalid
- * @since 2.0
- */
- public static String encodeBytes(byte[] source) {
- return encodeBytes(source, 0, source.length);
- }
-
- /**
- * Encodes a byte array into Base64 notation.
- *
- * @param source
- * The data to convert
- * @param off
- * Offset in array where conversion should begin
- * @param len
- * Length of data to convert
- * @return The Base64-encoded data as a String
- * @throws NullPointerException
- * if source array is null
- * @throws IllegalArgumentException
- * if source array, offset, or length are invalid
- * @since 2.0
- */
- public static String encodeBytes(byte[] source, int off, int len) {
- byte[] encoded = encodeBytesToBytes(source, off, len);
- try {
- return new String(encoded, PREFERRED_ENCODING);
- } catch (UnsupportedEncodingException uue) {
- return new String(encoded);
- }
- }
-
- /**
- * Similar to {@link #encodeBytes(byte[], int, int)} but returns a byte
- * array instead of instantiating a String. This is more efficient if you're
- * working with I/O streams and have large data sets to encode.
- *
- *
- * @param source
- * The data to convert
- * @param off
- * Offset in array where conversion should begin
- * @param len
- * Length of data to convert
- * @return The Base64-encoded data as a String if there is an error
- * @throws NullPointerException
- * if source array is null
- * @throws IllegalArgumentException
- * if source array, offset, or length are invalid
- * @since 2.3.1
- */
- public static byte[] encodeBytesToBytes(byte[] source, int off, int len) {
-
- if (source == null)
- throw new NullPointerException("Cannot serialize a null array.");
-
- if (off < 0)
- throw new IllegalArgumentException("Cannot have negative offset: "
- + off);
-
- if (len < 0)
- throw new IllegalArgumentException("Cannot have length offset: " + len);
-
- if (off + len > source.length)
- throw new IllegalArgumentException(
- String
- .format(
- "Cannot have offset of %d and length of %d with array of length %d",
- off, len, source.length));
-
- // Bytes needed for actual encoding
- int encLen = (len / 3) * 4 + (len % 3 > 0 ? 4 : 0);
-
- byte[] outBuff = new byte[encLen];
-
- int d = 0;
- int e = 0;
- int len2 = len - 2;
- for (; d < len2; d += 3, e += 4)
- encode3to4(source, d + off, 3, outBuff, e);
-
- if (d < len) {
- encode3to4(source, d + off, len - d, outBuff, e);
- e += 4;
- }
-
- if (e <= outBuff.length - 1) {
- byte[] finalOut = new byte[e];
- System.arraycopy(outBuff, 0, finalOut, 0, e);
- return finalOut;
- } else
- return outBuff;
- }
- }
-
- /**
- * HTTP request exception whose cause is always an {@link IOException}
- */
- public static class HttpRequestException extends RuntimeException {
-
- private static final long serialVersionUID = -1170466989781746231L;
-
- /**
- * Create a new HttpRequestException with the given cause
- *
- * @param cause
- */
- public HttpRequestException(final IOException cause) {
- super(cause);
- }
-
- /**
- * Get {@link IOException} that triggered this request exception
- *
- * @return {@link IOException} cause
- */
- @Override
- public IOException getCause() {
- return (IOException) super.getCause();
- }
- }
-
- /**
- * Operation that handles executing a callback once complete and handling
- * nested exceptions
- *
- * @param
- */
- protected static abstract class Operation implements Callable {
-
- /**
- * Run operation
- *
- * @return result
- * @throws HttpRequestException
- * @throws IOException
- */
- protected abstract V run() throws HttpRequestException, IOException;
-
- /**
- * Operation complete callback
- *
- * @throws IOException
- */
- protected abstract void done() throws IOException;
-
- public V call() throws HttpRequestException {
- boolean thrown = false;
- try {
- return run();
- } catch (HttpRequestException e) {
- thrown = true;
- throw e;
- } catch (IOException e) {
- thrown = true;
- throw new HttpRequestException(e);
- } finally {
- try {
- done();
- } catch (IOException e) {
- if (!thrown)
- throw new HttpRequestException(e);
- }
- }
- }
- }
-
- /**
- * Class that ensures a {@link Closeable} gets closed with proper exception
- * handling.
- *
- * @param
- */
- protected static abstract class CloseOperation extends Operation {
-
- private final Closeable closeable;
-
- private final boolean ignoreCloseExceptions;
-
- /**
- * Create closer for operation
- *
- * @param closeable
- * @param ignoreCloseExceptions
- */
- protected CloseOperation(final Closeable closeable,
- final boolean ignoreCloseExceptions) {
- this.closeable = closeable;
- this.ignoreCloseExceptions = ignoreCloseExceptions;
- }
-
- @Override
- protected void done() throws IOException {
- if (closeable instanceof Flushable)
- ((Flushable) closeable).flush();
- if (ignoreCloseExceptions)
- try {
- closeable.close();
- } catch (IOException e) {
- // Ignored
- }
- else
- closeable.close();
- }
- }
-
- /**
- * Class that and ensures a {@link Flushable} gets flushed with proper
- * exception handling.
- *
- * @param
- */
- protected static abstract class FlushOperation extends Operation {
-
- private final Flushable flushable;
-
- /**
- * Create flush operation
- *
- * @param flushable
- */
- protected FlushOperation(final Flushable flushable) {
- this.flushable = flushable;
- }
-
- @Override
- protected void done() throws IOException {
- flushable.flush();
- }
- }
-
- /**
- * Request output stream
- */
- public static class RequestOutputStream extends BufferedOutputStream {
-
- private final CharsetEncoder encoder;
-
- /**
- * Create request output stream
- *
- * @param stream
- * @param charset
- * @param bufferSize
- */
- public RequestOutputStream(final OutputStream stream, final String charset,
- final int bufferSize) {
- super(stream, bufferSize);
-
- encoder = Charset.forName(getValidCharset(charset)).newEncoder();
- }
-
- /**
- * Write string to stream
- *
- * @param value
- * @return this stream
- * @throws IOException
- */
- public RequestOutputStream write(final String value) throws IOException {
- final ByteBuffer bytes = encoder.encode(CharBuffer.wrap(value));
-
- super.write(bytes.array(), 0, bytes.limit());
-
- return this;
- }
- }
-
- /**
- * Represents array of any type as list of objects so we can easily iterate over it
- * @param array of elements
- * @return list with the same elements
- */
- private static List arrayToList(final Object array) {
- if (array instanceof Object[])
- return Arrays.asList((Object[]) array);
-
- List result = new ArrayList();
- // Arrays of the primitive types can't be cast to array of Object, so this:
- if (array instanceof int[])
- for (int value : (int[]) array) result.add(value);
- else if (array instanceof boolean[])
- for (boolean value : (boolean[]) array) result.add(value);
- else if (array instanceof long[])
- for (long value : (long[]) array) result.add(value);
- else if (array instanceof float[])
- for (float value : (float[]) array) result.add(value);
- else if (array instanceof double[])
- for (double value : (double[]) array) result.add(value);
- else if (array instanceof short[])
- for (short value : (short[]) array) result.add(value);
- else if (array instanceof byte[])
- for (byte value : (byte[]) array) result.add(value);
- else if (array instanceof char[])
- for (char value : (char[]) array) result.add(value);
- return result;
- }
-
- /**
- * Encode the given URL as an ASCII {@link String}
- *
- * This method ensures the path and query segments of the URL are properly
- * encoded such as ' ' characters being encoded to '%20' or any UTF-8
- * characters that are non-ASCII. No encoding of URLs is done by default by
- * the {@link HttpRequest} constructors and so if URL encoding is needed this
- * method should be called before calling the {@link HttpRequest} constructor.
- *
- * @param url
- * @return encoded URL
- * @throws HttpRequestException
- */
- public static String encode(final CharSequence url)
- throws HttpRequestException {
- URL parsed;
- try {
- parsed = new URL(url.toString());
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
-
- String host = parsed.getHost();
- int port = parsed.getPort();
- if (port != -1)
- host = host + ':' + Integer.toString(port);
-
- try {
- String encoded = new URI(parsed.getProtocol(), host, parsed.getPath(),
- parsed.getQuery(), null).toASCIIString();
- int paramsStart = encoded.indexOf('?');
- if (paramsStart > 0 && paramsStart + 1 < encoded.length())
- encoded = encoded.substring(0, paramsStart + 1)
- + encoded.substring(paramsStart + 1).replace("+", "%2B");
- return encoded;
- } catch (URISyntaxException e) {
- IOException io = new IOException("Parsing URI failed");
- io.initCause(e);
- throw new HttpRequestException(io);
- }
- }
-
- /**
- * Append given map as query parameters to the base URL
- *
- * Each map entry's key will be a parameter name and the value's
- * {@link Object#toString()} will be the parameter value.
- *
- * @param url
- * @param params
- * @return URL with appended query params
- */
- public static String append(final CharSequence url, final Map, ?> params) {
- final String baseUrl = url.toString();
- if (params == null || params.isEmpty())
- return baseUrl;
-
- final StringBuilder result = new StringBuilder(baseUrl);
-
- addPathSeparator(baseUrl, result);
- addParamPrefix(baseUrl, result);
-
- Entry, ?> entry;
- Iterator> iterator = params.entrySet().iterator();
- entry = (Entry, ?>) iterator.next();
- addParam(entry.getKey().toString(), entry.getValue(), result);
-
- while (iterator.hasNext()) {
- result.append('&');
- entry = (Entry, ?>) iterator.next();
- addParam(entry.getKey().toString(), entry.getValue(), result);
- }
-
- return result.toString();
- }
-
- /**
- * Append given name/value pairs as query parameters to the base URL
- *
- * The params argument is interpreted as a sequence of name/value pairs so the
- * given number of params must be divisible by 2.
- *
- * @param url
- * @param params
- * name/value pairs
- * @return URL with appended query params
- */
- public static String append(final CharSequence url, final Object... params) {
- final String baseUrl = url.toString();
- if (params == null || params.length == 0)
- return baseUrl;
-
- if (params.length % 2 != 0)
- throw new IllegalArgumentException(
- "Must specify an even number of parameter names/values");
-
- final StringBuilder result = new StringBuilder(baseUrl);
-
- addPathSeparator(baseUrl, result);
- addParamPrefix(baseUrl, result);
-
- addParam(params[0], params[1], result);
-
- for (int i = 2; i < params.length; i += 2) {
- result.append('&');
- addParam(params[i], params[i + 1], result);
- }
-
- return result.toString();
- }
-
- /**
- * Start a 'GET' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest get(final CharSequence url)
- throws HttpRequestException {
- return new HttpRequest(url, METHOD_GET);
- }
-
- /**
- * Start a 'GET' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest get(final URL url) throws HttpRequestException {
- return new HttpRequest(url, METHOD_GET);
- }
-
- /**
- * Start a 'GET' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param params
- * The query parameters to include as part of the baseUrl
- * @param encode
- * true to encode the full URL
- *
- * @see #append(CharSequence, Map)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest get(final CharSequence baseUrl,
- final Map, ?> params, final boolean encode) {
- String url = append(baseUrl, params);
- return get(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'GET' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param encode
- * true to encode the full URL
- * @param params
- * the name/value query parameter pairs to include as part of the
- * baseUrl
- *
- * @see #append(CharSequence, Object...)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest get(final CharSequence baseUrl,
- final boolean encode, final Object... params) {
- String url = append(baseUrl, params);
- return get(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'POST' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest post(final CharSequence url)
- throws HttpRequestException {
- return new HttpRequest(url, METHOD_POST);
- }
-
- /**
- * Start a 'POST' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest post(final URL url) throws HttpRequestException {
- return new HttpRequest(url, METHOD_POST);
- }
-
- /**
- * Start a 'POST' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param params
- * the query parameters to include as part of the baseUrl
- * @param encode
- * true to encode the full URL
- *
- * @see #append(CharSequence, Map)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest post(final CharSequence baseUrl,
- final Map, ?> params, final boolean encode) {
- String url = append(baseUrl, params);
- return post(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'POST' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param encode
- * true to encode the full URL
- * @param params
- * the name/value query parameter pairs to include as part of the
- * baseUrl
- *
- * @see #append(CharSequence, Object...)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest post(final CharSequence baseUrl,
- final boolean encode, final Object... params) {
- String url = append(baseUrl, params);
- return post(encode ? encode(url) : url);
- }
-
-/**
- * Start a 'PATCH' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest patch(final CharSequence url)
- throws HttpRequestException {
- return new HttpRequest(url, METHOD_PATCH);
- }
-
- /**
- * Start a 'PATCH' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest patch(final URL url) throws HttpRequestException {
- return new HttpRequest(url, METHOD_PATCH);
- }
-
- /**
- * Start a 'PATCH' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param params
- * the query parameters to include as part of the baseUrl
- * @param encode
- * true to encode the full URL
- *
- * @see #append(CharSequence, Map)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest patch(final CharSequence baseUrl,
- final Map, ?> params, final boolean encode) {
- String url = append(baseUrl, params);
- return patch(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'PATCH' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param encode
- * true to encode the full URL
- * @param params
- * the name/value query parameter pairs to include as part of the
- * baseUrl
- *
- * @see #append(CharSequence, Object...)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest patch(final CharSequence baseUrl,
- final boolean encode, final Object... params) {
- String url = append(baseUrl, params);
- return patch(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'PUT' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest put(final CharSequence url)
- throws HttpRequestException {
- return new HttpRequest(url, METHOD_PUT);
- }
-
- /**
- * Start a 'PUT' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest put(final URL url) throws HttpRequestException {
- return new HttpRequest(url, METHOD_PUT);
- }
-
- /**
- * Start a 'PUT' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param params
- * the query parameters to include as part of the baseUrl
- * @param encode
- * true to encode the full URL
- *
- * @see #append(CharSequence, Map)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest put(final CharSequence baseUrl,
- final Map, ?> params, final boolean encode) {
- String url = append(baseUrl, params);
- return put(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'PUT' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param encode
- * true to encode the full URL
- * @param params
- * the name/value query parameter pairs to include as part of the
- * baseUrl
- *
- * @see #append(CharSequence, Object...)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest put(final CharSequence baseUrl,
- final boolean encode, final Object... params) {
- String url = append(baseUrl, params);
- return put(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'DELETE' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest delete(final CharSequence url)
- throws HttpRequestException {
- return new HttpRequest(url, METHOD_DELETE);
- }
-
- /**
- * Start a 'DELETE' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest delete(final URL url) throws HttpRequestException {
- return new HttpRequest(url, METHOD_DELETE);
- }
-
- /**
- * Start a 'DELETE' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param params
- * The query parameters to include as part of the baseUrl
- * @param encode
- * true to encode the full URL
- *
- * @see #append(CharSequence, Map)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest delete(final CharSequence baseUrl,
- final Map, ?> params, final boolean encode) {
- String url = append(baseUrl, params);
- return delete(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'DELETE' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param encode
- * true to encode the full URL
- * @param params
- * the name/value query parameter pairs to include as part of the
- * baseUrl
- *
- * @see #append(CharSequence, Object...)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest delete(final CharSequence baseUrl,
- final boolean encode, final Object... params) {
- String url = append(baseUrl, params);
- return delete(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'HEAD' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest head(final CharSequence url)
- throws HttpRequestException {
- return new HttpRequest(url, METHOD_HEAD);
- }
-
- /**
- * Start a 'HEAD' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest head(final URL url) throws HttpRequestException {
- return new HttpRequest(url, METHOD_HEAD);
- }
-
- /**
- * Start a 'HEAD' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param params
- * The query parameters to include as part of the baseUrl
- * @param encode
- * true to encode the full URL
- *
- * @see #append(CharSequence, Map)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest head(final CharSequence baseUrl,
- final Map, ?> params, final boolean encode) {
- String url = append(baseUrl, params);
- return head(encode ? encode(url) : url);
- }
-
- /**
- * Start a 'GET' request to the given URL along with the query params
- *
- * @param baseUrl
- * @param encode
- * true to encode the full URL
- * @param params
- * the name/value query parameter pairs to include as part of the
- * baseUrl
- *
- * @see #append(CharSequence, Object...)
- * @see #encode(CharSequence)
- *
- * @return request
- */
- public static HttpRequest head(final CharSequence baseUrl,
- final boolean encode, final Object... params) {
- String url = append(baseUrl, params);
- return head(encode ? encode(url) : url);
- }
-
- /**
- * Start an 'OPTIONS' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest options(final CharSequence url)
- throws HttpRequestException {
- return new HttpRequest(url, METHOD_OPTIONS);
- }
-
- /**
- * Start an 'OPTIONS' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest options(final URL url) throws HttpRequestException {
- return new HttpRequest(url, METHOD_OPTIONS);
- }
-
- /**
- * Start a 'TRACE' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest trace(final CharSequence url)
- throws HttpRequestException {
- return new HttpRequest(url, METHOD_TRACE);
- }
-
- /**
- * Start a 'TRACE' request to the given URL
- *
- * @param url
- * @return request
- * @throws HttpRequestException
- */
- public static HttpRequest trace(final URL url) throws HttpRequestException {
- return new HttpRequest(url, METHOD_TRACE);
- }
-
- /**
- * Set the 'http.keepAlive' property to the given value.
- *
- * This setting will apply to all requests.
- *
- * @param keepAlive
- */
- public static void keepAlive(final boolean keepAlive) {
- setProperty("http.keepAlive", Boolean.toString(keepAlive));
- }
-
- /**
- * Set the 'http.maxConnections' property to the given value.
- *
- * This setting will apply to all requests.
- *
- * @param maxConnections
- */
- public static void maxConnections(final int maxConnections) {
- setProperty("http.maxConnections", Integer.toString(maxConnections));
- }
-
- /**
- * Set the 'http.proxyHost' and 'https.proxyHost' properties to the given host
- * value.
- *
- * This setting will apply to all requests.
- *
- * @param host
- */
- public static void proxyHost(final String host) {
- setProperty("http.proxyHost", host);
- setProperty("https.proxyHost", host);
- }
-
- /**
- * Set the 'http.proxyPort' and 'https.proxyPort' properties to the given port
- * number.
- *
- * This setting will apply to all requests.
- *
- * @param port
- */
- public static void proxyPort(final int port) {
- final String portValue = Integer.toString(port);
- setProperty("http.proxyPort", portValue);
- setProperty("https.proxyPort", portValue);
- }
-
- /**
- * Set the 'http.nonProxyHosts' property to the given host values.
- *
- * Hosts will be separated by a '|' character.
- *
- * This setting will apply to all requests.
- *
- * @param hosts
- */
- public static void nonProxyHosts(final String... hosts) {
- if (hosts != null && hosts.length > 0) {
- StringBuilder separated = new StringBuilder();
- int last = hosts.length - 1;
- for (int i = 0; i < last; i++)
- separated.append(hosts[i]).append('|');
- separated.append(hosts[last]);
- setProperty("http.nonProxyHosts", separated.toString());
- } else
- setProperty("http.nonProxyHosts", null);
- }
-
- /**
- * Set property to given value.
- *
- * Specifying a null value will cause the property to be cleared
- *
- * @param name
- * @param value
- * @return previous value
- */
- private static String setProperty(final String name, final String value) {
- final PrivilegedAction action;
- if (value != null)
- action = new PrivilegedAction() {
-
- public String run() {
- return System.setProperty(name, value);
- }
- };
- else
- action = new PrivilegedAction() {
-
- public String run() {
- return System.clearProperty(name);
- }
- };
- return AccessController.doPrivileged(action);
- }
-
- private HttpURLConnection connection = null;
-
- private final URL url;
-
- private final String requestMethod;
-
- private RequestOutputStream output;
-
- private boolean multipart;
-
- private boolean form;
-
- private boolean ignoreCloseExceptions = true;
-
- private boolean uncompress = false;
-
- private int bufferSize = 8192;
-
- private long totalSize = -1;
-
- private long totalWritten = 0;
-
- private String httpProxyHost;
-
- private int httpProxyPort;
-
- private UploadProgress progress = UploadProgress.DEFAULT;
-
- /**
- * Create HTTP connection wrapper
- *
- * @param url Remote resource URL.
- * @param method HTTP request method (e.g., "GET", "POST").
- * @throws HttpRequestException
- */
- public HttpRequest(final CharSequence url, final String method)
- throws HttpRequestException {
- try {
- this.url = new URL(url.toString());
- } catch (MalformedURLException e) {
- throw new HttpRequestException(e);
- }
- this.requestMethod = method;
- this.setupSecurity();
- }
-
- /**
- * Create HTTP connection wrapper
- *
- * @param url Remote resource URL.
- * @param method HTTP request method (e.g., "GET", "POST").
- * @throws HttpRequestException
- */
- public HttpRequest(final URL url, final String method)
- throws HttpRequestException {
- this.url = url;
- this.requestMethod = method;
- this.setupSecurity();
- }
-
- private void setupSecurity() {
- final HttpURLConnection connection = getConnection();
-
- if (!(connection instanceof HttpsURLConnection)) {
- return;
- }
-
- if (SOCKET_FACTORY != null) {
- ((HttpsURLConnection) connection).setSSLSocketFactory(SOCKET_FACTORY);
- }
-
- if (HOSTNAME_VERIFIER != null) {
- ((HttpsURLConnection) connection).setHostnameVerifier(HOSTNAME_VERIFIER);
- }
- }
-
- private Proxy createProxy() {
- return new Proxy(HTTP, new InetSocketAddress(httpProxyHost, httpProxyPort));
- }
-
- private HttpURLConnection createConnection() {
- try {
- final HttpURLConnection connection;
- if (httpProxyHost != null)
- connection = CONNECTION_FACTORY.create(url, createProxy());
- else
- connection = CONNECTION_FACTORY.create(url);
- connection.setRequestMethod(requestMethod);
- return connection;
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- @Override
- public String toString() {
- return method() + ' ' + url();
- }
-
- /**
- * Get underlying connection
- *
- * @return connection
- */
- public HttpURLConnection getConnection() {
- if (connection == null)
- connection = createConnection();
- return connection;
- }
-
- /**
- * Set whether or not to ignore exceptions that occur from calling
- * {@link Closeable#close()}
- *
- * The default value of this setting is true
- *
- * @param ignore
- * @return this request
- */
- public HttpRequest ignoreCloseExceptions(final boolean ignore) {
- ignoreCloseExceptions = ignore;
- return this;
- }
-
- /**
- * Get whether or not exceptions thrown by {@link Closeable#close()} are
- * ignored
- *
- * @return true if ignoring, false if throwing
- */
- public boolean ignoreCloseExceptions() {
- return ignoreCloseExceptions;
- }
-
- /**
- * Get the status code of the response
- *
- * @return the response code
- * @throws HttpRequestException
- */
- public int code() throws HttpRequestException {
- try {
- closeOutput();
- return getConnection().getResponseCode();
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- /**
- * Set the value of the given {@link AtomicInteger} to the status code of the
- * response
- *
- * @param output
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest code(final AtomicInteger output)
- throws HttpRequestException {
- output.set(code());
- return this;
- }
-
- /**
- * Is the response code a 200 OK?
- *
- * @return true if 200, false otherwise
- * @throws HttpRequestException
- */
- public boolean ok() throws HttpRequestException {
- return HTTP_OK == code();
- }
-
- /**
- * Is the response code a 201 Created?
- *
- * @return true if 201, false otherwise
- * @throws HttpRequestException
- */
- public boolean created() throws HttpRequestException {
- return HTTP_CREATED == code();
- }
-
- /**
- * Is the response code a 204 No Content?
- *
- * @return true if 204, false otherwise
- * @throws HttpRequestException
- */
- public boolean noContent() throws HttpRequestException {
- return HTTP_NO_CONTENT == code();
- }
-
- /**
- * Is the response code a 500 Internal Server Error?
- *
- * @return true if 500, false otherwise
- * @throws HttpRequestException
- */
- public boolean serverError() throws HttpRequestException {
- return HTTP_INTERNAL_ERROR == code();
- }
-
- /**
- * Is the response code a 400 Bad Request?
- *
- * @return true if 400, false otherwise
- * @throws HttpRequestException
- */
- public boolean badRequest() throws HttpRequestException {
- return HTTP_BAD_REQUEST == code();
- }
-
- /**
- * Is the response code a 404 Not Found?
- *
- * @return true if 404, false otherwise
- * @throws HttpRequestException
- */
- public boolean notFound() throws HttpRequestException {
- return HTTP_NOT_FOUND == code();
- }
-
- /**
- * Is the response code a 304 Not Modified?
- *
- * @return true if 304, false otherwise
- * @throws HttpRequestException
- */
- public boolean notModified() throws HttpRequestException {
- return HTTP_NOT_MODIFIED == code();
- }
-
- /**
- * Get status message of the response
- *
- * @return message
- * @throws HttpRequestException
- */
- public String message() throws HttpRequestException {
- try {
- closeOutput();
- return getConnection().getResponseMessage();
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- /**
- * Disconnect the connection
- *
- * @return this request
- */
- public HttpRequest disconnect() {
- getConnection().disconnect();
- return this;
- }
-
- /**
- * Set chunked streaming mode to the given size
- *
- * @param size
- * @return this request
- */
- public HttpRequest chunk(final int size) {
- getConnection().setChunkedStreamingMode(size);
- return this;
- }
-
- /**
- * Set the size used when buffering and copying between streams
- *
- * This size is also used for send and receive buffers created for both char
- * and byte arrays
- *
- * The default buffer size is 8,192 bytes
- *
- * @param size
- * @return this request
- */
- public HttpRequest bufferSize(final int size) {
- if (size < 1)
- throw new IllegalArgumentException("Size must be greater than zero");
- bufferSize = size;
- return this;
- }
-
- /**
- * Get the configured buffer size
- *
- * The default buffer size is 8,192 bytes
- *
- * @return buffer size
- */
- public int bufferSize() {
- return bufferSize;
- }
-
- /**
- * Set whether or not the response body should be automatically uncompressed
- * when read from.
- *
- * This will only affect requests that have the 'Content-Encoding' response
- * header set to 'gzip'.
- *
- * This causes all receive methods to use a {@link GZIPInputStream} when
- * applicable so that higher level streams and readers can read the data
- * uncompressed.
- *
- * Setting this option does not cause any request headers to be set
- * automatically so {@link #acceptGzipEncoding()} should be used in
- * conjunction with this setting to tell the server to gzip the response.
- *
- * @param uncompress
- * @return this request
- */
- public HttpRequest uncompress(final boolean uncompress) {
- this.uncompress = uncompress;
- return this;
- }
-
- /**
- * Create byte array output stream
- *
- * @return stream
- */
- protected ByteArrayOutputStream byteStream() {
- final int size = contentLength();
- if (size > 0)
- return new ByteArrayOutputStream(size);
- else
- return new ByteArrayOutputStream();
- }
-
- /**
- * Get response as {@link String} in given character set
- *
- * This will fall back to using the UTF-8 character set if the given charset
- * is null
- *
- * @param charset
- * @return string
- * @throws HttpRequestException
- */
- public String body(final String charset) throws HttpRequestException {
- final ByteArrayOutputStream output = byteStream();
- try {
- copy(buffer(), output);
- return output.toString(getValidCharset(charset));
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- /**
- * Get response as {@link String} using character set returned from
- * {@link #charset()}
- *
- * @return string
- * @throws HttpRequestException
- */
- public String body() throws HttpRequestException {
- return body(charset());
- }
-
- /**
- * Get the response body as ByteBuffer and set it as the value of the
- * given reference.
- *
- * @param output
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest body(final AtomicReference output) throws HttpRequestException {
- final ByteArrayOutputStream outputStream = byteStream();
-
- try {
- copy(buffer(), outputStream);
- output.set(ByteBuffer.wrap(outputStream.toByteArray()));
-
- return this;
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- /**
- * Get the response body as a {@link String} and set it as the value of the
- * given reference.
- *
- * @param output
- * @param charset
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest body(final AtomicReference output, final String charset) throws HttpRequestException {
- output.set(body(charset));
- return this;
- }
-
- /**
- * Is the response body empty?
- *
- * @return true if the Content-Length response header is 0, false otherwise
- * @throws HttpRequestException
- */
- public boolean isBodyEmpty() throws HttpRequestException {
- return contentLength() == 0;
- }
-
- /**
- * Get response as byte array
- *
- * @return byte array
- * @throws HttpRequestException
- */
- public byte[] bytes() throws HttpRequestException {
- final ByteArrayOutputStream output = byteStream();
- try {
- copy(buffer(), output);
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- return output.toByteArray();
- }
-
- /**
- * Get response in a buffered stream
- *
- * @see #bufferSize(int)
- * @return stream
- * @throws HttpRequestException
- */
- public BufferedInputStream buffer() throws HttpRequestException {
- return new BufferedInputStream(stream(), bufferSize);
- }
-
- /**
- * Get stream to response body
- *
- * @return stream
- * @throws HttpRequestException
- */
- public InputStream stream() throws HttpRequestException {
- InputStream stream;
- if (code() < HTTP_BAD_REQUEST)
- try {
- stream = getConnection().getInputStream();
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- else {
- stream = getConnection().getErrorStream();
- if (stream == null)
- try {
- stream = getConnection().getInputStream();
- } catch (IOException e) {
- if (contentLength() > 0)
- throw new HttpRequestException(e);
- else
- stream = new ByteArrayInputStream(new byte[0]);
- }
- }
-
- if (!uncompress || !ENCODING_GZIP.equals(contentEncoding()))
- return stream;
- else
- try {
- return new GZIPInputStream(stream);
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- /**
- * Get reader to response body using given character set.
- *
- * This will fall back to using the UTF-8 character set if the given charset
- * is null
- *
- * @param charset
- * @return reader
- * @throws HttpRequestException
- */
- public InputStreamReader reader(final String charset)
- throws HttpRequestException {
- try {
- return new InputStreamReader(stream(), getValidCharset(charset));
- } catch (UnsupportedEncodingException e) {
- throw new HttpRequestException(e);
- }
- }
-
- /**
- * Get reader to response body using the character set returned from
- * {@link #charset()}
- *
- * @return reader
- * @throws HttpRequestException
- */
- public InputStreamReader reader() throws HttpRequestException {
- return reader(charset());
- }
-
- /**
- * Get buffered reader to response body using the given character set r and
- * the configured buffer size
- *
- *
- * @see #bufferSize(int)
- * @param charset
- * @return reader
- * @throws HttpRequestException
- */
- public BufferedReader bufferedReader(final String charset)
- throws HttpRequestException {
- return new BufferedReader(reader(charset), bufferSize);
- }
-
- /**
- * Get buffered reader to response body using the character set returned from
- * {@link #charset()} and the configured buffer size
- *
- * @see #bufferSize(int)
- * @return reader
- * @throws HttpRequestException
- */
- public BufferedReader bufferedReader() throws HttpRequestException {
- return bufferedReader(charset());
- }
-
- /**
- * Stream response body to file
- *
- * @param file
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest receive(final File file) throws HttpRequestException {
- final OutputStream output;
- try {
- output = new BufferedOutputStream(new FileOutputStream(file), bufferSize);
- } catch (FileNotFoundException e) {
- throw new HttpRequestException(e);
- }
- return new CloseOperation(output, ignoreCloseExceptions) {
-
- @Override
- protected HttpRequest run() throws HttpRequestException, IOException {
- return receive(output);
- }
- }.call();
- }
-
- /**
- * Stream response to given output stream
- *
- * @param output
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest receive(final OutputStream output)
- throws HttpRequestException {
- try {
- return copy(buffer(), output);
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- /**
- * Stream response to given print stream
- *
- * @param output
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest receive(final PrintStream output)
- throws HttpRequestException {
- return receive((OutputStream) output);
- }
-
- /**
- * Receive response into the given appendable
- *
- * @param appendable
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest receive(final Appendable appendable)
- throws HttpRequestException {
- final BufferedReader reader = bufferedReader();
- return new CloseOperation(reader, ignoreCloseExceptions) {
-
- @Override
- public HttpRequest run() throws IOException {
- final CharBuffer buffer = CharBuffer.allocate(bufferSize);
- int read;
- while ((read = reader.read(buffer)) != -1) {
- buffer.rewind();
- appendable.append(buffer, 0, read);
- buffer.rewind();
- }
- return HttpRequest.this;
- }
- }.call();
- }
-
- /**
- * Receive response into the given writer
- *
- * @param writer
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest receive(final Writer writer) throws HttpRequestException {
- final BufferedReader reader = bufferedReader();
- return new CloseOperation(reader, ignoreCloseExceptions) {
-
- @Override
- public HttpRequest run() throws IOException {
- return copy(reader, writer);
- }
- }.call();
- }
-
- /**
- * Set read timeout on connection to given value
- *
- * @param timeout
- * @return this request
- */
- public HttpRequest readTimeout(final int timeout) {
- getConnection().setReadTimeout(timeout);
- return this;
- }
-
- /**
- * Set connect timeout on connection to given value
- *
- * @param timeout
- * @return this request
- */
- public HttpRequest connectTimeout(final int timeout) {
- getConnection().setConnectTimeout(timeout);
- return this;
- }
-
- /**
- * Set header name to given value
- *
- * @param name
- * @param value
- * @return this request
- */
- public HttpRequest header(final String name, final String value) {
- getConnection().setRequestProperty(name, value);
- return this;
- }
-
- /**
- * Set header name to given value
- *
- * @param name
- * @param value
- * @return this request
- */
- public HttpRequest header(final String name, final Number value) {
- return header(name, value != null ? value.toString() : null);
- }
-
- /**
- * Set all headers found in given map where the keys are the header names and
- * the values are the header values
- *
- * @param headers
- * @return this request
- */
- public HttpRequest headers(final Map headers) {
- if (!headers.isEmpty())
- for (Entry header : headers.entrySet())
- header(header);
- return this;
- }
-
- /**
- * Set header to have given entry's key as the name and value as the value
- *
- * @param header
- * @return this request
- */
- public HttpRequest header(final Entry header) {
- return header(header.getKey(), header.getValue());
- }
-
- /**
- * Get a response header
- *
- * @param name
- * @return response header
- * @throws HttpRequestException
- */
- public String header(final String name) throws HttpRequestException {
- closeOutputQuietly();
- return getConnection().getHeaderField(name);
- }
-
- /**
- * Get all the response headers
- *
- * @return map of response header names to their value(s)
- * @throws HttpRequestException
- */
- public Map> headers() throws HttpRequestException {
- closeOutputQuietly();
- return getConnection().getHeaderFields();
- }
-
- /**
- * Get a date header from the response falling back to returning -1 if the
- * header is missing or parsing fails
- *
- * @param name
- * @return date, -1 on failures
- * @throws HttpRequestException
- */
- public long dateHeader(final String name) throws HttpRequestException {
- return dateHeader(name, -1L);
- }
-
- /**
- * Get a date header from the response falling back to returning the given
- * default value if the header is missing or parsing fails
- *
- * @param name
- * @param defaultValue
- * @return date, default value on failures
- * @throws HttpRequestException
- */
- public long dateHeader(final String name, final long defaultValue)
- throws HttpRequestException {
- closeOutputQuietly();
- return getConnection().getHeaderFieldDate(name, defaultValue);
- }
-
- /**
- * Get an integer header from the response falling back to returning -1 if the
- * header is missing or parsing fails
- *
- * @param name
- * @return header value as an integer, -1 when missing or parsing fails
- * @throws HttpRequestException
- */
- public int intHeader(final String name) throws HttpRequestException {
- return intHeader(name, -1);
- }
-
- /**
- * Get an integer header value from the response falling back to the given
- * default value if the header is missing or if parsing fails
- *
- * @param name
- * @param defaultValue
- * @return header value as an integer, default value when missing or parsing
- * fails
- * @throws HttpRequestException
- */
- public int intHeader(final String name, final int defaultValue)
- throws HttpRequestException {
- closeOutputQuietly();
- return getConnection().getHeaderFieldInt(name, defaultValue);
- }
-
- /**
- * Get all values of the given header from the response
- *
- * @param name
- * @return non-null but possibly empty array of {@link String} header values
- */
- public String[] headers(final String name) {
- final Map> headers = headers();
- if (headers == null || headers.isEmpty())
- return EMPTY_STRINGS;
-
- final List values = headers.get(name);
- if (values != null && !values.isEmpty())
- return values.toArray(new String[values.size()]);
- else
- return EMPTY_STRINGS;
- }
-
- /**
- * Get parameter with given name from header value in response
- *
- * @param headerName
- * @param paramName
- * @return parameter value or null if missing
- */
- public String parameter(final String headerName, final String paramName) {
- return getParam(header(headerName), paramName);
- }
-
- /**
- * Get all parameters from header value in response
- *
- * This will be all key=value pairs after the first ';' that are separated by
- * a ';'
- *
- * @param headerName
- * @return non-null but possibly empty map of parameter headers
- */
- public Map parameters(final String headerName) {
- return getParams(header(headerName));
- }
-
- /**
- * Get parameter values from header value
- *
- * @param header
- * @return parameter value or null if none
- */
- protected Map getParams(final String header) {
- if (header == null || header.length() == 0)
- return Collections.emptyMap();
-
- final int headerLength = header.length();
- int start = header.indexOf(';') + 1;
- if (start == 0 || start == headerLength)
- return Collections.emptyMap();
-
- int end = header.indexOf(';', start);
- if (end == -1)
- end = headerLength;
-
- Map params = new LinkedHashMap();
- while (start < end) {
- int nameEnd = header.indexOf('=', start);
- if (nameEnd != -1 && nameEnd < end) {
- String name = header.substring(start, nameEnd).trim();
- if (name.length() > 0) {
- String value = header.substring(nameEnd + 1, end).trim();
- int length = value.length();
- if (length != 0)
- if (length > 2 && '"' == value.charAt(0)
- && '"' == value.charAt(length - 1))
- params.put(name, value.substring(1, length - 1));
- else
- params.put(name, value);
- }
- }
-
- start = end + 1;
- end = header.indexOf(';', start);
- if (end == -1)
- end = headerLength;
- }
-
- return params;
- }
-
- /**
- * Get parameter value from header value
- *
- * @param value
- * @param paramName
- * @return parameter value or null if none
- */
- protected String getParam(final String value, final String paramName) {
- if (value == null || value.length() == 0)
- return null;
-
- final int length = value.length();
- int start = value.indexOf(';') + 1;
- if (start == 0 || start == length)
- return null;
-
- int end = value.indexOf(';', start);
- if (end == -1)
- end = length;
-
- while (start < end) {
- int nameEnd = value.indexOf('=', start);
- if (nameEnd != -1 && nameEnd < end
- && paramName.equals(value.substring(start, nameEnd).trim())) {
- String paramValue = value.substring(nameEnd + 1, end).trim();
- int valueLength = paramValue.length();
- if (valueLength != 0)
- if (valueLength > 2 && '"' == paramValue.charAt(0)
- && '"' == paramValue.charAt(valueLength - 1))
- return paramValue.substring(1, valueLength - 1);
- else
- return paramValue;
- }
-
- start = end + 1;
- end = value.indexOf(';', start);
- if (end == -1)
- end = length;
- }
-
- return null;
- }
-
- /**
- * Get 'charset' parameter from 'Content-Type' response header
- *
- * @return charset or null if none
- */
- public String charset() {
- return parameter(HEADER_CONTENT_TYPE, PARAM_CHARSET);
- }
-
- /**
- * Set the 'User-Agent' header to given value
- *
- * @param userAgent
- * @return this request
- */
- public HttpRequest userAgent(final String userAgent) {
- return header(HEADER_USER_AGENT, userAgent);
- }
-
- /**
- * Set the 'Referer' header to given value
- *
- * @param referer
- * @return this request
- */
- public HttpRequest referer(final String referer) {
- return header(HEADER_REFERER, referer);
- }
-
- /**
- * Set value of {@link HttpURLConnection#setUseCaches(boolean)}
- *
- * @param useCaches
- * @return this request
- */
- public HttpRequest useCaches(final boolean useCaches) {
- getConnection().setUseCaches(useCaches);
- return this;
- }
-
- /**
- * Set the 'Accept-Encoding' header to given value
- *
- * @param acceptEncoding
- * @return this request
- */
- public HttpRequest acceptEncoding(final String acceptEncoding) {
- return header(HEADER_ACCEPT_ENCODING, acceptEncoding);
- }
-
- /**
- * Set the 'Accept-Encoding' header to 'gzip'
- *
- * @see #uncompress(boolean)
- * @return this request
- */
- public HttpRequest acceptGzipEncoding() {
- return acceptEncoding(ENCODING_GZIP);
- }
-
- /**
- * Set the 'Accept-Charset' header to given value
- *
- * @param acceptCharset
- * @return this request
- */
- public HttpRequest acceptCharset(final String acceptCharset) {
- return header(HEADER_ACCEPT_CHARSET, acceptCharset);
- }
-
- /**
- * Set the 'Accept-Charset' header to given values
- *
- * @param acceptCharsets
- * @return this request
- */
- public HttpRequest acceptCharset(final String[] acceptCharsets) {
- return header(HEADER_ACCEPT_CHARSET, TextUtils.join(", ", acceptCharsets));
- }
-
- /**
- * Get the 'Content-Encoding' header from the response
- *
- * @return this request
- */
- public String contentEncoding() {
- return header(HEADER_CONTENT_ENCODING);
- }
-
- /**
- * Get the 'Server' header from the response
- *
- * @return server
- */
- public String server() {
- return header(HEADER_SERVER);
- }
-
- /**
- * Get the 'Date' header from the response
- *
- * @return date value, -1 on failures
- */
- public long date() {
- return dateHeader(HEADER_DATE);
- }
-
- /**
- * Get the 'Cache-Control' header from the response
- *
- * @return cache control
- */
- public String cacheControl() {
- return header(HEADER_CACHE_CONTROL);
- }
-
- /**
- * Get the 'ETag' header from the response
- *
- * @return entity tag
- */
- public String eTag() {
- return header(HEADER_ETAG);
- }
-
- /**
- * Get the 'Expires' header from the response
- *
- * @return expires value, -1 on failures
- */
- public long expires() {
- return dateHeader(HEADER_EXPIRES);
- }
-
- /**
- * Get the 'Last-Modified' header from the response
- *
- * @return last modified value, -1 on failures
- */
- public long lastModified() {
- return dateHeader(HEADER_LAST_MODIFIED);
- }
-
- /**
- * Get the 'Location' header from the response
- *
- * @return location
- */
- public String location() {
- return header(HEADER_LOCATION);
- }
-
- /**
- * Set the 'Authorization' header to given value
- *
- * @param authorization
- * @return this request
- */
- public HttpRequest authorization(final String authorization) {
- return header(HEADER_AUTHORIZATION, authorization);
- }
-
- /**
- * Set the 'Proxy-Authorization' header to given value
- *
- * @param proxyAuthorization
- * @return this request
- */
- public HttpRequest proxyAuthorization(final String proxyAuthorization) {
- return header(HEADER_PROXY_AUTHORIZATION, proxyAuthorization);
- }
-
- /**
- * Set the 'Authorization' header to given values in Basic authentication
- * format
- *
- * @param name
- * @param password
- * @return this request
- */
- public HttpRequest basic(final String name, final String password) {
- return authorization("Basic " + Base64.encode(name + ':' + password));
- }
-
- /**
- * Set the 'Proxy-Authorization' header to given values in Basic authentication
- * format
- *
- * @param name
- * @param password
- * @return this request
- */
- public HttpRequest proxyBasic(final String name, final String password) {
- return proxyAuthorization("Basic " + Base64.encode(name + ':' + password));
- }
-
- /**
- * Set the 'If-Modified-Since' request header to the given value
- *
- * @param ifModifiedSince
- * @return this request
- */
- public HttpRequest ifModifiedSince(final long ifModifiedSince) {
- getConnection().setIfModifiedSince(ifModifiedSince);
- return this;
- }
-
- /**
- * Set the 'If-None-Match' request header to the given value
- *
- * @param ifNoneMatch
- * @return this request
- */
- public HttpRequest ifNoneMatch(final String ifNoneMatch) {
- return header(HEADER_IF_NONE_MATCH, ifNoneMatch);
- }
-
- /**
- * Set the 'Content-Type' request header to the given value
- *
- * @param contentType
- * @return this request
- */
- public HttpRequest contentType(final String contentType) {
- return contentType(contentType, null);
- }
-
- /**
- * Set the 'Content-Type' request header to the given value and charset
- *
- * @param contentType
- * @param charset
- * @return this request
- */
- public HttpRequest contentType(final String contentType, final String charset) {
- if (charset != null && charset.length() > 0) {
- final String separator = "; " + PARAM_CHARSET + '=';
- return header(HEADER_CONTENT_TYPE, contentType + separator + charset);
- } else
- return header(HEADER_CONTENT_TYPE, contentType);
- }
-
- /**
- * Get the 'Content-Type' header from the response
- *
- * @return response header value
- */
- public String contentType() {
- return header(HEADER_CONTENT_TYPE);
- }
-
- /**
- * Get the 'Content-Length' header from the response
- *
- * @return response header value
- */
- public int contentLength() {
- return intHeader(HEADER_CONTENT_LENGTH);
- }
-
- /**
- * Set the 'Content-Length' request header to the given value
- *
- * @param contentLength
- * @return this request
- */
- public HttpRequest contentLength(final String contentLength) {
- return contentLength(Integer.parseInt(contentLength));
- }
-
- /**
- * Set the 'Content-Length' request header to the given value
- *
- * @param contentLength
- * @return this request
- */
- public HttpRequest contentLength(final int contentLength) {
- getConnection().setFixedLengthStreamingMode(contentLength);
- return this;
- }
-
- /**
- * Set the 'Accept' header to given value
- *
- * @param accept
- * @return this request
- */
- public HttpRequest accept(final String accept) {
- return header(HEADER_ACCEPT, accept);
- }
-
- /**
- * Set the 'Accept' header to 'application/json'
- *
- * @return this request
- */
- public HttpRequest acceptJson() {
- return accept(CONTENT_TYPE_JSON);
- }
-
- /**
- * Copy from input stream to output stream
- *
- * @param input
- * @param output
- * @return this request
- * @throws IOException
- */
- protected HttpRequest copy(final InputStream input, final OutputStream output)
- throws IOException {
- return new CloseOperation(input, ignoreCloseExceptions) {
-
- @Override
- public HttpRequest run() throws IOException {
- final byte[] buffer = new byte[bufferSize];
- int read;
- while ((read = input.read(buffer)) != -1) {
- output.write(buffer, 0, read);
- totalWritten += read;
- progress.onUpload(totalWritten, totalSize);
- }
- return HttpRequest.this;
- }
- }.call();
- }
-
- /**
- * Copy from reader to writer
- *
- * @param input
- * @param output
- * @return this request
- * @throws IOException
- */
- protected HttpRequest copy(final Reader input, final Writer output)
- throws IOException {
- return new CloseOperation(input, ignoreCloseExceptions) {
-
- @Override
- public HttpRequest run() throws IOException {
- final char[] buffer = new char[bufferSize];
- int read;
- while ((read = input.read(buffer)) != -1) {
- output.write(buffer, 0, read);
- totalWritten += read;
- progress.onUpload(totalWritten, -1);
- }
- return HttpRequest.this;
- }
- }.call();
- }
-
- /**
- * Set the UploadProgress callback for this request
- *
- * @param callback
- * @return this request
- */
- public HttpRequest progress(final UploadProgress callback) {
- if (callback == null)
- progress = UploadProgress.DEFAULT;
- else
- progress = callback;
- return this;
- }
-
- private HttpRequest incrementTotalSize(final long size) {
- if (totalSize == -1)
- totalSize = 0;
- totalSize += size;
- return this;
- }
-
- /**
- * Close output stream
- *
- * @return this request
- * @throws HttpRequestException
- * @throws IOException
- */
- protected HttpRequest closeOutput() throws IOException {
- progress(null);
- if (output == null)
- return this;
- if (multipart)
- output.write(CRLF + "--" + BOUNDARY + "--" + CRLF);
- if (ignoreCloseExceptions)
- try {
- output.close();
- } catch (IOException ignored) {
- // Ignored
- }
- else
- output.close();
- output = null;
- return this;
- }
-
- /**
- * Call {@link #closeOutput()} and re-throw a caught {@link IOException}s as
- * an {@link HttpRequestException}
- *
- * @return this request
- * @throws HttpRequestException
- */
- protected HttpRequest closeOutputQuietly() throws HttpRequestException {
- try {
- return closeOutput();
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- /**
- * Open output stream
- *
- * @return this request
- * @throws IOException
- */
- protected HttpRequest openOutput() throws IOException {
- if (output != null)
- return this;
- getConnection().setDoOutput(true);
- final String charset = getParam(
- getConnection().getRequestProperty(HEADER_CONTENT_TYPE), PARAM_CHARSET);
- output = new RequestOutputStream(getConnection().getOutputStream(), charset,
- bufferSize);
- return this;
- }
-
- /**
- * Start part of a multipart
- *
- * @return this request
- * @throws IOException
- */
- protected HttpRequest startPart() throws IOException {
- if (!multipart) {
- multipart = true;
- contentType(CONTENT_TYPE_MULTIPART).openOutput();
- output.write("--" + BOUNDARY + CRLF);
- } else
- output.write(CRLF + "--" + BOUNDARY + CRLF);
- return this;
- }
-
- /**
- * Write part header
- *
- * @param name
- * @param filename
- * @return this request
- * @throws IOException
- */
- protected HttpRequest writePartHeader(final String name, final String filename)
- throws IOException {
- return writePartHeader(name, filename, null);
- }
-
- /**
- * Write part header
- *
- * @param name
- * @param filename
- * @param contentType
- * @return this request
- * @throws IOException
- */
- protected HttpRequest writePartHeader(final String name,
- final String filename, final String contentType) throws IOException {
- final StringBuilder partBuffer = new StringBuilder();
- partBuffer.append("form-data; name=\"").append(name);
- if (filename != null)
- partBuffer.append("\"; filename=\"").append(filename);
- partBuffer.append('"');
- partHeader("Content-Disposition", partBuffer.toString());
- if (contentType != null)
- partHeader(HEADER_CONTENT_TYPE, contentType);
- return send(CRLF);
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param part
- * @return this request
- */
- public HttpRequest part(final String name, final String part) {
- return part(name, null, part);
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param filename
- * @param part
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest part(final String name, final String filename,
- final String part) throws HttpRequestException {
- return part(name, filename, null, part);
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param filename
- * @param contentType
- * value of the Content-Type part header
- * @param part
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest part(final String name, final String filename,
- final String contentType, final String part) throws HttpRequestException {
- try {
- startPart();
- writePartHeader(name, filename, contentType);
- output.write(part);
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- return this;
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param part
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest part(final String name, final Number part)
- throws HttpRequestException {
- return part(name, null, part);
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param filename
- * @param part
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest part(final String name, final String filename,
- final Number part) throws HttpRequestException {
- return part(name, filename, part != null ? part.toString() : null);
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param part
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest part(final String name, final File part)
- throws HttpRequestException {
- return part(name, null, part);
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param filename
- * @param part
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest part(final String name, final String filename,
- final File part) throws HttpRequestException {
- return part(name, filename, null, part);
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param filename
- * @param contentType
- * value of the Content-Type part header
- * @param part
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest part(final String name, final String filename,
- final String contentType, final File part) throws HttpRequestException {
- final InputStream stream;
- try {
- stream = new BufferedInputStream(new FileInputStream(part));
- incrementTotalSize(part.length());
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- return part(name, filename, contentType, stream);
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param part
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest part(final String name, final InputStream part)
- throws HttpRequestException {
- return part(name, null, null, part);
- }
-
- /**
- * Write part of a multipart request to the request body
- *
- * @param name
- * @param filename
- * @param contentType
- * value of the Content-Type part header
- * @param part
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest part(final String name, final String filename,
- final String contentType, final InputStream part)
- throws HttpRequestException {
- try {
- startPart();
- writePartHeader(name, filename, contentType);
- copy(part, output);
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- return this;
- }
-
- /**
- * Write a multipart header to the response body
- *
- * @param name
- * @param value
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest partHeader(final String name, final String value)
- throws HttpRequestException {
- return send(name).send(": ").send(value).send(CRLF);
- }
-
- /**
- * Write contents of file to request body
- *
- * @param input
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest send(final File input) throws HttpRequestException {
- final InputStream stream;
- try {
- stream = new BufferedInputStream(new FileInputStream(input));
- incrementTotalSize(input.length());
- } catch (FileNotFoundException e) {
- throw new HttpRequestException(e);
- }
- return send(stream);
- }
-
- /**
- * Write byte array to request body
- *
- * @param input
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest send(final byte[] input) throws HttpRequestException {
- if (input != null)
- incrementTotalSize(input.length);
- return send(new ByteArrayInputStream(input));
- }
-
- /**
- * Write stream to request body
- *
- * The given stream will be closed once sending completes
- *
- * @param input
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest send(final InputStream input) throws HttpRequestException {
- try {
- openOutput();
- copy(input, output);
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- return this;
- }
-
- /**
- * Write reader to request body
- *
- * The given reader will be closed once sending completes
- *
- * @param input
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest send(final Reader input) throws HttpRequestException {
- try {
- openOutput();
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- final Writer writer = new OutputStreamWriter(output,
- output.encoder.charset());
- return new FlushOperation(writer) {
-
- @Override
- protected HttpRequest run() throws IOException {
- return copy(input, writer);
- }
- }.call();
- }
-
- /**
- * Write char sequence to request body
- *
- * The charset configured via {@link #contentType(String)} will be used and
- * UTF-8 will be used if it is unset.
- *
- * @param value
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest send(final CharSequence value) throws HttpRequestException {
- try {
- openOutput();
- output.write(value.toString());
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- return this;
- }
-
- /**
- * Create writer to request output stream
- *
- * @return writer
- * @throws HttpRequestException
- */
- public OutputStreamWriter writer() throws HttpRequestException {
- try {
- openOutput();
- return new OutputStreamWriter(output, output.encoder.charset());
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- }
-
- /**
- * Write the values in the map as form data to the request body
- *
- * The pairs specified will be URL-encoded in UTF-8 and sent with the
- * 'application/x-www-form-urlencoded' content-type
- *
- * @param values
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest form(final Map, ?> values) throws HttpRequestException {
- return form(values, CHARSET_UTF8);
- }
-
- /**
- * Write the key and value in the entry as form data to the request body
- *
- * The pair specified will be URL-encoded in UTF-8 and sent with the
- * 'application/x-www-form-urlencoded' content-type
- *
- * @param entry
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest form(final Entry, ?> entry) throws HttpRequestException {
- return form(entry, CHARSET_UTF8);
- }
-
- /**
- * Write the key and value in the entry as form data to the request body
- *
- * The pair specified will be URL-encoded and sent with the
- * 'application/x-www-form-urlencoded' content-type
- *
- * @param entry
- * @param charset
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest form(final Entry, ?> entry, final String charset)
- throws HttpRequestException {
- return form(entry.getKey(), entry.getValue(), charset);
- }
-
- /**
- * Write the name/value pair as form data to the request body
- *
- * The pair specified will be URL-encoded in UTF-8 and sent with the
- * 'application/x-www-form-urlencoded' content-type
- *
- * @param name
- * @param value
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest form(final Object name, final Object value)
- throws HttpRequestException {
- return form(name, value, CHARSET_UTF8);
- }
-
- /**
- * Write the name/value pair as form data to the request body
- *
- * The values specified will be URL-encoded and sent with the
- * 'application/x-www-form-urlencoded' content-type
- *
- * @param name
- * @param value
- * @param charset
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest form(final Object name, final Object value, String charset)
- throws HttpRequestException {
- final boolean first = !form;
- if (first) {
- contentType(CONTENT_TYPE_FORM, charset);
- form = true;
- }
- charset = getValidCharset(charset);
- try {
- openOutput();
- if (!first)
- output.write('&');
- output.write(URLEncoder.encode(name.toString(), charset));
- output.write('=');
- if (value != null)
- output.write(URLEncoder.encode(value.toString(), charset));
- } catch (IOException e) {
- throw new HttpRequestException(e);
- }
- return this;
- }
-
- /**
- * Write the values in the map as encoded form data to the request body
- *
- * @param values
- * @param charset
- * @return this request
- * @throws HttpRequestException
- */
- public HttpRequest form(final Map, ?> values, final String charset)
- throws HttpRequestException {
- if (!values.isEmpty())
- for (Entry, ?> entry : values.entrySet())
- form(entry, charset);
- return this;
- }
-
- /**
- * Get the {@link URL} of this request's connection
- *
- * @return request URL
- */
- public URL url() {
- return getConnection().getURL();
- }
-
- /**
- * Get the HTTP method of this request
- *
- * @return method
- */
- public String method() {
- return getConnection().getRequestMethod();
- }
-
- /**
- * Configure an HTTP proxy on this connection. Use {{@link #proxyBasic(String, String)} if
- * this proxy requires basic authentication.
- *
- * @param proxyHost
- * @param proxyPort
- * @return this request
- */
- public HttpRequest useProxy(final String proxyHost, final int proxyPort) {
- if (connection != null)
- throw new IllegalStateException("The connection has already been created. This method must be called before reading or writing to the request.");
-
- this.httpProxyHost = proxyHost;
- this.httpProxyPort = proxyPort;
- return this;
- }
-
- /**
- * Set whether or not the underlying connection should follow redirects in
- * the response.
- *
- * @param followRedirects - true fo follow redirects, false to not.
- * @return this request
- */
- public HttpRequest followRedirects(final boolean followRedirects) {
- getConnection().setInstanceFollowRedirects(followRedirects);
- return this;
- }
-}
diff --git a/src/android/com/github/kevinsawicki/http/TLSSocketFactory.java b/src/android/com/github/kevinsawicki/http/TLSSocketFactory.java
deleted file mode 100644
index 37cedb0..0000000
--- a/src/android/com/github/kevinsawicki/http/TLSSocketFactory.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.github.kevinsawicki.http;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.UnknownHostException;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-
-public class TLSSocketFactory extends SSLSocketFactory {
-
- private SSLSocketFactory delegate;
-
- public TLSSocketFactory(SSLContext context) {
- delegate = context.getSocketFactory();
- }
-
- @Override
- public String[] getDefaultCipherSuites() {
- return delegate.getDefaultCipherSuites();
- }
-
- @Override
- public String[] getSupportedCipherSuites() {
- return delegate.getSupportedCipherSuites();
- }
-
- @Override
- public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
- return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
- }
-
- @Override
- public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
- return enableTLSOnSocket(delegate.createSocket(host, port));
- }
-
- @Override
- public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
- return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
- }
-
- @Override
- public Socket createSocket(InetAddress host, int port) throws IOException {
- return enableTLSOnSocket(delegate.createSocket(host, port));
- }
-
- @Override
- public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
- return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
- }
-
- private Socket enableTLSOnSocket(Socket socket) {
- if(socket != null && (socket instanceof SSLSocket)) {
- ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"});
- }
- return socket;
- }
-}
diff --git a/src/android/com/silkimen/cordovahttp/CordovaHttpBase.java b/src/android/com/silkimen/cordovahttp/CordovaHttpBase.java
new file mode 100644
index 0000000..b005e57
--- /dev/null
+++ b/src/android/com/silkimen/cordovahttp/CordovaHttpBase.java
@@ -0,0 +1,171 @@
+package com.silkimen.cordovahttp;
+
+import java.io.ByteArrayOutputStream;
+
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+
+import java.nio.ByteBuffer;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import com.silkimen.http.HttpBodyDecoder;
+import com.silkimen.http.HttpRequest;
+import com.silkimen.http.HttpRequest.HttpRequestException;
+import com.silkimen.http.JsonUtils;
+
+import org.apache.cordova.CallbackContext;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.util.Log;
+
+abstract class CordovaHttpBase implements Runnable {
+ protected static final String TAG = "Cordova-Plugin-HTTP";
+
+ protected String method;
+ protected String url;
+ protected String serializer = "none";
+ protected Object data;
+ protected JSONObject params;
+ protected JSONObject headers;
+ protected int timeout;
+ protected CallbackContext callbackContext;
+
+ public CordovaHttpBase(String method, String url, String serializer, Object data, JSONObject headers, int timeout,
+ CallbackContext callbackContext) {
+
+ this.method = method;
+ this.url = url;
+ this.serializer = serializer;
+ this.data = data;
+ this.headers = headers;
+ this.timeout = timeout;
+ this.callbackContext = callbackContext;
+ }
+
+ public CordovaHttpBase(String method, String url, JSONObject params, JSONObject headers, int timeout,
+ CallbackContext callbackContext) {
+
+ this.method = method;
+ this.url = url;
+ this.params = params;
+ this.headers = headers;
+ this.timeout = timeout;
+ this.callbackContext = callbackContext;
+ }
+
+ @Override
+ public void run() {
+ CordovaHttpResponse response = new CordovaHttpResponse();
+
+ try {
+ HttpRequest request = this.createRequest();
+ this.prepareRequest(request);
+ this.sendBody(request);
+ this.processResponse(request, response);
+ } catch (HttpRequestException e) {
+ if (e.getCause() instanceof SSLHandshakeException) {
+ response.setStatus(-2);
+ response.setErrorMessage("SSL handshake failed: " + e.getMessage());
+ Log.w(TAG, "SSL handshake failed", e);
+ } else if (e.getCause() instanceof UnknownHostException) {
+ response.setStatus(-3);
+ response.setErrorMessage("Host could not be resolved: " + e.getMessage());
+ Log.w(TAG, "Host could not be resolved", e);
+ } else if (e.getCause() instanceof SocketTimeoutException) {
+ response.setStatus(-4);
+ response.setErrorMessage("Request timed out: " + e.getMessage());
+ Log.w(TAG, "Request timed out", e);
+ } else {
+ response.setStatus(-1);
+ response.setErrorMessage("There was an error with the request: " + e.getCause().getMessage());
+ Log.w(TAG, "Generic request error", e);
+ }
+ } catch (Exception e) {
+ response.setStatus(-1);
+ response.setErrorMessage(e.getMessage());
+ Log.e(TAG, "An unexpected error occured", e);
+ }
+
+ try {
+ if (response.hasFailed()) {
+ this.callbackContext.error(response.toJSON());
+ } else {
+ this.callbackContext.success(response.toJSON());
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "An unexpected error occured while creating HTTP response object", e);
+ }
+ }
+
+ protected HttpRequest createRequest() throws JSONException {
+ String processedUrl = HttpRequest.encode(HttpRequest.append(this.url, JsonUtils.getObjectMap(this.params)));
+ HttpRequest request = new HttpRequest(processedUrl, this.method);
+
+ return request;
+ }
+
+ protected void prepareRequest(HttpRequest request) throws JSONException {
+ request.followRedirects(true /* @TODO */);
+ request.readTimeout(this.timeout);
+ request.acceptCharset("UTF-8");
+ request.uncompress(true);
+
+ // setup content type before applying headers, so user can override it
+ this.setContentType(request);
+
+ request.headers(JsonUtils.getStringMap(this.headers));
+ }
+
+ protected void setContentType(HttpRequest request) {
+ switch (this.serializer) {
+ case "json":
+ request.contentType("application/json", "UTF-8");
+ break;
+ case "utf8":
+ request.contentType("text/plain", "UTF-8");
+ break;
+ case "urlencoded":
+ // intentionally left blank, because content type is set in HttpRequest.form()
+ break;
+ }
+ }
+
+ protected void sendBody(HttpRequest request) throws Exception {
+ if (this.data == null) {
+ return;
+ }
+
+ switch (this.serializer) {
+ case "json":
+ request.send(this.data.toString());
+ break;
+ case "utf8":
+ request.send(((JSONObject) this.data).getString("text"));
+ break;
+ case "urlencoded":
+ request.form(JsonUtils.getObjectMap((JSONObject) this.data));
+ break;
+ }
+ }
+
+ protected void processResponse(HttpRequest request, CordovaHttpResponse response) throws Exception {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ request.receive(outputStream);
+
+ ByteBuffer rawOutput = ByteBuffer.wrap(outputStream.toByteArray());
+ String decodedBody = HttpBodyDecoder.decodeBody(rawOutput, request.charset());
+
+ response.setStatus(request.code());
+ response.setUrl(request.url().toString());
+ response.setHeaders(request.headers());
+
+ if (request.code() >= 200 && request.code() < 300) {
+ response.setBody(decodedBody);
+ } else {
+ response.setErrorMessage(decodedBody);
+ }
+ }
+}
diff --git a/src/android/com/silkimen/cordovahttp/CordovaHttpDownload.java b/src/android/com/silkimen/cordovahttp/CordovaHttpDownload.java
index 05f73fe..9c6bc5e 100644
--- a/src/android/com/silkimen/cordovahttp/CordovaHttpDownload.java
+++ b/src/android/com/silkimen/cordovahttp/CordovaHttpDownload.java
@@ -1,105 +1,38 @@
package com.silkimen.cordovahttp;
import java.io.File;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
import java.net.URI;
-import java.net.URISyntaxException;
-import javax.net.ssl.SSLHandshakeException;
-
-import com.silkimen.http.HttpBodyDecoder;
import com.silkimen.http.HttpRequest;
-import com.silkimen.http.HttpRequest.HttpRequestException;
-import com.silkimen.http.JsonUtils;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.file.FileUtils;
-
-import org.json.JSONException;
import org.json.JSONObject;
-import android.util.Log;
-
-class CordovaHttpDownload implements Runnable {
- private static final String TAG = "Cordova-Plugin-HTTP";
-
- private String url;
- private JSONObject params;
- private JSONObject headers;
+class CordovaHttpDownload extends CordovaHttpBase {
private String filePath;
- private int timeout;
- private CallbackContext callbackContext;
public CordovaHttpDownload(String url, JSONObject params, JSONObject headers, String filePath, int timeout,
CallbackContext callbackContext) {
- this.url = url;
- this.params = params;
- this.headers = headers;
+ super("GET", url, params, headers, timeout, callbackContext);
this.filePath = filePath;
- this.timeout = timeout;
- this.callbackContext = callbackContext;
}
@Override
- public void run() {
- CordovaHttpResponse response = new CordovaHttpResponse();
+ protected void processResponse(HttpRequest request, CordovaHttpResponse response) throws Exception {
+ response.setStatus(request.code());
+ response.setUrl(request.url().toString());
+ response.setHeaders(request.headers());
- try {
- String processedUrl = HttpRequest.encode(HttpRequest.append(this.url, JsonUtils.getObjectMap(this.params)));
+ if (request.code() >= 200 && request.code() < 300) {
+ File file = new File(new URI(this.filePath));
+ JSONObject fileEntry = FileUtils.getFilePlugin().getEntryForFile(file);
- HttpRequest request = new HttpRequest(processedUrl, "GET")
- .followRedirects(true /* @TODO */)
- .readTimeout(this.timeout)
- .acceptCharset("UTF-8")
- .uncompress(true)
- .headers(JsonUtils.getStringMap(this.headers));
-
- response.setStatus(request.code());
- response.setUrl(request.url().toString());
- response.setHeaders(request.headers());
-
- if (request.code() >= 200 && request.code() < 300) {
- File file = new File(new URI(filePath));
-
- request.receive(file);
- response.setFileEntry(FileUtils.getFilePlugin().getEntryForFile(file));
- } else {
- response.setErrorMessage("There was an error downloading the file");
- }
- } catch (HttpRequestException e) {
- if (e.getCause() instanceof SSLHandshakeException) {
- response.setStatus(-2);
- response.setErrorMessage("SSL handshake failed: " + e.getMessage());
- Log.w(TAG, "SSL handshake failed", e);
- } else if (e.getCause() instanceof UnknownHostException) {
- response.setStatus(-3);
- response.setErrorMessage("Host could not be resolved: " + e.getMessage());
- Log.w(TAG, "Host could not be resolved", e);
- } else if (e.getCause() instanceof SocketTimeoutException) {
- response.setStatus(-4);
- response.setErrorMessage("Request timed out: " + e.getMessage());
- Log.w(TAG, "Request timed out", e);
- } else {
- response.setStatus(-1);
- response.setErrorMessage("There was an error with the request: " + e.getCause().getMessage());
- Log.w(TAG, "Generic request error", e);
- }
- } catch (Exception e) {
- response.setStatus(-1);
- response.setErrorMessage(e.getMessage());
- Log.e(TAG, "An unexpected error occured", e);
- }
-
- try {
- if (response.hasFailed()) {
- this.callbackContext.error(response.toJSON());
- } else {
- this.callbackContext.success(response.toJSON());
- }
- } catch (JSONException e) {
- Log.e(TAG, "An unexpected error occured while processing HTTP response", e);
+ request.receive(file);
+ response.setFileEntry(fileEntry);
+ } else {
+ response.setErrorMessage("There was an error downloading the file");
}
}
}
diff --git a/src/android/com/silkimen/cordovahttp/CordovaHttpOperation.java b/src/android/com/silkimen/cordovahttp/CordovaHttpOperation.java
new file mode 100644
index 0000000..97fe824
--- /dev/null
+++ b/src/android/com/silkimen/cordovahttp/CordovaHttpOperation.java
@@ -0,0 +1,18 @@
+package com.silkimen.cordovahttp;
+
+import org.apache.cordova.CallbackContext;
+import org.json.JSONObject;
+
+class CordovaHttpOperation extends CordovaHttpBase {
+ public CordovaHttpOperation(String method, String url, String serializer, Object data, JSONObject headers,
+ int timeout, CallbackContext callbackContext) {
+
+ super(method, url, serializer, data, headers, timeout, callbackContext);
+ }
+
+ public CordovaHttpOperation(String method, String url, JSONObject params, JSONObject headers, int timeout,
+ CallbackContext callbackContext) {
+
+ super(method, url, params, headers, timeout, callbackContext);
+ }
+}
diff --git a/src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java b/src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java
index 8f73e00..9392ba3 100644
--- a/src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java
+++ b/src/android/com/silkimen/cordovahttp/CordovaHttpPlugin.java
@@ -83,10 +83,10 @@ public class CordovaHttpPlugin extends CordovaPlugin {
JSONObject headers = args.getJSONObject(2);
int timeout = args.getInt(3) * 1000;
- CordovaHttpRequest get = new CordovaHttpRequest(method.toUpperCase(), url, params, headers, timeout,
+ CordovaHttpOperation request = new CordovaHttpOperation(method.toUpperCase(), url, params, headers, timeout,
callbackContext);
- cordova.getThreadPool().execute(get);
+ cordova.getThreadPool().execute(request);
return true;
}
@@ -100,7 +100,7 @@ public class CordovaHttpPlugin extends CordovaPlugin {
JSONObject headers = args.getJSONObject(3);
int timeout = args.getInt(4) * 1000;
- CordovaHttpRequest request = new CordovaHttpRequest(method.toUpperCase(), url, serializer, data, headers, timeout,
+ CordovaHttpOperation request = new CordovaHttpOperation(method.toUpperCase(), url, serializer, data, headers, timeout,
callbackContext);
cordova.getThreadPool().execute(request);
diff --git a/src/android/com/silkimen/cordovahttp/CordovaHttpRequest.java b/src/android/com/silkimen/cordovahttp/CordovaHttpRequest.java
deleted file mode 100644
index 65b0a49..0000000
--- a/src/android/com/silkimen/cordovahttp/CordovaHttpRequest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package com.silkimen.cordovahttp;
-
-import java.io.ByteArrayOutputStream;
-
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import java.nio.ByteBuffer;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import com.silkimen.http.HttpBodyDecoder;
-import com.silkimen.http.HttpRequest;
-import com.silkimen.http.HttpRequest.HttpRequestException;
-import com.silkimen.http.JsonUtils;
-
-import org.apache.cordova.CallbackContext;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.util.Log;
-
-public class CordovaHttpRequest implements Runnable {
- private static final String TAG = "Cordova-Plugin-HTTP";
-
- private String method;
- private String url;
- private String serializer = "none";
- private Object data;
- private JSONObject params;
- private JSONObject headers;
- private int timeout;
- private CallbackContext callbackContext;
-
- public CordovaHttpRequest(String method, String url, String serializer, Object data, JSONObject headers,
- int timeout, CallbackContext callbackContext) {
-
- this.method = method;
- this.url = url;
- this.serializer = serializer;
- this.data = data;
- this.headers = headers;
- this.timeout = timeout;
- this.callbackContext = callbackContext;
- }
-
- public CordovaHttpRequest(String method, String url, JSONObject params, JSONObject headers, int timeout,
- CallbackContext callbackContext) {
-
- this.method = method;
- this.url = url;
- this.params = params;
- this.headers = headers;
- this.timeout = timeout;
- this.callbackContext = callbackContext;
- }
-
- @Override
- public void run() {
- CordovaHttpResponse response = new CordovaHttpResponse();
-
- try {
- String processedUrl = HttpRequest.encode(HttpRequest.append(this.url, JsonUtils.getObjectMap(this.params)));
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-
- HttpRequest request = new HttpRequest(processedUrl, this.method)
- .followRedirects(true /* @TODO */)
- .readTimeout(this.timeout)
- .acceptCharset("UTF-8")
- .uncompress(true);
-
- // setup content type before applying headers, so user can override it
- this.setContentType(request)
- .headers(JsonUtils.getStringMap(this.headers));
-
- this.sendBody(request)
- .receive(outputStream);
-
- ByteBuffer rawOutput = ByteBuffer.wrap(outputStream.toByteArray());
- String decodedBody = HttpBodyDecoder.decodeBody(rawOutput, request.charset());
-
- response.setStatus(request.code());
- response.setUrl(request.url().toString());
- response.setHeaders(request.headers());
-
- if (request.code() >= 200 && request.code() < 300) {
- response.setBody(decodedBody);
- } else {
- response.setErrorMessage(decodedBody);
- }
- } catch (HttpRequestException e) {
- if (e.getCause() instanceof SSLHandshakeException) {
- response.setStatus(-2);
- response.setErrorMessage("SSL handshake failed: " + e.getMessage());
- Log.w(TAG, "SSL handshake failed", e);
- } else if (e.getCause() instanceof UnknownHostException) {
- response.setStatus(-3);
- response.setErrorMessage("Host could not be resolved: " + e.getMessage());
- Log.w(TAG, "Host could not be resolved", e);
- } else if (e.getCause() instanceof SocketTimeoutException) {
- response.setStatus(-4);
- response.setErrorMessage("Request timed out: " + e.getMessage());
- Log.w(TAG, "Request timed out", e);
- } else {
- response.setStatus(-1);
- response.setErrorMessage("There was an error with the request: " + e.getCause().getMessage());
- Log.w(TAG, "Generic request error", e);
- }
- } catch (Exception e) {
- response.setStatus(-1);
- response.setErrorMessage(e.getMessage());
- Log.e(TAG, "An unexpected error occured", e);
- }
-
- try {
- if (response.hasFailed()) {
- this.callbackContext.error(response.toJSON());
- } else {
- this.callbackContext.success(response.toJSON());
- }
- } catch (JSONException e) {
- Log.e(TAG, "An unexpected error occured while processing HTTP response", e);
- }
- }
-
- private HttpRequest setContentType(HttpRequest request) {
- switch(this.serializer) {
- case "json":
- return request.contentType("application/json", "UTF-8");
- case "utf8":
- return request.contentType("text/plain", "UTF-8");
- case "urlencoded":
- // intentionally left blank, because content type is set in HttpRequest.form()
- }
-
- return request;
- }
-
- private HttpRequest sendBody(HttpRequest request) throws JSONException {
- if (this.data == null) {
- return request;
- }
-
- switch (this.serializer) {
- case "json":
- return request.send(this.data.toString());
- case "utf8":
- return request.send(((JSONObject) this.data).getString("text"));
- case "urlencoded":
- return request.form(JsonUtils.getObjectMap((JSONObject) this.data));
- }
-
- return request;
- }
-}
diff --git a/src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java b/src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java
index 8d96b50..31e0e8a 100644
--- a/src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java
+++ b/src/android/com/silkimen/cordovahttp/CordovaHttpUpload.java
@@ -1,128 +1,39 @@
package com.silkimen.cordovahttp;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
+import android.webkit.MimeTypeMap;
-import java.net.SocketTimeoutException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.UnknownHostException;
-
-import java.nio.ByteBuffer;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import com.silkimen.http.HttpBodyDecoder;
import com.silkimen.http.HttpRequest;
-import com.silkimen.http.HttpRequest.HttpRequestException;
-import com.silkimen.http.JsonUtils;
+
+import java.io.File;
+import java.net.URI;
import org.apache.cordova.CallbackContext;
-
-import org.json.JSONException;
import org.json.JSONObject;
-import android.webkit.MimeTypeMap;
-import android.util.Log;
-class CordovaHttpUpload implements Runnable {
- private static final String TAG = "Cordova-Plugin-HTTP";
-
- private String url;
- private JSONObject params;
- private JSONObject headers;
+class CordovaHttpUpload extends CordovaHttpBase {
private String filePath;
private String uploadName;
- private int timeout;
- private CallbackContext callbackContext;
public CordovaHttpUpload(String url, JSONObject params, JSONObject headers, String filePath, String uploadName,
int timeout, CallbackContext callbackContext) {
- this.url = url;
- this.params = params;
- this.headers = headers;
+ super("POST", url, params, headers, timeout, callbackContext);
this.filePath = filePath;
this.uploadName = uploadName;
- this.timeout = timeout;
- this.callbackContext = callbackContext;
}
@Override
- public void run() {
- CordovaHttpResponse response = new CordovaHttpResponse();
+ protected void sendBody(HttpRequest request) throws Exception {
+ int filenameIndex = this.filePath.lastIndexOf('/');
+ String filename = this.filePath.substring(filenameIndex + 1);
- try {
- String processedUrl = HttpRequest.encode(HttpRequest.append(this.url, JsonUtils.getObjectMap(this.params)));
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ int extIndex = this.filePath.lastIndexOf('.');
+ String ext = this.filePath.substring(extIndex + 1);
- HttpRequest request = new HttpRequest(processedUrl, "POST")
- .followRedirects(true /* @TODO */)
- .readTimeout(this.timeout)
- .acceptCharset("UTF-8")
- .uncompress(true)
- .headers(JsonUtils.getStringMap(this.headers));
+ MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
+ String mimeType = mimeTypeMap.getMimeTypeFromExtension(ext);
- int filenameIndex = filePath.lastIndexOf('/');
- String filename = filePath.substring(filenameIndex + 1);
-
- int extIndex = filePath.lastIndexOf('.');
- String ext = filePath.substring(extIndex + 1);
-
- MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
- String mimeType = mimeTypeMap.getMimeTypeFromExtension(ext);
-
- request.part(this.uploadName, filename, mimeType, new File(new URI(this.filePath)))
- .receive(outputStream);
-
- ByteBuffer rawOutput = ByteBuffer.wrap(outputStream.toByteArray());
- String decodedBody = HttpBodyDecoder.decodeBody(rawOutput, request.charset());
-
- response.setStatus(request.code());
- response.setUrl(request.url().toString());
- response.setHeaders(request.headers());
-
- if (request.code() >= 200 && request.code() < 300) {
- response.setBody(decodedBody);
- } else {
- response.setErrorMessage(decodedBody);
- }
- } catch (HttpRequestException e) {
- if (e.getCause() instanceof SSLHandshakeException) {
- response.setStatus(-2);
- response.setErrorMessage("SSL handshake failed: " + e.getMessage());
- Log.w(TAG, "SSL handshake failed", e);
- } else if (e.getCause() instanceof UnknownHostException) {
- response.setStatus(-3);
- response.setErrorMessage("Host could not be resolved: " + e.getMessage());
- Log.w(TAG, "Host could not be resolved", e);
- } else if (e.getCause() instanceof SocketTimeoutException) {
- response.setStatus(-4);
- response.setErrorMessage("Request timed out: " + e.getMessage());
- Log.w(TAG, "Request timed out", e);
- } else {
- response.setStatus(-1);
- response.setErrorMessage("There was an error with the request: " + e.getCause().getMessage());
- Log.w(TAG, "Generic request error", e);
- }
- } catch (URISyntaxException e) {
- response.setStatus(-1);
- response.setErrorMessage("An error occured while loading file");
- Log.e(TAG, "An error occured while loading file", e);
- } catch (Exception e) {
- response.setStatus(-1);
- response.setErrorMessage(e.getMessage());
- Log.e(TAG, "An unexpected error occured", e);
- }
-
- try {
- if (response.hasFailed()) {
- this.callbackContext.error(response.toJSON());
- } else {
- this.callbackContext.success(response.toJSON());
- }
- } catch (JSONException e) {
- Log.e(TAG, "An unexpected error occured while processing HTTP response", e);
- }
+ request.part(this.uploadName, filename, mimeType, new File(new URI(this.filePath)));
}
}
diff --git a/src/android/com/synconset/cordovahttp/CordovaHttp.java b/src/android/com/synconset/cordovahttp/CordovaHttp.java
deleted file mode 100644
index ee14091..0000000
--- a/src/android/com/synconset/cordovahttp/CordovaHttp.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
- * A HTTP plugin for Cordova / Phonegap
- */
-package com.synconset.cordovahttp;
-
-import org.apache.cordova.CallbackContext;
-
-import org.json.JSONException;
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import java.io.ByteArrayOutputStream;
-import java.nio.ByteBuffer;
-
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.MalformedInputException;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.Iterator;
-
-import android.text.TextUtils;
-
-import com.silkimen.http.HttpBodyDecoder;
-import com.silkimen.http.HttpRequest;
-import com.silkimen.http.HttpRequest.HttpRequestException;
-
-abstract class CordovaHttp {
- protected static final String TAG = "CordovaHTTP";
- private static AtomicBoolean disableRedirect = new AtomicBoolean(false);
-
- private String urlString;
- private Object params;
- private String serializerName;
- private JSONObject headers;
- private int timeoutInMilliseconds;
- private CallbackContext callbackContext;
-
- public CordovaHttp(String urlString, Object params, JSONObject headers, int timeout,
- CallbackContext callbackContext) {
- this(urlString, params, "default", headers, timeout, callbackContext);
- }
-
- public CordovaHttp(String urlString, Object params, String serializerName, JSONObject headers, int timeout,
- CallbackContext callbackContext) {
- this.urlString = urlString;
- this.params = params;
- this.serializerName = serializerName;
- this.headers = headers;
- this.timeoutInMilliseconds = timeout;
- this.callbackContext = callbackContext;
-
-
- }
-
- public static void disableRedirect(boolean disable) {
- disableRedirect.set(disable);
- }
-
- protected String getUrlString() {
- return this.urlString;
- }
-
- protected Object getParamsObject() {
- return this.params;
- }
-
- protected String getSerializerName() {
- return this.serializerName;
- }
-
- protected HashMap getParamsMap() throws JSONException, Exception {
- if (this.params instanceof JSONObject) {
- return this.getMapFromJSONObject((JSONObject) this.params);
- } else {
- throw new Exception("unsupported params type, needs to be a JSON object");
- }
- }
-
- protected JSONObject getHeadersObject() {
- return this.headers;
- }
-
- protected HashMap getHeadersMap() throws JSONException {
- return this.getStringMapFromJSONObject(this.headers);
- }
-
- protected int getRequestTimeout() {
- return this.timeoutInMilliseconds;
- }
-
- protected CallbackContext getCallbackContext() {
- return this.callbackContext;
- }
-
- protected HttpRequest setupRedirect(HttpRequest request) {
- if (disableRedirect.get()) {
- request.followRedirects(false);
- }
-
- return request;
- }
-
- protected void setupDataSerializer(HttpRequest request) throws JSONException, Exception {
- if ("json".equals(this.getSerializerName())) {
- request.contentType(request.CONTENT_TYPE_JSON, request.CHARSET_UTF8);
- } else if ("utf8".equals(this.getSerializerName())) {
- request.contentType("text/plain", request.CHARSET_UTF8);
- }
- }
-
- protected void respondWithError(int status, String msg) {
- try {
- JSONObject response = new JSONObject();
- response.put("status", status);
- response.put("error", msg);
- this.callbackContext.error(response);
- } catch (JSONException e) {
- this.callbackContext.error(msg);
- }
- }
-
- protected void respondWithError(String msg) {
- this.respondWithError(-1, msg);
- }
-
- protected void addResponseHeaders(HttpRequest request, JSONObject response) throws JSONException {
- Map> headers = request.headers();
- Map filteredHeaders = new HashMap();
-
- for (Map.Entry> entry : headers.entrySet()) {
- String key = entry.getKey();
- List value = entry.getValue();
-
- if ((key != null) && (!value.isEmpty())) {
- filteredHeaders.put(key.toLowerCase(), TextUtils.join(", ", value));
- }
- }
-
- response.put("headers", new JSONObject(filteredHeaders));
- }
-
- protected HashMap getStringMapFromJSONObject(JSONObject object) throws JSONException {
- HashMap map = new HashMap();
- Iterator> i = object.keys();
-
- while (i.hasNext()) {
- String key = (String) i.next();
- map.put(key, object.getString(key));
- }
- return map;
- }
-
- protected ArrayList getListFromJSONArray(JSONArray array) throws JSONException {
- ArrayList list = new ArrayList();
-
- for (int i = 0; i < array.length(); i++) {
- list.add(array.get(i));
- }
- return list;
- }
-
- protected HashMap getMapFromJSONObject(JSONObject object) throws JSONException {
- HashMap map = new HashMap();
- Iterator> i = object.keys();
-
- while (i.hasNext()) {
- String key = (String) i.next();
- Object value = object.get(key);
-
- if (value instanceof JSONArray) {
- map.put(key, getListFromJSONArray((JSONArray) value));
- } else {
- map.put(key, object.get(key));
- }
- }
- return map;
- }
-
- protected void prepareRequest(HttpRequest request) throws HttpRequestException, JSONException {
- this.setupRedirect(request);
-
- request.readTimeout(this.getRequestTimeout());
- // request.acceptCharset(ACCEPTED_CHARSETS);
- request.headers(this.getHeadersMap());
- request.uncompress(true);
- }
-
- protected void prepareRequestBody(HttpRequest request) throws JSONException, Exception {
- if ("json".equals(this.getSerializerName())) {
- request.send(this.getParamsObject().toString());
- } else if ("utf8".equals(this.getSerializerName())) {
- request.send(this.getParamsMap().get("text").toString());
- } else {
- request.form(this.getParamsMap());
- }
- }
-
- protected void returnResponseObject(HttpRequest request) throws HttpRequestException {
- try {
- JSONObject response = new JSONObject();
- int code = request.code();
-
- final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- request.receive(outputStream);
- ByteBuffer rawOutput = ByteBuffer.wrap(outputStream.toByteArray());
-
- //request.body(rawOutput);
- response.put("status", code);
- response.put("url", request.url().toString());
- this.addResponseHeaders(request, response);
-
- if (code >= 200 && code < 300) {
- response.put("data", HttpBodyDecoder.decodeBody(rawOutput, request.charset()));
- this.getCallbackContext().success(response);
- } else {
- response.put("error", HttpBodyDecoder.decodeBody(rawOutput, request.charset()));
- this.getCallbackContext().error(response);
- }
- } catch (JSONException e) {
- this.respondWithError("There was an error generating the response");
- } catch (MalformedInputException e) {
- this.respondWithError("Could not decode response data due to malformed data");
- } catch (CharacterCodingException e) {
- this.respondWithError("Could not decode response data due to invalid or unknown charset encoding");
- }
- }
-
- protected void handleHttpRequestException(HttpRequestException e) {
- if (e.getCause() instanceof UnknownHostException) {
- this.respondWithError(0, "The host could not be resolved: " + e.getMessage());
- } else if (e.getCause() instanceof SocketTimeoutException) {
- this.respondWithError(1, "The request timed out: " + e.getMessage());
- } else if (e.getCause() instanceof SSLHandshakeException) {
- this.respondWithError(-2, "SSL handshake failed: " + e.getMessage());
- } else {
- this.respondWithError("There was an error with the request: " + e.getMessage());
- }
- }
-}
diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpDelete.java b/src/android/com/synconset/cordovahttp/CordovaHttpDelete.java
deleted file mode 100644
index 4857828..0000000
--- a/src/android/com/synconset/cordovahttp/CordovaHttpDelete.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * A HTTP plugin for Cordova / Phonegap
- */
-package com.synconset.cordovahttp;
-
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import org.apache.cordova.CallbackContext;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import com.silkimen.http.HttpRequest;
-import com.silkimen.http.HttpRequest.HttpRequestException;
-
-class CordovaHttpDelete extends CordovaHttp implements Runnable {
- public CordovaHttpDelete(String urlString, Object data, JSONObject headers, int timeout, CallbackContext callbackContext) {
- super(urlString, data, headers, timeout, callbackContext);
- }
-
- @Override
- public void run() {
- try {
- HttpRequest request = HttpRequest.delete(this.getUrlString(), this.getParamsMap(), false);
-
- this.prepareRequest(request);
- this.returnResponseObject(request);
- } catch (HttpRequestException e) {
- this.handleHttpRequestException(e);
- } catch (Exception e) {
- this.respondWithError(e.getMessage());
- }
- }
-}
diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpHead.java b/src/android/com/synconset/cordovahttp/CordovaHttpHead.java
deleted file mode 100644
index 224788a..0000000
--- a/src/android/com/synconset/cordovahttp/CordovaHttpHead.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * A HTTP plugin for Cordova / Phonegap
- */
-package com.synconset.cordovahttp;
-
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import org.apache.cordova.CallbackContext;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import com.silkimen.http.HttpRequest;
-import com.silkimen.http.HttpRequest.HttpRequestException;
-
-class CordovaHttpHead extends CordovaHttp implements Runnable {
- public CordovaHttpHead(String urlString, Object params, JSONObject headers, int timeout, CallbackContext callbackContext) {
- super(urlString, params, headers, timeout, callbackContext);
- }
-
- @Override
- public void run() {
- try {
- HttpRequest request = HttpRequest.head(this.getUrlString(), this.getParamsMap(), false);
-
- this.prepareRequest(request);
- this.returnResponseObject(request);
- } catch (HttpRequestException e) {
- this.handleHttpRequestException(e);
- } catch (Exception e) {
- this.respondWithError(e.getMessage());
- }
- }
-}
diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpPatch.java b/src/android/com/synconset/cordovahttp/CordovaHttpPatch.java
deleted file mode 100644
index e6015cf..0000000
--- a/src/android/com/synconset/cordovahttp/CordovaHttpPatch.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * A HTTP plugin for Cordova / Phonegap
- */
-package com.synconset.cordovahttp;
-
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import org.apache.cordova.CallbackContext;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import com.silkimen.http.HttpRequest;
-import com.silkimen.http.HttpRequest.HttpRequestException;
-
-class CordovaHttpPatch extends CordovaHttp implements Runnable {
- public CordovaHttpPatch(String urlString, Object params, String serializerName, JSONObject headers, int timeout, CallbackContext callbackContext) {
- super(urlString, params, serializerName, headers, timeout, callbackContext);
- }
-
- @Override
- public void run() {
- try {
- /* todo */
- HttpRequest request = HttpRequest.get(this.getUrlString());
-
- this.setupDataSerializer(request);
- this.prepareRequest(request);
- this.prepareRequestBody(request);
- this.returnResponseObject(request);
- } catch (HttpRequestException e) {
- this.handleHttpRequestException(e);
- } catch (Exception e) {
- this.respondWithError(e.getMessage());
- }
- }
-}
diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpPost.java b/src/android/com/synconset/cordovahttp/CordovaHttpPost.java
deleted file mode 100644
index 4696086..0000000
--- a/src/android/com/synconset/cordovahttp/CordovaHttpPost.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * A HTTP plugin for Cordova / Phonegap
- */
-package com.synconset.cordovahttp;
-
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import org.apache.cordova.CallbackContext;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import com.silkimen.http.HttpRequest;
-import com.silkimen.http.HttpRequest.HttpRequestException;
-
-class CordovaHttpPost extends CordovaHttp implements Runnable {
- public CordovaHttpPost(String urlString, Object params, String serializerName, JSONObject headers, int timeout, CallbackContext callbackContext) {
- super(urlString, params, serializerName, headers, timeout, callbackContext);
- }
-
- @Override
- public void run() {
- try {
- HttpRequest request = HttpRequest.post(this.getUrlString());
-
- this.setupDataSerializer(request);
- this.prepareRequest(request);
- this.prepareRequestBody(request);
- this.returnResponseObject(request);
- } catch (HttpRequestException e) {
- this.handleHttpRequestException(e);
- } catch (Exception e) {
- this.respondWithError(e.getMessage());
- }
- }
-}
diff --git a/src/android/com/synconset/cordovahttp/CordovaHttpPut.java b/src/android/com/synconset/cordovahttp/CordovaHttpPut.java
deleted file mode 100644
index 0386b4a..0000000
--- a/src/android/com/synconset/cordovahttp/CordovaHttpPut.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * A HTTP plugin for Cordova / Phonegap
- */
-package com.synconset.cordovahttp;
-
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import org.apache.cordova.CallbackContext;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import com.silkimen.http.HttpRequest;
-import com.silkimen.http.HttpRequest.HttpRequestException;
-
-class CordovaHttpPut extends CordovaHttp implements Runnable {
- public CordovaHttpPut(String urlString, Object data, String serializerName, JSONObject headers, int timeout, CallbackContext callbackContext) {
- super(urlString, data, serializerName, headers, timeout, callbackContext);
- }
-
- @Override
- public void run() {
- try {
- HttpRequest request = HttpRequest.put(this.getUrlString());
-
- this.setupDataSerializer(request);
- this.prepareRequest(request);
- this.prepareRequestBody(request);
- this.returnResponseObject(request);
- } catch (HttpRequestException e) {
- this.handleHttpRequestException(e);
- } catch (Exception e) {
- this.respondWithError(e.getMessage());
- }
- }
-}