Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add initial HTTP request library

  • Loading branch information...
commit 585a935495467a10a409dd157bbfce82d85edb9f 0 parents
@kevinsawicki kevinsawicki authored
3  .gitignore
@@ -0,0 +1,3 @@
+bin
+*~
+
15 README.md
@@ -0,0 +1,15 @@
+# Http-Request
+
+A simple convenience library for using a [HttpURLConnection](http://download.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html)
+
+## Examples
+Perform a GET request and get the status of the response
+
+```java
+int response = HttpRequest.get("http://google.com").code();
+```
+
+Perform a POST request with some data and get the status of the response
+```java
+int response = HttpRequest.post("http://google.com).body("name=kevin").code();
+```
8 lib/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
23 lib/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>http-request</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
12 lib/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Thu Oct 20 14:41:25 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
55 lib/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,55 @@
+#Fri Oct 21 20:48:40 CEST 2011
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
103 lib/pom.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.github.kevinsawicki</groupId>
+ <artifactId>http-request</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <url>https://github.com/kevinsawicki/http-request</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <licenses>
+ <license>
+ <name>MIT License</name>
+ <url>http://www.opensource.org/licenses/mit-license.php</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <scm>
+ <url>https://github.com/kevinsawicki/http-request</url>
+ <connection>scm:git:git://github.com/kevinsawicki/http-request.git
+ </connection>
+ <developerConnection>scm:git:git@github.com:kevinsawicki/http-request.git
+ </developerConnection>
+ </scm>
+
+ <developers>
+ <developer>
+ <email>kevinsawicki@gmail.com</email>
+ <name>Kevin Sawicki</name>
+ <url>https://github.com/kevinsawicki</url>
+ <id>kevinsawicki</id>
+ </developer>
+ </developers>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addDefaultImplementationEntries>true
+ </addDefaultImplementationEntries>
+ <addDefaultSpecificationEntries>true
+ </addDefaultSpecificationEntries>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>8.0.3.v20111011</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
808 lib/src/main/java/com/github/kevinsawicki/http/HttpRequest.java
@@ -0,0 +1,808 @@
+/*
+ * Copyright (c) 2011 Kevin Sawicki <kevinsawicki@gmail.com>
+ *
+ * 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 java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * A fluid interface for making HTTP requests using an underlying
+ * {@link HttpURLConnection} (or sub-class).
+ */
+public class HttpRequest {
+
+ /**
+ * 'GET' request method
+ */
+ public static final String METHOD_GET = "GET";
+
+ /**
+ * 'HEAD' request method
+ */
+ public static final String METHOD_HEAD = "HEAD";
+
+ /**
+ * 'DELETE' request method
+ */
+ public static final String METHOD_DELETE = "DELETE";
+
+ /**
+ * 'OPTIONS' options method
+ */
+ public static final String METHOD_OPTIONS = "OPTIONS";
+
+ /**
+ * 'POST' request method
+ */
+ public static final String METHOD_POST = "POST";
+
+ /**
+ * 'PUT' request method
+ */
+ public static final String METHOD_PUT = "PUT";
+
+ /**
+ * 'TRACE' request method
+ */
+ public static final String METHOD_TRACE = "TRACE";
+
+ private static final String BOUNDARY = "----1010101010";
+
+ /**
+ * Request exception
+ */
+ public static class RequestException extends RuntimeException {
+
+ /** serialVersionUID */
+ private static final long serialVersionUID = -1170466989781746231L;
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public RequestException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * @param message
+ */
+ public RequestException(String message) {
+ super(message);
+ }
+
+ /**
+ * @param cause
+ */
+ public RequestException(Throwable cause) {
+ super(cause);
+ }
+ }
+
+ /**
+ * Start a 'GET' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest get(String url) throws RequestException {
+ return new HttpRequest(url, METHOD_GET);
+ }
+
+ /**
+ * Start a 'GET' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest get(URL url) throws RequestException {
+ return new HttpRequest(url, METHOD_GET);
+ }
+
+ /**
+ * Start a 'POST' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest post(String url) throws RequestException {
+ return new HttpRequest(url, METHOD_POST);
+ }
+
+ /**
+ * Start a 'POST' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest post(URL url) throws RequestException {
+ return new HttpRequest(url, METHOD_POST);
+ }
+
+ /**
+ * Start a 'PUT' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest put(String url) throws RequestException {
+ return new HttpRequest(url, METHOD_PUT);
+ }
+
+ /**
+ * Start a 'PUT' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest put(URL url) throws RequestException {
+ return new HttpRequest(url, METHOD_PUT);
+ }
+
+ /**
+ * Start a 'DELETE' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest delete(String url) throws RequestException {
+ return new HttpRequest(url, METHOD_DELETE);
+ }
+
+ /**
+ * Start a 'DELETE' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest delete(URL url) throws RequestException {
+ return new HttpRequest(url, METHOD_DELETE);
+ }
+
+ /**
+ * Start a 'HEAD' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest head(String url) throws RequestException {
+ return new HttpRequest(url, METHOD_HEAD);
+ }
+
+ /**
+ * Start a 'HEAD' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest head(URL url) throws RequestException {
+ return new HttpRequest(url, METHOD_HEAD);
+ }
+
+ /**
+ * Start a 'OPTIONS' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest options(String url) throws RequestException {
+ return new HttpRequest(url, METHOD_OPTIONS);
+ }
+
+ /**
+ * Start a 'OPTIONS' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest options(URL url) throws RequestException {
+ return new HttpRequest(url, METHOD_OPTIONS);
+ }
+
+ /**
+ * Start a 'TRACE' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest trace(String url) throws RequestException {
+ return new HttpRequest(url, METHOD_TRACE);
+ }
+
+ /**
+ * Start a 'TRACE' request to the given URL
+ *
+ * @param url
+ * @return request
+ * @throws RequestException
+ */
+ public static HttpRequest trace(URL url) throws RequestException {
+ return new HttpRequest(url, METHOD_TRACE);
+ }
+
+ private final HttpURLConnection connection;
+
+ private DataOutputStream output;
+
+ private int bufferSize = 8196;
+
+ /**
+ * Create HTTP connection wrapper
+ *
+ * @param url
+ * @param method
+ * @throws RequestException
+ */
+ public HttpRequest(String url, String method) throws RequestException {
+ try {
+ connection = (HttpURLConnection) new URL(url).openConnection();
+ connection.setRequestMethod(method);
+ } catch (IOException e) {
+ throw new RequestException(e);
+ }
+ }
+
+ /**
+ * Create HTTP connection wrapper
+ *
+ * @param url
+ * @param method
+ * @throws RequestException
+ */
+ public HttpRequest(URL url, String method) throws RequestException {
+ try {
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod(method);
+ } catch (IOException e) {
+ throw new RequestException(e);
+ }
+ }
+
+ /**
+ * Get underlying connection
+ *
+ * @return connection
+ */
+ public HttpURLConnection getConnection() {
+ return connection;
+ }
+
+ /**
+ * Get the status code of the response
+ *
+ * @return this request
+ * @throws RequestException
+ */
+ public int code() throws RequestException {
+ closeOutput();
+ try {
+ return connection.getResponseCode();
+ } catch (IOException e) {
+ throw new RequestException(e);
+ }
+ }
+
+ /**
+ * Get status message of the response
+ *
+ * @return message
+ */
+ public String message() {
+ closeOutput();
+ try {
+ return connection.getResponseMessage();
+ } catch (IOException e) {
+ throw new RequestException(e);
+ }
+ }
+
+ /**
+ * Disconnect the connection
+ *
+ * @return this request
+ */
+ public HttpRequest disconnect() {
+ connection.disconnect();
+ return this;
+ }
+
+ /**
+ * Set the buffer size used when copying between streams
+ *
+ * @param size
+ * @return this request
+ */
+ public HttpRequest bufferSize(int size) {
+ if (size < 1)
+ throw new IllegalArgumentException("Size must be greater than zero");
+ bufferSize = size;
+ return this;
+ }
+
+ /**
+ * Get response as String
+ *
+ * @return string
+ * @throws RequestException
+ */
+ public String string() throws RequestException {
+ final ByteArrayOutputStream output = new ByteArrayOutputStream(
+ contentLength());
+ copy(buffer(), output);
+ final String charset = charset();
+ if (charset == null)
+ return output.toString();
+ try {
+ return output.toString(charset);
+ } catch (UnsupportedEncodingException e) {
+ throw new RequestException(e);
+ }
+ }
+
+ /**
+ * Get response as byte array
+ *
+ * @return byte array
+ * @throws RequestException
+ */
+ public byte[] bytes() throws RequestException {
+ final ByteArrayOutputStream output = new ByteArrayOutputStream(
+ contentLength());
+ copy(buffer(), output);
+ return output.toByteArray();
+ }
+
+ /**
+ * Get response in a buffered stream
+ *
+ * @return stream
+ * @throws RequestException
+ */
+ public BufferedInputStream buffer() throws RequestException {
+ return new BufferedInputStream(stream());
+ }
+
+ /**
+ * Get stream to response
+ *
+ * @return stream
+ * @throws RequestException
+ */
+ public InputStream stream() throws RequestException {
+ try {
+ return connection.getInputStream();
+ } catch (IOException e) {
+ throw new RequestException(e);
+ }
+ }
+
+ /**
+ * Set read timeout on connection to value
+ *
+ * @param timeout
+ * @return this request
+ */
+ public HttpRequest readTimeout(int timeout) {
+ connection.setReadTimeout(timeout);
+ return this;
+ }
+
+ /**
+ * Set header name to given value
+ *
+ * @param name
+ * @param value
+ * @return this request
+ */
+ public HttpRequest header(String name, String value) {
+ connection.setRequestProperty(name, value);
+ return this;
+ }
+
+ /**
+ * Get a response header
+ *
+ * @param name
+ * @return response header
+ */
+ public String header(String name) {
+ return connection.getHeaderField(name);
+ }
+
+ /**
+ * Get 'charset' parameter from 'Content-Type' response header
+ *
+ * @return charset or null if none
+ */
+ public String charset() {
+ String contentType = contentType();
+ if (contentType == null || contentType.length() == 0)
+ return null;
+ int postSemi = contentType.indexOf(';') + 1;
+ if (postSemi > 0 && postSemi == contentType.length())
+ return null;
+ String[] params = contentType.substring(postSemi).split(";");
+ final String charsetParam = "charset";
+ for (String param : params) {
+ String[] split = param.split("=");
+ if (split.length != 2)
+ continue;
+ if (!charsetParam.equals(split[0]))
+ continue;
+
+ String charset = split[1];
+ int length = charset.length();
+ if (length == 0)
+ continue;
+ if (length > 2 && '"' == charset.charAt(0)
+ && '"' == charset.charAt(length - 1))
+ charset = charset.substring(1, length - 1);
+ return charset;
+ }
+ return null;
+ }
+
+ /**
+ * Set the 'User-Agent' header to given value
+ *
+ * @param value
+ * @return this request
+ */
+ public HttpRequest userAgent(String value) {
+ return header("User-Agent", value);
+ }
+
+ /**
+ * Set the 'Host' header to given value
+ *
+ * @param value
+ * @return this request
+ */
+ public HttpRequest host(String value) {
+ return header("Host", value);
+ }
+
+ /**
+ * Set the 'Accept-Encoding' header to given value
+ *
+ * @param value
+ * @return this request
+ */
+ public HttpRequest acceptEncoding(String value) {
+ return header("Accept-Encoding", value);
+ }
+
+ /**
+ * Get the 'Content-Encoding' header from the response
+ *
+ * @return this request
+ */
+ public String contentEncoding() {
+ return header("Content-Encoding");
+ }
+
+ /**
+ * Get the 'Server' header from the response
+ *
+ * @return server
+ */
+ public String server() {
+ return header("Server");
+ }
+
+ /**
+ * Get the 'Date' header from the response
+ *
+ * @return date value, -1 on failures
+ */
+ public long date() {
+ return connection.getHeaderFieldDate("Date", -1L);
+ }
+
+ /**
+ * Get the 'Expires' header from the response
+ *
+ * @return expires value, -1 on failures
+ */
+ public long expires() {
+ return connection.getHeaderFieldDate("Expires", -1L);
+ }
+
+ /**
+ * Set the 'Authentication' header to given value
+ *
+ * @param value
+ * @return this request
+ */
+ public HttpRequest authentication(final String value) {
+ return header("Authentication", value);
+ }
+
+ /**
+ * Set the 'Content-Type' request header to the given value
+ *
+ * @param value
+ * @return this request
+ */
+ public HttpRequest contentType(final String value) {
+ return header("Content-Type", value);
+ }
+
+ /**
+ * Get the 'Content-Type' header from the response
+ *
+ * @return response header value
+ */
+ public String contentType() {
+ return header("Content-Type");
+ }
+
+ /**
+ * Get the 'Content-Type' header from the response
+ *
+ * @return response header value
+ */
+ public int contentLength() {
+ return connection.getHeaderFieldInt("Content-Length", -1);
+ }
+
+ /**
+ * Set the 'Content-Length' request header to the given value
+ *
+ * @param value
+ * @return this request
+ */
+ public HttpRequest contentLength(final String value) {
+ return header("Content-Length", value);
+ }
+
+ /**
+ * Set the 'Accept' header to given value
+ *
+ * @param value
+ * @return this request
+ */
+ public HttpRequest accept(final String value) {
+ return header("Accept", value);
+ }
+
+ /**
+ * Copy between streams
+ *
+ * @param input
+ * @param output
+ * @return this request
+ * @throws RequestException
+ */
+ protected HttpRequest copy(final InputStream input,
+ final OutputStream output) throws RequestException {
+ final byte[] buffer = new byte[bufferSize];
+ int read;
+ try {
+ while ((read = input.read(buffer)) != -1)
+ output.write(buffer, 0, read);
+ } catch (IOException e) {
+ throw new RequestException(e);
+ } finally {
+ try {
+ input.close();
+ } catch (IOException e) {
+ throw new RequestException(e);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Close output stream
+ *
+ * @return this request
+ * @throws RequestException
+ */
+ protected HttpRequest closeOutput() throws RequestException {
+ if (output == null)
+ return this;
+ try {
+ output.writeBytes("\r\n--");
+ output.writeBytes(BOUNDARY);
+ output.writeBytes("--\r\n");
+ output.close();
+ output = null;
+ } catch (IOException e) {
+ throw new RequestException(e);
+ }
+ return this;
+ }
+
+ /**
+ * Write part to stream
+ *
+ * @param name
+ * @param value
+ * @return this request
+ * @throws RequestException
+ */
+ public HttpRequest part(final String name, final Object value)
+ throws RequestException {
+ try {
+ if (output == null) {
+ output = new DataOutputStream(connection.getOutputStream());
+ contentType("multipart/form-data; boundary=" + BOUNDARY);
+ output.writeBytes("--");
+ output.writeBytes(BOUNDARY);
+ output.writeBytes("\r\n");
+ } else
+ output.writeBytes("\r\n--" + BOUNDARY + "\r\n");
+
+ output.writeBytes("Content-Disposition: form-data; name=\"");
+ output.writeBytes(name);
+ output.writeBytes("\"\r\n\r\n");
+ if (value instanceof InputStream)
+ copy((InputStream) value, output);
+ else
+ output.writeBytes(value.toString());
+ } catch (IOException e) {
+ throw new RequestException(e);
+ }
+ return this;
+ }
+
+ /**
+ * Write stream to request body
+ *
+ * @param input
+ * @return this request
+ * @throws RequestException
+ */
+ public HttpRequest body(final InputStream input) throws RequestException {
+ connection.setDoOutput(true);
+ try {
+ copy(input, connection.getOutputStream());
+ } catch (IOException e) {
+ throw new RequestException(e);
+ }
+ return this;
+ }
+
+ /**
+ * Write string as UTF-8 bytes to request body
+ *
+ * @param value
+ * @return this request
+ * @throws RequestException
+ */
+ public HttpRequest body(final String value) throws RequestException {
+ return body(value, "UTF-8");
+ }
+
+ /**
+ * Write string in given charset to request body.
+ * <p>
+ * The platform's default charset will be used if charset is null
+ *
+ * @param value
+ * @param charset
+ * @return this request
+ * @throws RequestException
+ */
+ public HttpRequest body(final String value, final String charset)
+ throws RequestException {
+ connection.setDoOutput(true);
+ final byte[] bytes;
+ if (charset != null)
+ try {
+ bytes = value.getBytes(charset);
+ } catch (UnsupportedEncodingException e) {
+ throw new RequestException(e);
+ }
+ else
+ bytes = value.getBytes();
+ return body(new ByteArrayInputStream(bytes));
+ }
+
+ /**
+ * Configure HTTPS connection to trust all certificates
+ *
+ * @return this request
+ * @throws RequestException
+ */
+ public HttpRequest trustAllCerts() throws RequestException {
+ if (!(connection instanceof HttpsURLConnection))
+ return this;
+ final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+
+ public void checkClientTrusted(X509Certificate[] chain,
+ String authType) throws CertificateException {
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain,
+ String authType) throws CertificateException {
+ }
+ } };
+ final SSLContext context;
+ try {
+ context = SSLContext.getInstance("TLS");
+ context.init(null, trustAllCerts, new SecureRandom());
+ } catch (KeyManagementException e) {
+ throw new RequestException(e);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RequestException(e);
+ }
+ ((HttpsURLConnection) connection).setSSLSocketFactory(context
+ .getSocketFactory());
+ return this;
+ }
+
+ /**
+ * Configured HTTPS connection to trust all hosts
+ *
+ * @return this request
+ */
+ public HttpRequest trustAllHosts() {
+ if (!(connection instanceof HttpsURLConnection))
+ return this;
+ ((HttpsURLConnection) connection)
+ .setHostnameVerifier(new HostnameVerifier() {
+
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ });
+ return this;
+ }
+}
141 lib/src/test/java/com/github/kevinsawicki/http/RequestTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2011 Kevin Sawicki <kevinsawicki@gmail.com>
+ *
+ * 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 com.github.kevinsawicki.http.HttpRequest.get;
+import static com.github.kevinsawicki.http.HttpRequest.post;
+import static org.junit.Assert.assertEquals;
+
+import java.net.HttpURLConnection;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.Request;
+import org.junit.Test;
+
+/**
+ * Unit tests of HttpRequest
+ */
+public class RequestTest extends ServerTestCase {
+
+ /**
+ * Make a GET request with an empty body response
+ *
+ * @throws Exception
+ */
+ @Test
+ public void getEmpty() throws Exception {
+ final AtomicReference<String> method = new AtomicReference<String>();
+ String url = setUp(new RequestHandler() {
+
+ public void handle(Request request, HttpServletResponse response) {
+ method.set(request.getMethod());
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ });
+ HttpRequest request = get(url);
+ int code = request.code();
+ assertEquals("GET", method.get());
+ assertEquals(HttpURLConnection.HTTP_OK, code);
+ assertEquals("", request.string());
+ }
+
+ /**
+ * Make a POST request with an empty request body
+ *
+ * @throws Exception
+ */
+ @Test
+ public void postEmpty() throws Exception {
+ final AtomicReference<String> method = new AtomicReference<String>();
+ String url = setUp(new RequestHandler() {
+
+ public void handle(Request request, HttpServletResponse response) {
+ method.set(request.getMethod());
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ });
+ int code = post(url).code();
+ assertEquals("POST", method.get());
+ assertEquals(HttpURLConnection.HTTP_OK, code);
+ }
+
+ /**
+ * Make a POST request with a non-empty request body
+ *
+ * @throws Exception
+ */
+ @Test
+ public void postNonEmptyString() throws Exception {
+ final AtomicReference<String> body = new AtomicReference<String>();
+ String url = setUp(new RequestHandler() {
+
+ public void handle(Request request, HttpServletResponse response) {
+ body.set(new String(read()));
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ });
+ int code = post(url).body("hello").code();
+ assertEquals(HttpURLConnection.HTTP_OK, code);
+ assertEquals("hello", body.get());
+ }
+
+ /**
+ * Make a GET request for a non-empty response body
+ *
+ * @throws Exception
+ */
+ @Test
+ public void getNonEmptyString() throws Exception {
+ String url = setUp(new RequestHandler() {
+
+ public void handle(Request request, HttpServletResponse response) {
+ response.setStatus(HttpServletResponse.SC_OK);
+ write("hello");
+ }
+ });
+ HttpRequest request = get(url);
+ assertEquals(HttpURLConnection.HTTP_OK, request.code());
+ assertEquals("hello", request.string());
+ assertEquals("hello".getBytes().length, request.contentLength());
+ }
+
+ /**
+ * Make a GET request with a response that includes a charset parameter
+ *
+ * @throws Exception
+ */
+ @Test
+ public void getWithResponseCharset() throws Exception {
+ String url = setUp(new RequestHandler() {
+
+ public void handle(Request request, HttpServletResponse response) {
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("text/html; charset=UTF-8");
+ }
+ });
+ HttpRequest request = get(url);
+ assertEquals(HttpURLConnection.HTTP_OK, request.code());
+ assertEquals("UTF-8", request.charset());
+ }
+}
146 lib/src/test/java/com/github/kevinsawicki/http/ServerTestCase.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2011 Kevin Sawicki <kevinsawicki@gmail.com>
+ *
+ * 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 java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.junit.After;
+
+/**
+ * Base test case that provides a running HTTP server
+ */
+public class ServerTestCase {
+
+ /**
+ * Simplified handler
+ */
+ protected static abstract class RequestHandler extends AbstractHandler {
+
+ private Request request;
+
+ private HttpServletResponse response;
+
+ /**
+ * Handle request
+ *
+ * @param request
+ * @param response
+ */
+ public abstract void handle(Request request,
+ HttpServletResponse response);
+
+ /**
+ * Read content
+ *
+ * @return content
+ */
+ protected byte[] read() {
+ byte[] content = new byte[request.getContentLength()];
+ try {
+ request.getInputStream().read(content);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return content;
+ }
+
+ /**
+ * Write value
+ *
+ * @param value
+ */
+ protected void write(String value) {
+ try {
+ response.getWriter().print(value);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Write line
+ *
+ * @param value
+ */
+ protected void writeln(String value) {
+ try {
+ response.getWriter().println(value);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void handle(String target, Request baseRequest,
+ HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException {
+ this.request = (Request) request;
+ this.response = response;
+ this.request.setHandled(true);
+ handle(this.request, response);
+ }
+
+ }
+
+ /**
+ * Server
+ */
+ protected Server server;
+
+ /**
+ * Set up server with handler
+ *
+ * @param handler
+ * @return port
+ * @throws Exception
+ */
+ public String setUp(final Handler handler) throws Exception {
+ server = new Server();
+ if (handler != null)
+ server.setHandler(handler);
+ Connector connector = new SelectChannelConnector();
+ connector.setPort(0);
+ server.setConnectors(new Connector[] { connector });
+ server.start();
+ return "http://localhost:" + connector.getLocalPort();
+ }
+
+ /**
+ * Tear down server if created
+ *
+ * @throws Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ if (server != null)
+ server.stop();
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.