/**
* junit-rules: JUnit Rules Library
*
* Copyright (c) 2009-2011 by Alistair A. Israel.
* This software is made available under the terms of the MIT License.
*
* Created Sep 1, 2009
*/
package junit.rules.httpserver;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URI;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
/**
* <p>
* Simplifies the effort to write an {@link HttpHandler}.
* <p>
* <p>
* With contributions by <a href="https://github.com/beobal">Sam Tunnicliffe</a>.
* </p>
*
* @author Alistair A. Israel
*/
public class SimpleHttpHandler implements HttpHandler {
/**
* {@value #GET}
*/
private static final String GET = "GET";
/**
* {@value #POST}
*/
private static final String POST = "POST";
/**
* {@value #PUT}
*/
private static final String PUT = "PUT";
/**
* {@value #DELETE}
*/
private static final String DELETE = "DELETE";
/**
* HTTP OK ({@value #HTTP_OK})
*
* @see HttpURLConnection#HTTP_OK
*/
public static final int HTTP_OK = HttpURLConnection.HTTP_OK;
private HttpExchange httpExchange;
private ByteArrayOutputStream out;
private PrintWriter pw;
private int responseCodeSent;
/**
* {@inheritDoc}
*
* @see com.sun.net.httpserver.HttpHandler#handle(com.sun.net.httpserver.HttpExchange)
*/
@Override
public final void handle(final HttpExchange exchange) throws IOException {
this.httpExchange = exchange;
this.out = new ByteArrayOutputStream();
this.pw = new PrintWriter(out);
responseCodeSent = -1;
final String requestMethod = exchange.getRequestMethod();
if (GET.equalsIgnoreCase(requestMethod)) {
onGet();
} else if (POST.equalsIgnoreCase(requestMethod)) {
onPost();
} else if (PUT.equalsIgnoreCase(requestMethod)) {
onPut();
} else if (DELETE.equalsIgnoreCase(requestMethod)) {
onDelete();
}
if (responseCodeSent == -1) {
sendResponse(HTTP_OK);
}
}
/**
* @return the httpExchange
*/
public final HttpExchange getHttpExchange() {
return httpExchange;
}
/**
* Get the request URI
*
* @return the request URI
* @see com.sun.net.httpserver.HttpExchange#getRequestURI()
*/
protected final URI getRequestURI() {
return httpExchange.getRequestURI();
}
/**
* Returns a stream from which the request body can be read. Multiple calls to this method will return the same
* stream. It is recommended that applications should consume (read) all of the data from this stream before closing
* it. If a stream is closed before all data has been read, then the close() call will read and discard remaining
* data (up to an implementation specific number of bytes).
*
* @return the stream from which the request body can be read.
* @see com.sun.net.httpserver.HttpExchange#getRequestBody()
*/
protected final InputStream getRequestBody() {
return httpExchange.getRequestBody();
}
/**
* Returns an immutable Map containing the HTTP headers that were included with this request. The keys in this Map
* will be the header names, while the values will be a List of Strings containing each value that was included
* (either for a header that was listed several times, or one that accepts a comma-delimited list of values on a
* single line). In either of these cases, the values for the header name will be presented in the order that they
* were included in the request.
*
* @return a read-only Map which can be used to access request headers
* @see com.sun.net.httpserver.HttpExchange#getRequestHeaders()
*/
protected final Headers getRequestHeaders() {
return httpExchange.getRequestHeaders();
}
/**
* Get the request method
*
* @return the request method
* @see com.sun.net.httpserver.HttpExchange#getRequestMethod()
*/
protected final String getRequestMethod() {
return httpExchange.getRequestMethod();
}
/**
* Returns a {@link PrintWriter} to the response buffer used to calculate the byte length of the actual HTTP
* response to be sent later.
*
* @return a {@link PrintWriter}
*/
protected final PrintWriter getResponseWriter() {
return this.pw;
}
/**
* Returns a mutable Map into which the HTTP response headers can be stored and which will be transmitted as part of
* this response. The keys in the Map will be the header names, while the values must be a List of Strings
* containing each value that should be included multiple times (in the order that they should be included).
*
* @return a writable Map which can be used to set response headers.
* @see com.sun.net.httpserver.HttpExchange#getResponseHeaders()
*/
protected final Headers getResponseHeaders() {
return httpExchange.getResponseHeaders();
}
/**
* @throws IOException
* on exception
*/
protected void onGet() throws IOException {
}
/**
* @throws IOException
* on exception
*/
protected void onPost() throws IOException {
}
/**
* @throws IOException
* on exception
*/
protected void onPut() throws IOException {
}
/**
* @throws IOException
* on exception
*/
protected void onDelete() throws IOException {
}
/**
* @param responseCode
* the HTTP response code to send
* @throws IOException
* on exception
*/
protected final void sendResponse(final int responseCode) throws IOException {
pw.flush();
httpExchange.sendResponseHeaders(responseCode, out.size());
final OutputStream responseBody = httpExchange.getResponseBody();
out.writeTo(responseBody);
responseBody.flush();
httpExchange.close();
responseCodeSent = responseCode;
}
}