aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorritchie <ritchie@gmx.at>2015-05-10 13:41:19 +0200
committerritchie <ritchie@gmx.at>2015-05-10 13:41:19 +0200
commit9058464950a9734da0a7ff2dc47f3081bbb5117c (patch)
tree6e6ab43930c3d0e134dc194e4a8a4a57cb1c7e7f
parenta59803b641f7eee45cfd0cf170e669dfe2b1eb8d (diff)
downloadnanohttpd-9058464950a9734da0a7ff2dc47f3081bbb5117c.tar.gz
after the last pull request in this series the formatter is now active
-rw-r--r--core/src/main/java/fi/iki/elonen/NanoHTTPD.java548
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpChunkedResponseTest.java39
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpDeleteRequestTest.java68
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpGetRequestTest.java29
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpHeadRequestTest.java16
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpKeepAliveTest.java43
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpParsingTest.java1
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpPostRequestTest.java109
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpPutRequestTest.java16
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpServerTest.java27
-rw-r--r--core/src/test/java/fi/iki/elonen/HttpSessionHeadersTest.java10
-rw-r--r--core/src/test/java/fi/iki/elonen/InvalidRequestTest.java7
-rw-r--r--core/src/test/java/fi/iki/elonen/integration/CookieIntegrationTest.java11
-rw-r--r--core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java7
-rw-r--r--core/src/test/java/fi/iki/elonen/integration/IntegrationTestBase.java5
-rw-r--r--core/src/test/java/fi/iki/elonen/integration/PutStreamIntegrationTest.java10
-rw-r--r--markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPlugin.java20
-rw-r--r--markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPluginInfo.java21
-rw-r--r--pom.xml41
-rw-r--r--samples/src/main/java/fi/iki/elonen/HelloServer.java50
-rw-r--r--samples/src/main/java/fi/iki/elonen/TempFilesServer.java12
-rw-r--r--samples/src/main/java/fi/iki/elonen/debug/DebugServer.java28
-rw-r--r--webserver/src/main/java/fi/iki/elonen/InternalRewrite.java5
-rw-r--r--webserver/src/main/java/fi/iki/elonen/ServerRunner.java5
-rw-r--r--webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java164
-rw-r--r--webserver/src/main/java/fi/iki/elonen/WebServerPlugin.java5
-rw-r--r--webserver/src/main/java/fi/iki/elonen/WebServerPluginInfo.java6
-rw-r--r--websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java201
-rw-r--r--websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java15
-rw-r--r--websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java2
-rw-r--r--websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java4
31 files changed, 857 insertions, 668 deletions
diff --git a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java
index 5132bbf..0705196 100644
--- a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java
+++ b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java
@@ -72,7 +72,6 @@ import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
-
import java.security.KeyStore;
import javax.net.ssl.*;
@@ -81,7 +80,10 @@ import javax.net.ssl.*;
* <p/>
* <p/>
* NanoHTTPD
- * <p>Copyright (c) 2012-2013 by Paul S. Hawke, 2001,2005-2013 by Jarno Elonen, 2010 by Konstantinos Togias</p>
+ * <p>
+ * Copyright (c) 2012-2013 by Paul S. Hawke, 2001,2005-2013 by Jarno Elonen,
+ * 2010 by Konstantinos Togias
+ * </p>
* <p/>
* <p/>
* <b>Features + limitations: </b>
@@ -90,8 +92,10 @@ import javax.net.ssl.*;
* <li>Only one Java file</li>
* <li>Java 5 compatible</li>
* <li>Released as open source, Modified BSD licence</li>
- * <li>No fixed config files, logging, authorization etc. (Implement yourself if you need them.)</li>
- * <li>Supports parameter parsing of GET and POST methods (+ rudimentary PUT support in 1.25)</li>
+ * <li>No fixed config files, logging, authorization etc. (Implement yourself if
+ * you need them.)</li>
+ * <li>Supports parameter parsing of GET and POST methods (+ rudimentary PUT
+ * support in 1.25)</li>
* <li>Supports both dynamic content and file serving</li>
* <li>Supports file upload (since version 1.2, 2010)</li>
* <li>Supports partial content (streaming)</li>
@@ -106,7 +110,8 @@ import javax.net.ssl.*;
* <li>File server supports simple skipping for files (continue download)</li>
* <li>File server serves also very long files without memory overhead</li>
* <li>Contains a built-in list of most common MIME types</li>
- * <li>All header names are converted to lower case so they don't vary between browsers/clients</li>
+ * <li>All header names are converted to lower case so they don't vary between
+ * browsers/clients</li>
* <p/>
* </ul>
* <p/>
@@ -118,43 +123,56 @@ import javax.net.ssl.*;
* <p/>
* </ul>
* <p/>
- * See the separate "LICENSE.md" file for the distribution license (Modified BSD licence)
+ * See the separate "LICENSE.md" file for the distribution license (Modified BSD
+ * licence)
*/
public abstract class NanoHTTPD {
+
/**
* Maximum time to wait on Socket.getInputStream().read() (in milliseconds)
- * This is required as the Keep-Alive HTTP connections would otherwise
- * block the socket reading thread forever (or as long the browser is open).
+ * This is required as the Keep-Alive HTTP connections would otherwise block
+ * the socket reading thread forever (or as long the browser is open).
*/
public static final int SOCKET_READ_TIMEOUT = 5000;
+
/**
* Common MIME type for dynamic content: plain text
*/
public static final String MIME_PLAINTEXT = "text/plain";
+
/**
* Common MIME type for dynamic content: html
*/
public static final String MIME_HTML = "text/html";
+
/**
- * Pseudo-Parameter to use to store the actual query string in the parameters map for later re-processing.
+ * Pseudo-Parameter to use to store the actual query string in the
+ * parameters map for later re-processing.
*/
private static final String QUERY_STRING_PARAMETER = "NanoHttpd.QUERY_STRING";
-
- /**
- * logger to log to.
- */
- private static Logger LOG = Logger.getLogger(NanoHTTPD.class.getName());
-
+
+ /**
+ * logger to log to.
+ */
+ private static Logger LOG = Logger.getLogger(NanoHTTPD.class.getName());
+
private final String hostname;
+
private final int myPort;
+
private ServerSocket myServerSocket;
+
private Set<Socket> openConnections = new HashSet<Socket>();
+
private SSLServerSocketFactory sslServerSocketFactory;
+
private Thread myThread;
+
/**
* Pluggable strategy for asynchronously executing requests.
*/
private AsyncRunner asyncRunner;
+
/**
* Pluggable strategy for creating and cleaning up temporary files.
*/
@@ -182,86 +200,84 @@ public abstract class NanoHTTPD {
try {
closeable.close();
} catch (IOException e) {
- LOG.log(Level.SEVERE, "Could not close",e);
+ LOG.log(Level.SEVERE, "Could not close", e);
}
}
}
- /**
- * Creates an SSLSocketFactory for HTTPS.
- *
- * Pass a KeyStore resource with your certificate and passphrase
- */
- public static SSLServerSocketFactory makeSSLSocketFactory(String keyAndTrustStoreClasspathPath, char[] passphrase) throws IOException {
- SSLServerSocketFactory res = null;
- try {
- KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
- InputStream keystoreStream = NanoHTTPD.class.getResourceAsStream(keyAndTrustStoreClasspathPath);
- keystore.load(keystoreStream, passphrase);
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- trustManagerFactory.init(keystore);
- KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- keyManagerFactory.init(keystore, passphrase);
- SSLContext ctx = SSLContext.getInstance("TLS");
- ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
- res = ctx.getServerSocketFactory();
- } catch (Exception e) {
- throw new IOException(e.getMessage());
- }
- return res;
- }
-
- /**
- * Creates an SSLSocketFactory for HTTPS.
- *
- * Pass a loaded KeyStore and a loaded KeyManagerFactory.
- * These objects must properly loaded/initialized by the caller.
- */
- public static SSLServerSocketFactory makeSSLSocketFactory(KeyStore loadedKeyStore, KeyManagerFactory loadedKeyFactory) throws IOException {
- SSLServerSocketFactory res = null;
- try {
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- trustManagerFactory.init(loadedKeyStore);
- SSLContext ctx = SSLContext.getInstance("TLS");
- ctx.init(loadedKeyFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
- res = ctx.getServerSocketFactory();
- } catch (Exception e) {
- throw new IOException(e.getMessage());
- }
- return res;
- }
-
- /**
- * Creates an SSLSocketFactory for HTTPS.
- *
- * Pass a loaded KeyStore and an array of loaded KeyManagers.
- * These objects must properly loaded/initialized by the caller.
- */
- public static SSLServerSocketFactory makeSSLSocketFactory(KeyStore loadedKeyStore, KeyManager[] keyManagers) throws IOException {
- SSLServerSocketFactory res = null;
- try {
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- trustManagerFactory.init(loadedKeyStore);
- SSLContext ctx = SSLContext.getInstance("TLS");
- ctx.init(keyManagers, trustManagerFactory.getTrustManagers(), null);
- res = ctx.getServerSocketFactory();
- } catch (Exception e) {
- throw new IOException(e.getMessage());
- }
- return res;
- }
-
- /**
- * Call before start() to serve over HTTPS instead of HTTP
- */
- public void makeSecure(SSLServerSocketFactory sslServerSocketFactory) {
- this.sslServerSocketFactory = sslServerSocketFactory;
- }
+ /**
+ * Creates an SSLSocketFactory for HTTPS. Pass a KeyStore resource with your
+ * certificate and passphrase
+ */
+ public static SSLServerSocketFactory makeSSLSocketFactory(String keyAndTrustStoreClasspathPath, char[] passphrase) throws IOException {
+ SSLServerSocketFactory res = null;
+ try {
+ KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ InputStream keystoreStream = NanoHTTPD.class.getResourceAsStream(keyAndTrustStoreClasspathPath);
+ keystore.load(keystoreStream, passphrase);
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(keystore);
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ keyManagerFactory.init(keystore, passphrase);
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
+ res = ctx.getServerSocketFactory();
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ return res;
+ }
+
+ /**
+ * Creates an SSLSocketFactory for HTTPS. Pass a loaded KeyStore and a
+ * loaded KeyManagerFactory. These objects must properly loaded/initialized
+ * by the caller.
+ */
+ public static SSLServerSocketFactory makeSSLSocketFactory(KeyStore loadedKeyStore, KeyManagerFactory loadedKeyFactory) throws IOException {
+ SSLServerSocketFactory res = null;
+ try {
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(loadedKeyStore);
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(loadedKeyFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
+ res = ctx.getServerSocketFactory();
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ return res;
+ }
+
+ /**
+ * Creates an SSLSocketFactory for HTTPS. Pass a loaded KeyStore and an
+ * array of loaded KeyManagers. These objects must properly
+ * loaded/initialized by the caller.
+ */
+ public static SSLServerSocketFactory makeSSLSocketFactory(KeyStore loadedKeyStore, KeyManager[] keyManagers) throws IOException {
+ SSLServerSocketFactory res = null;
+ try {
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(loadedKeyStore);
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(keyManagers, trustManagerFactory.getTrustManagers(), null);
+ res = ctx.getServerSocketFactory();
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ return res;
+ }
+
+ /**
+ * Call before start() to serve over HTTPS instead of HTTP
+ */
+ public void makeSecure(SSLServerSocketFactory sslServerSocketFactory) {
+ this.sslServerSocketFactory = sslServerSocketFactory;
+ }
/**
* Start the server.
- *
- * @throws IOException if the socket is in use.
+ *
+ * @throws IOException
+ * if the socket is in use.
*/
public void start() throws IOException {
if (sslServerSocketFactory != null) {
@@ -275,6 +291,7 @@ public abstract class NanoHTTPD {
myServerSocket.bind((hostname != null) ? new InetSocketAddress(hostname, myPort) : new InetSocketAddress(myPort));
myThread = new Thread(new Runnable() {
+
@Override
public void run() {
do {
@@ -284,6 +301,7 @@ public abstract class NanoHTTPD {
finalAccept.setSoTimeout(SOCKET_READ_TIMEOUT);
final InputStream inputStream = finalAccept.getInputStream();
asyncRunner.exec(new Runnable() {
+
@Override
public void run() {
OutputStream outputStream = null;
@@ -295,13 +313,15 @@ public abstract class NanoHTTPD {
session.execute();
}
} catch (Exception e) {
- // When the socket is closed by the client, we throw our own SocketException
- // to break the "keep alive" loop above. If the exception was anything other
- // than the expected SocketException OR a SocketTimeoutException, print the
+ // When the socket is closed by the client,
+ // we throw our own SocketException
+ // to break the "keep alive" loop above. If
+ // the exception was anything other
+ // than the expected SocketException OR a
+ // SocketTimeoutException, print the
// stacktrace
- if (!(e instanceof SocketException && "NanoHttpd Shutdown".equals(e.getMessage())) &&
- !(e instanceof SocketTimeoutException)) {
- LOG.log(Level.FINE, "Communication with the client broken", e);
+ if (!(e instanceof SocketException && "NanoHttpd Shutdown".equals(e.getMessage())) && !(e instanceof SocketTimeoutException)) {
+ LOG.log(Level.FINE, "Communication with the client broken", e);
}
} finally {
safeClose(outputStream);
@@ -312,7 +332,7 @@ public abstract class NanoHTTPD {
}
});
} catch (IOException e) {
- LOG.log(Level.FINE, "Communication with the client broken", e);
+ LOG.log(Level.FINE, "Communication with the client broken", e);
}
} while (!myServerSocket.isClosed());
}
@@ -333,14 +353,15 @@ public abstract class NanoHTTPD {
myThread.join();
}
} catch (Exception e) {
- LOG.log(Level.SEVERE, "Could not stop all connections", e);
+ LOG.log(Level.SEVERE, "Could not stop all connections", e);
}
}
/**
* Registers that a new connection has been set up.
- *
- * @param socket the {@link Socket} for the connection.
+ *
+ * @param socket
+ * the {@link Socket} for the connection.
*/
public synchronized void registerConnection(Socket socket) {
openConnections.add(socket);
@@ -348,7 +369,7 @@ public abstract class NanoHTTPD {
/**
* Registers that a connection has been closed
- *
+ *
* @param socket
* the {@link Socket} for the connection.
*/
@@ -382,16 +403,21 @@ public abstract class NanoHTTPD {
* <p/>
* <p/>
* (By default, this returns a 404 "Not Found" plain text error response.)
- *
- * @param uri Percent-decoded URI without parameters, for example "/index.cgi"
- * @param method "GET", "POST" etc.
- * @param parms Parsed, percent decoded parameters from URI and, in case of POST, data.
- * @param headers Header entries, percent decoded
+ *
+ * @param uri
+ * Percent-decoded URI without parameters, for example
+ * "/index.cgi"
+ * @param method
+ * "GET", "POST" etc.
+ * @param parms
+ * Parsed, percent decoded parameters from URI and, in case of
+ * POST, data.
+ * @param headers
+ * Header entries, percent decoded
* @return HTTP response, see class Response for details
*/
@Deprecated
- public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms,
- Map<String, String> files) {
+ public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms, Map<String, String> files) {
return new Response(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "Not Found");
}
@@ -400,8 +426,9 @@ public abstract class NanoHTTPD {
* <p/>
* <p/>
* (By default, this returns a 404 "Not Found" plain text error response.)
- *
- * @param session The HTTP session
+ *
+ * @param session
+ * The HTTP session
* @return HTTP response, see class Response for details
*/
public Response serve(IHTTPSession session) {
@@ -424,39 +451,46 @@ public abstract class NanoHTTPD {
/**
* Decode percent encoded <code>String</code> values.
- *
- * @param str the percent encoded <code>String</code>
- * @return expanded form of the input, for example "foo%20bar" becomes "foo bar"
+ *
+ * @param str
+ * the percent encoded <code>String</code>
+ * @return expanded form of the input, for example "foo%20bar" becomes
+ * "foo bar"
*/
protected String decodePercent(String str) {
String decoded = null;
try {
decoded = URLDecoder.decode(str, "UTF8");
} catch (UnsupportedEncodingException ignored) {
- LOG.log(Level.WARNING, "Encoding not supported, ignored", ignored);
+ LOG.log(Level.WARNING, "Encoding not supported, ignored", ignored);
}
return decoded;
}
/**
- * Decode parameters from a URL, handing the case where a single parameter name might have been
- * supplied several times, by return lists of values. In general these lists will contain a single
- * element.
- *
- * @param parms original <b>NanoHTTPD</b> parameters values, as passed to the <code>serve()</code> method.
- * @return a map of <code>String</code> (parameter name) to <code>List&lt;String&gt;</code> (a list of the values supplied).
+ * Decode parameters from a URL, handing the case where a single parameter
+ * name might have been supplied several times, by return lists of values.
+ * In general these lists will contain a single element.
+ *
+ * @param parms
+ * original <b>NanoHTTPD</b> parameters values, as passed to the
+ * <code>serve()</code> method.
+ * @return a map of <code>String</code> (parameter name) to
+ * <code>List&lt;String&gt;</code> (a list of the values supplied).
*/
protected Map<String, List<String>> decodeParameters(Map<String, String> parms) {
return this.decodeParameters(parms.get(QUERY_STRING_PARAMETER));
}
/**
- * Decode parameters from a URL, handing the case where a single parameter name might have been
- * supplied several times, by return lists of values. In general these lists will contain a single
- * element.
- *
- * @param queryString a query string pulled from the URL.
- * @return a map of <code>String</code> (parameter name) to <code>List&lt;String&gt;</code> (a list of the values supplied).
+ * Decode parameters from a URL, handing the case where a single parameter
+ * name might have been supplied several times, by return lists of values.
+ * In general these lists will contain a single element.
+ *
+ * @param queryString
+ * a query string pulled from the URL.
+ * @return a map of <code>String</code> (parameter name) to
+ * <code>List&lt;String&gt;</code> (a list of the values supplied).
*/
protected Map<String, List<String>> decodeParameters(String queryString) {
Map<String, List<String>> parms = new HashMap<String, List<String>>();
@@ -478,41 +512,53 @@ public abstract class NanoHTTPD {
return parms;
}
- // ------------------------------------------------------------------------------- //
+ // -------------------------------------------------------------------------------
+ // //
//
// Threading Strategy.
//
- // ------------------------------------------------------------------------------- //
+ // -------------------------------------------------------------------------------
+ // //
/**
* Pluggable strategy for asynchronously executing requests.
- *
- * @param asyncRunner new strategy for handling threads.
+ *
+ * @param asyncRunner
+ * new strategy for handling threads.
*/
public void setAsyncRunner(AsyncRunner asyncRunner) {
this.asyncRunner = asyncRunner;
}
- // ------------------------------------------------------------------------------- //
+ // -------------------------------------------------------------------------------
+ // //
//
// Temp file handling strategy.
//
- // ------------------------------------------------------------------------------- //
+ // -------------------------------------------------------------------------------
+ // //
/**
* Pluggable strategy for creating and cleaning up temporary files.
- *
- * @param tempFileManagerFactory new strategy for handling temp files.
+ *
+ * @param tempFileManagerFactory
+ * new strategy for handling temp files.
*/
public void setTempFileManagerFactory(TempFileManagerFactory tempFileManagerFactory) {
this.tempFileManagerFactory = tempFileManagerFactory;
}
/**
- * HTTP Request methods, with the ability to decode a <code>String</code> back to its enum value.
+ * HTTP Request methods, with the ability to decode a <code>String</code>
+ * back to its enum value.
*/
public enum Method {
- GET, PUT, POST, DELETE, HEAD, OPTIONS;
+ GET,
+ PUT,
+ POST,
+ DELETE,
+ HEAD,
+ OPTIONS;
static Method lookup(String method) {
for (Method m : Method.values()) {
@@ -528,6 +574,7 @@ public abstract class NanoHTTPD {
* Pluggable strategy for asynchronously executing requests.
*/
public interface AsyncRunner {
+
void exec(Runnable code);
}
@@ -535,18 +582,23 @@ public abstract class NanoHTTPD {
* Factory to create temp file managers.
*/
public interface TempFileManagerFactory {
+
TempFileManager create();
}
- // ------------------------------------------------------------------------------- //
+ // -------------------------------------------------------------------------------
+ // //
/**
* Temp file manager.
* <p/>
- * <p>Temp file managers are created 1-to-1 with incoming requests, to create and cleanup
- * temporary files created as a result of handling the request.</p>
+ * <p>
+ * Temp file managers are created 1-to-1 with incoming requests, to create
+ * and cleanup temporary files created as a result of handling the request.
+ * </p>
*/
public interface TempFileManager {
+
TempFile createTempFile() throws Exception;
void clear();
@@ -555,10 +607,13 @@ public abstract class NanoHTTPD {
/**
* A temp file.
* <p/>
- * <p>Temp files are responsible for managing the actual temporary storage and cleaning
- * themselves up when no longer needed.</p>
+ * <p>
+ * Temp files are responsible for managing the actual temporary storage and
+ * cleaning themselves up when no longer needed.
+ * </p>
*/
public interface TempFile {
+
OutputStream open() throws Exception;
void delete() throws Exception;
@@ -569,11 +624,14 @@ public abstract class NanoHTTPD {
/**
* Default threading strategy for NanoHTTPD.
* <p/>
- * <p>By default, the server spawns a new Thread for every incoming request. These are set
- * to <i>daemon</i> status, and named according to the request number. The name is
- * useful when profiling the application.</p>
+ * <p>
+ * By default, the server spawns a new Thread for every incoming request.
+ * These are set to <i>daemon</i> status, and named according to the request
+ * number. The name is useful when profiling the application.
+ * </p>
*/
public static class DefaultAsyncRunner implements AsyncRunner {
+
private long requestCount;
@Override
@@ -589,14 +647,17 @@ public abstract class NanoHTTPD {
/**
* Default strategy for creating and cleaning up temporary files.
* <p/>
- * <p>This class stores its files in the standard location (that is,
- * wherever <code>java.io.tmpdir</code> points to). Files are added
- * to an internal list, and deleted when no longer needed (that is,
- * when <code>clear()</code> is invoked at the end of processing a
- * request).</p>
+ * <p>
+ * This class stores its files in the standard location (that is, wherever
+ * <code>java.io.tmpdir</code> points to). Files are added to an internal
+ * list, and deleted when no longer needed (that is, when
+ * <code>clear()</code> is invoked at the end of processing a request).
+ * </p>
*/
public static class DefaultTempFileManager implements TempFileManager {
+
private final String tmpdir;
+
private final List<TempFile> tempFiles;
public DefaultTempFileManager() {
@@ -617,7 +678,7 @@ public abstract class NanoHTTPD {
try {
file.delete();
} catch (Exception ignored) {
- LOG.log(Level.WARNING, "could not delete file ", ignored);
+ LOG.log(Level.WARNING, "could not delete file ", ignored);
}
}
tempFiles.clear();
@@ -627,11 +688,15 @@ public abstract class NanoHTTPD {
/**
* Default strategy for creating and cleaning up temporary files.
* <p/>
- * <p>By default, files are created by <code>File.createTempFile()</code> in
- * the directory specified.</p>
+ * <p>
+ * By default, files are created by <code>File.createTempFile()</code> in
+ * the directory specified.
+ * </p>
*/
public static class DefaultTempFile implements TempFile {
+
private File file;
+
private OutputStream fstream;
public DefaultTempFile(String tempdir) throws IOException {
@@ -660,33 +725,40 @@ public abstract class NanoHTTPD {
* HTTP response. Return one of these from serve().
*/
public static class Response {
+
/**
* HTTP status code after processing, e.g. "200 OK", Status.OK
*/
private IStatus status;
+
/**
* MIME type of content, e.g. "text/html"
*/
private String mimeType;
+
/**
* Data of the response, may be null.
*/
private InputStream data;
+
/**
* Headers for the HTTP response. Use addHeader() to add lines.
*/
private Map<String, String> header = new HashMap<String, String>();
+
/**
* The request method that spawned this response.
*/
private Method requestMethod;
+
/**
* Use chunkedTransfer
*/
private boolean chunkedTransfer;
/**
- * Default constructor: response = Status.OK, mime = MIME_HTML and your supplied message
+ * Default constructor: response = Status.OK, mime = MIME_HTML and your
+ * supplied message
*/
public Response(String msg) {
this(Status.OK, MIME_HTML, msg);
@@ -710,7 +782,7 @@ public abstract class NanoHTTPD {
try {
this.data = txt != null ? new ByteArrayInputStream(txt.getBytes("UTF-8")) : null;
} catch (java.io.UnsupportedEncodingException uee) {
- LOG.log(Level.SEVERE,"encoding problem",uee);
+ LOG.log(Level.SEVERE, "encoding problem", uee);
}
}
@@ -769,7 +841,7 @@ public abstract class NanoHTTPD {
outputStream.flush();
safeClose(data);
} catch (IOException ioe) {
- LOG.log(Level.SEVERE, "Could not send response to the client", ioe);
+ LOG.log(Level.SEVERE, "Could not send response to the client", ioe);
}
}
@@ -784,7 +856,7 @@ public abstract class NanoHTTPD {
}
}
- pw.print("Content-Length: "+ size +"\r\n");
+ pw.print("Content-Length: " + size + "\r\n");
return size;
}
@@ -870,7 +942,9 @@ public abstract class NanoHTTPD {
}
public interface IStatus {
+
int getRequestStatus();
+
String getDescription();
}
@@ -878,11 +952,24 @@ public abstract class NanoHTTPD {
* Some HTTP response status codes
*/
public enum Status implements IStatus {
- SWITCH_PROTOCOL(101, "Switching Protocols"), OK(200, "OK"), CREATED(201, "Created"), ACCEPTED(202, "Accepted"), NO_CONTENT(204, "No Content"), PARTIAL_CONTENT(206, "Partial Content"), REDIRECT(301,
- "Moved Permanently"), NOT_MODIFIED(304, "Not Modified"), BAD_REQUEST(400, "Bad Request"), UNAUTHORIZED(401,
- "Unauthorized"), FORBIDDEN(403, "Forbidden"), NOT_FOUND(404, "Not Found"), METHOD_NOT_ALLOWED(405, "Method Not Allowed"), RANGE_NOT_SATISFIABLE(416,
- "Requested Range Not Satisfiable"), INTERNAL_ERROR(500, "Internal Server Error");
+ SWITCH_PROTOCOL(101, "Switching Protocols"),
+ OK(200, "OK"),
+ CREATED(201, "Created"),
+ ACCEPTED(202, "Accepted"),
+ NO_CONTENT(204, "No Content"),
+ PARTIAL_CONTENT(206, "Partial Content"),
+ REDIRECT(301, "Moved Permanently"),
+ NOT_MODIFIED(304, "Not Modified"),
+ BAD_REQUEST(400, "Bad Request"),
+ UNAUTHORIZED(401, "Unauthorized"),
+ FORBIDDEN(403, "Forbidden"),
+ NOT_FOUND(404, "Not Found"),
+ METHOD_NOT_ALLOWED(405, "Method Not Allowed"),
+ RANGE_NOT_SATISFIABLE(416, "Requested Range Not Satisfiable"),
+ INTERNAL_ERROR(500, "Internal Server Error");
+
private final int requestStatus;
+
private final String description;
Status(int requestStatus, String description) {
@@ -903,6 +990,7 @@ public abstract class NanoHTTPD {
}
public static final class ResponseException extends Exception {
+
private static final long serialVersionUID = 6569838532917408380L;
private final Response.Status status;
@@ -926,6 +1014,7 @@ public abstract class NanoHTTPD {
* Default strategy for creating and cleaning up temporary files.
*/
private class DefaultTempFileManagerFactory implements TempFileManagerFactory {
+
@Override
public TempFileManager create() {
return new DefaultTempFileManager();
@@ -933,9 +1022,11 @@ public abstract class NanoHTTPD {
}
/**
- * Handles one session, i.e. parses the HTTP request and returns the response.
+ * Handles one session, i.e. parses the HTTP request and returns the
+ * response.
*/
public interface IHTTPSession {
+
void execute() throws IOException;
Map<String, String> getParms();
@@ -957,24 +1048,39 @@ public abstract class NanoHTTPD {
/**
* Adds the files in the request body to the files map.
- * @param files map to modify
+ *
+ * @param files
+ * map to modify
*/
void parseBody(Map<String, String> files) throws IOException, ResponseException;
}
protected class HTTPSession implements IHTTPSession {
+
public static final int BUFSIZE = 8192;
+
private final TempFileManager tempFileManager;
+
private final OutputStream outputStream;
+
private PushbackInputStream inputStream;
+
private int splitbyte;
+
private int rlen;
+
private String uri;
+
private Method method;
+
private Map<String, String> parms;
+
private Map<String, String> headers;
+
private CookieHandler cookies;
+
private String queryParameterString;
+
private String remoteIp;
public HTTPSession(TempFileManager tempFileManager, InputStream inputStream, OutputStream outputStream) {
@@ -997,7 +1103,8 @@ public abstract class NanoHTTPD {
// Read the first 8192 bytes.
// The full header should fit in here.
// Apache's default header limit is 8KB.
- // Do NOT assume that a single read will get the entire header at once!
+ // Do NOT assume that a single read will get the entire header
+ // at once!
byte[] buf = new byte[BUFSIZE];
splitbyte = 0;
rlen = 0;
@@ -1030,17 +1137,16 @@ public abstract class NanoHTTPD {
}
parms = new HashMap<String, String>();
- if(null == headers) {
+ if (null == headers) {
headers = new HashMap<String, String>();
} else {
headers.clear();
}
if (null != remoteIp) {
- headers.put("remote-addr", remoteIp);
- headers.put("http-client-ip", remoteIp);
- }
-
+ headers.put("remote-addr", remoteIp);
+ headers.put("http-client-ip", remoteIp);
+ }
// Create a BufferedReader for parsing the header.
BufferedReader hin = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, rlen)));
@@ -1074,7 +1180,7 @@ public abstract class NanoHTTPD {
// treat socket timeouts the same way we treat socket exceptions
// i.e. close the stream & finalAccept object by throwing the
// exception up the call stack.
- throw ste;
+ throw ste;
} catch (IOException ioe) {
Response r = new Response(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
r.send(outputStream);
@@ -1108,7 +1214,7 @@ public abstract class NanoHTTPD {
// Now read all the body and write it to f
byte[] buf = new byte[512];
while (rlen >= 0 && size > 0) {
- rlen = inputStream.read(buf, 0, (int)Math.min(size, 512));
+ rlen = inputStream.read(buf, 0, (int) Math.min(size, 512));
size -= rlen;
if (rlen > 0) {
randomAccessFile.write(buf, 0, rlen);
@@ -1140,7 +1246,8 @@ public abstract class NanoHTTPD {
if ("multipart/form-data".equalsIgnoreCase(contentType)) {
// Handle multipart/form-data
if (!st.hasMoreTokens()) {
- throw new ResponseException(Response.Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html");
+ throw new ResponseException(Response.Status.BAD_REQUEST,
+ "BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html");
}
String boundaryStartString = "boundary=";
@@ -1164,10 +1271,12 @@ public abstract class NanoHTTPD {
postLine = postLineBuffer.toString().trim();
// Handle application/x-www-form-urlencoded
if ("application/x-www-form-urlencoded".equalsIgnoreCase(contentType)) {
- decodeParms(postLine, parms);
+ decodeParms(postLine, parms);
} else if (postLine.length() != 0) {
- // Special case for raw POST data => create a special files entry "postData" with raw content data
- files.put("postData", postLine);
+ // Special case for raw POST data => create a
+ // special files entry "postData" with raw content
+ // data
+ files.put("postData", postLine);
}
}
} else if (Method.PUT.equals(method)) {
@@ -1182,8 +1291,7 @@ public abstract class NanoHTTPD {
/**
* Decodes the sent headers and loads the data into Key/value pairs
*/
- private void decodeHeader(BufferedReader in, Map<String, String> pre, Map<String, String> parms, Map<String, String> headers)
- throws ResponseException {
+ private void decodeHeader(BufferedReader in, Map<String, String> pre, Map<String, String> parms, Map<String, String> headers) throws ResponseException {
try {
// Read the request line
String inLine = in.readLine();
@@ -1237,15 +1345,15 @@ public abstract class NanoHTTPD {
/**
* Decodes the Multipart Body data and put it into Key/Value pairs.
*/
- private void decodeMultipartData(String boundary, ByteBuffer fbuf, BufferedReader in, Map<String, String> parms,
- Map<String, String> files) throws ResponseException {
+ private void decodeMultipartData(String boundary, ByteBuffer fbuf, BufferedReader in, Map<String, String> parms, Map<String, String> files) throws ResponseException {
try {
int[] bpositions = getBoundaryPositions(fbuf, boundary.getBytes());
int boundarycount = 1;
String mpline = in.readLine();
while (mpline != null) {
if (!mpline.contains(boundary)) {
- throw new ResponseException(Response.Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but next chunk does not start with boundary. Usage: GET /example/file.html");
+ throw new ResponseException(Response.Status.BAD_REQUEST,
+ "BAD REQUEST: Content type is multipart/form-data but next chunk does not start with boundary. Usage: GET /example/file.html");
}
boundarycount++;
Map<String, String> item = new HashMap<String, String>();
@@ -1260,7 +1368,8 @@ public abstract class NanoHTTPD {
if (mpline != null) {
String contentDisposition = item.get("content-disposition");
if (contentDisposition == null) {
- throw new ResponseException(Response.Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but no content-disposition info found. Usage: GET /example/file.html");
+ throw new ResponseException(Response.Status.BAD_REQUEST,
+ "BAD REQUEST: Content type is multipart/form-data but no content-disposition info found. Usage: GET /example/file.html");
}
StringTokenizer st = new StringTokenizer(contentDisposition, ";");
Map<String, String> disposition = new HashMap<String, String>();
@@ -1293,14 +1402,14 @@ public abstract class NanoHTTPD {
}
int offset = stripMultipartHeaders(fbuf, bpositions[boundarycount - 2]);
String path = saveTmpFile(fbuf, offset, bpositions[boundarycount - 1] - offset - 4);
- if(!files.containsKey(pname)) {
- files.put(pname, path);
+ if (!files.containsKey(pname)) {
+ files.put(pname, path);
} else {
- int count = 2;
- while(files.containsKey(pname+count)) {
- count++;
- }
- files.put(pname+count, path);
+ int count = 2;
+ while (files.containsKey(pname + count)) {
+ count++;
+ }
+ files.put(pname + count, path);
}
value = disposition.get("filename");
value = value.substring(1, value.length() - 1);
@@ -1317,7 +1426,8 @@ public abstract class NanoHTTPD {
}
/**
- * Find byte index separating header from body. It must be the last byte of the first two sequential new lines.
+ * Find byte index separating header from body. It must be the last byte
+ * of the first two sequential new lines.
*/
private int findHeaderEnd(final byte[] buf, int rlen) {
int splitbyte = 0;
@@ -1361,7 +1471,8 @@ public abstract class NanoHTTPD {
}
/**
- * Retrieves the content of a sent file and saves it to a temporary file. The full path to the saved file is returned.
+ * Retrieves the content of a sent file and saves it to a temporary
+ * file. The full path to the saved file is returned.
*/
private String saveTmpFile(ByteBuffer b, int offset, int len) {
String path = "";
@@ -1389,12 +1500,13 @@ public abstract class NanoHTTPD {
TempFile tempFile = tempFileManager.createTempFile();
return new RandomAccessFile(tempFile.getName(), "rw");
} catch (Exception e) {
- throw new Error(e); // we won't recover, so throw an error
+ throw new Error(e); // we won't recover, so throw an error
}
}
/**
- * It returns the offset separating multipart file headers from the file's data.
+ * It returns the offset separating multipart file headers from the
+ * file's data.
*/
private int stripMultipartHeaders(ByteBuffer b, int offset) {
int i;
@@ -1407,8 +1519,10 @@ public abstract class NanoHTTPD {
}
/**
- * Decodes parameters in percent-encoded URI-format ( e.g. "name=Jack%20Daniels&pass=Single%20Malt" ) and
- * adds them to given Map. NOTE: this doesn't support multiple identical keys due to the simplicity of Map.
+ * Decodes parameters in percent-encoded URI-format ( e.g.
+ * "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given
+ * Map. NOTE: this doesn't support multiple identical keys due to the
+ * simplicity of Map.
*/
private void decodeParms(String parms, Map<String, String> p) {
if (parms == null) {
@@ -1422,8 +1536,7 @@ public abstract class NanoHTTPD {
String e = st.nextToken();
int sep = e.indexOf('=');
if (sep >= 0) {
- p.put(decodePercent(e.substring(0, sep)).trim(),
- decodePercent(e.substring(sep + 1)));
+ p.put(decodePercent(e.substring(0, sep)).trim(), decodePercent(e.substring(sep + 1)));
} else {
p.put(decodePercent(e).trim(), "");
}
@@ -1435,7 +1548,7 @@ public abstract class NanoHTTPD {
return parms;
}
- public String getQueryParameterString() {
+ public String getQueryParameterString() {
return queryParameterString;
}
@@ -1466,6 +1579,7 @@ public abstract class NanoHTTPD {
}
public static class Cookie {
+
private String n, v, e;
public Cookie(String name, String value, String expires) {
@@ -1499,14 +1613,16 @@ public abstract class NanoHTTPD {
}
/**
- * Provides rudimentary support for cookies.
- * Doesn't support 'path', 'secure' nor 'httpOnly'.
- * Feel free to improve it and/or add unsupported features.
- *
+ * Provides rudimentary support for cookies. Doesn't support 'path',
+ * 'secure' nor 'httpOnly'. Feel free to improve it and/or add unsupported
+ * features.
+ *
* @author LordFokas
*/
public class CookieHandler implements Iterable<String> {
+
private HashMap<String, String> cookies = new HashMap<String, String>();
+
private ArrayList<Cookie> queue = new ArrayList<Cookie>();
public CookieHandler(Map<String, String> httpHeaders) {
@@ -1522,14 +1638,16 @@ public abstract class NanoHTTPD {
}
}
- @Override public Iterator<String> iterator() {
+ @Override
+ public Iterator<String> iterator() {
return cookies.keySet().iterator();
}
/**
* Read a cookie from the HTTP Headers.
- *
- * @param name The cookie's name.
+ *
+ * @param name
+ * The cookie's name.
* @return The cookie's value if it exists, null otherwise.
*/
public String read(String name) {
@@ -1538,10 +1656,13 @@ public abstract class NanoHTTPD {
/**
* Sets a cookie.
- *
- * @param name The cookie's name.
- * @param value The cookie's value.
- * @param expires How many days until the cookie expires.
+ *
+ * @param name
+ * The cookie's name.
+ * @param value
+ * The cookie's value.
+ * @param expires
+ * How many days until the cookie expires.
*/
public void set(String name, String value, int expires) {
queue.add(new Cookie(name, value, Cookie.getHTTPTime(expires)));
@@ -1552,18 +1673,23 @@ public abstract class NanoHTTPD {
}
/**
- * Set a cookie with an expiration date from a month ago, effectively deleting it on the client side.
- *
- * @param name The cookie name.
+ * Set a cookie with an expiration date from a month ago, effectively
+ * deleting it on the client side.
+ *
+ * @param name
+ * The cookie name.
*/
public void delete(String name) {
set(name, "-delete-", -30);
}
/**
- * Internally used by the webserver to add all queued cookies into the Response's HTTP Headers.
- *
- * @param response The Response object to which headers the queued cookies will be added.
+ * Internally used by the webserver to add all queued cookies into the
+ * Response's HTTP Headers.
+ *
+ * @param response
+ * The Response object to which headers the queued cookies
+ * will be added.
*/
public void unloadQueue(Response response) {
for (Cookie cookie : queue) {
diff --git a/core/src/test/java/fi/iki/elonen/HttpChunkedResponseTest.java b/core/src/test/java/fi/iki/elonen/HttpChunkedResponseTest.java
index ab0ba3e..779e43f 100644
--- a/core/src/test/java/fi/iki/elonen/HttpChunkedResponseTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpChunkedResponseTest.java
@@ -40,29 +40,30 @@ import java.io.PipedInputStream;
import static fi.iki.elonen.NanoHTTPD.Response.Status.OK;
public class HttpChunkedResponseTest extends HttpServerTest {
+
@org.junit.Test
public void thatChunkedContentIsChunked() throws Exception {
PipedInputStream pipedInputStream = new ChunkedInputStream(new String[]{
- "some",
- "thing which is longer than sixteen characters",
- "whee!",
- ""
+ "some",
+ "thing which is longer than sixteen characters",
+ "whee!",
+ ""
});
String[] expected = {
- "HTTP/1.1 200 OK",
- "Content-Type: what/ever",
- "Date: .*",
- "Connection: keep-alive",
- "Transfer-Encoding: chunked",
- "",
- "4",
- "some",
- "2d",
- "thing which is longer than sixteen characters",
- "5",
- "whee!",
- "0",
- ""
+ "HTTP/1.1 200 OK",
+ "Content-Type: what/ever",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Transfer-Encoding: chunked",
+ "",
+ "4",
+ "some",
+ "2d",
+ "thing which is longer than sixteen characters",
+ "5",
+ "whee!",
+ "0",
+ ""
};
testServer.response = new NanoHTTPD.Response(OK, "what/ever", pipedInputStream);
testServer.response.setChunkedTransfer(true);
@@ -73,7 +74,9 @@ public class HttpChunkedResponseTest extends HttpServerTest {
}
private static class ChunkedInputStream extends PipedInputStream {
+
int chunk = 0;
+
String[] chunks;
private ChunkedInputStream(String[] chunks) {
diff --git a/core/src/test/java/fi/iki/elonen/HttpDeleteRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpDeleteRequestTest.java
index b9883a3..4756b1d 100644
--- a/core/src/test/java/fi/iki/elonen/HttpDeleteRequestTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpDeleteRequestTest.java
@@ -50,12 +50,12 @@ public class HttpDeleteRequestTest extends HttpServerTest {
ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1");
String[] expected = {
- "HTTP/1.1 204 No Content",
- "Content-Type: text/html",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 0",
- ""
+ "HTTP/1.1 204 No Content",
+ "Content-Type: text/html",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 0",
+ ""
};
assertResponse(outputStream, expected);
@@ -63,17 +63,17 @@ public class HttpDeleteRequestTest extends HttpServerTest {
@Test
public void testDeleteRequestThatDoesntSendBackResponseBody_NullString() throws Exception {
- testServer.response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.NO_CONTENT, NanoHTTPD.MIME_HTML, (String)null);
+ testServer.response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.NO_CONTENT, NanoHTTPD.MIME_HTML, (String) null);
ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1");
String[] expected = {
- "HTTP/1.1 204 No Content",
- "Content-Type: text/html",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 0",
- ""
+ "HTTP/1.1 204 No Content",
+ "Content-Type: text/html",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 0",
+ ""
};
assertResponse(outputStream, expected);
@@ -81,17 +81,17 @@ public class HttpDeleteRequestTest extends HttpServerTest {
@Test
public void testDeleteRequestThatDoesntSendBackResponseBody_NullInputStream() throws Exception {
- testServer.response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.NO_CONTENT, NanoHTTPD.MIME_HTML, (InputStream)null);
+ testServer.response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.NO_CONTENT, NanoHTTPD.MIME_HTML, (InputStream) null);
ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1");
String[] expected = {
- "HTTP/1.1 204 No Content",
- "Content-Type: text/html",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 0",
- ""
+ "HTTP/1.1 204 No Content",
+ "Content-Type: text/html",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 0",
+ ""
};
assertResponse(outputStream, expected);
@@ -104,13 +104,13 @@ public class HttpDeleteRequestTest extends HttpServerTest {
ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1");
String[] expected = {
- "HTTP/1.1 200 OK",
- "Content-Type: application/xml",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 8",
- "",
- "<body />"
+ "HTTP/1.1 200 OK",
+ "Content-Type: application/xml",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 8",
+ "",
+ "<body />"
};
assertResponse(outputStream, expected);
@@ -123,13 +123,13 @@ public class HttpDeleteRequestTest extends HttpServerTest {
ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1");
String[] expected = {
- "HTTP/1.1 202 Accepted",
- "Content-Type: application/xml",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 8",
- "",
- "<body />"
+ "HTTP/1.1 202 Accepted",
+ "Content-Type: application/xml",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 8",
+ "",
+ "<body />"
};
assertResponse(outputStream, expected);
diff --git a/core/src/test/java/fi/iki/elonen/HttpGetRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpGetRequestTest.java
index aa31397..9980d2e 100644
--- a/core/src/test/java/fi/iki/elonen/HttpGetRequestTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpGetRequestTest.java
@@ -47,12 +47,12 @@ public class HttpGetRequestTest extends HttpServerTest {
ByteArrayOutputStream outputStream = invokeServer("GET " + URI + " HTTP/1.1");
String[] expected = {
- "HTTP/1.1 200 OK",
- "Content-Type: text/html",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 0",
- ""
+ "HTTP/1.1 200 OK",
+ "Content-Type: text/html",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 0",
+ ""
};
assertResponse(outputStream, expected);
@@ -65,13 +65,13 @@ public class HttpGetRequestTest extends HttpServerTest {
ByteArrayOutputStream outputStream = invokeServer("GET " + URI + " HTTP/1.1");
String[] expected = {
- "HTTP/1.1 200 OK",
- "Content-Type: text/html",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 8",
- "",
- responseBody
+ "HTTP/1.1 200 OK",
+ "Content-Type: text/html",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 8",
+ "",
+ responseBody
};
assertResponse(outputStream, expected);
@@ -199,6 +199,7 @@ public class HttpGetRequestTest extends HttpServerTest {
invokeServer("GET " + URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1");
assertEquals(testServer.decodedParamters, testServer.decodedParamtersFromParameter);
}
- // -------------------------------------------------------------------------------------------------------- //
+ // --------------------------------------------------------------------------------------------------------
+ // //
}
diff --git a/core/src/test/java/fi/iki/elonen/HttpHeadRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpHeadRequestTest.java
index 2368211..2602fd9 100644
--- a/core/src/test/java/fi/iki/elonen/HttpHeadRequestTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpHeadRequestTest.java
@@ -41,6 +41,7 @@ import java.util.List;
import static junit.framework.Assert.*;
public class HttpHeadRequestTest extends HttpServerTest {
+
@Override
public void setUp() {
super.setUp();
@@ -53,12 +54,12 @@ public class HttpHeadRequestTest extends HttpServerTest {
ByteArrayOutputStream outputStream = invokeServer("HEAD " + URI + " HTTP/1.1");
String[] expected = {
- "HTTP/1.1 200 OK",
- "Content-Type: text/html",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 8",
- ""
+ "HTTP/1.1 200 OK",
+ "Content-Type: text/html",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 8",
+ ""
};
assertResponse(outputStream, expected);
@@ -186,6 +187,7 @@ public class HttpHeadRequestTest extends HttpServerTest {
invokeServer("HEAD " + URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1");
assertEquals(testServer.decodedParamters, testServer.decodedParamtersFromParameter);
}
- // -------------------------------------------------------------------------------------------------------- //
+ // --------------------------------------------------------------------------------------------------------
+ // //
}
diff --git a/core/src/test/java/fi/iki/elonen/HttpKeepAliveTest.java b/core/src/test/java/fi/iki/elonen/HttpKeepAliveTest.java
index a20f60a..829d5c5 100644
--- a/core/src/test/java/fi/iki/elonen/HttpKeepAliveTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpKeepAliveTest.java
@@ -47,41 +47,46 @@ public class HttpKeepAliveTest extends HttpServerTest {
public void testManyGetRequests() throws Exception {
String request = "GET " + URI + " HTTP/1.1\r\n\r\n";
String[] expected = {
- "HTTP/1.1 200 OK",
- "Content-Type: text/html",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 0",
- ""
+ "HTTP/1.1 200 OK",
+ "Content-Type: text/html",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 0",
+ ""
};
testManyRequests(request, expected);
}
-
+
@Test
public void testManyPutRequests() throws Exception {
String data = "BodyData 1\nLine 2";
String request = "PUT " + URI + " HTTP/1.1\r\nContent-Length: " + data.length() + "\r\n\r\n" + data;
String[] expected = {
- "HTTP/1.1 200 OK",
- "Content-Type: text/html",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 0",
- ""
+ "HTTP/1.1 200 OK",
+ "Content-Type: text/html",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 0",
+ ""
};
testManyRequests(request, expected);
}
private Throwable error = null;
-
+
/**
- * Issue the given request many times to check whether an error occurs.
- * For this test, a small stack size is used, since a stack overflow is among the possible errors.
- * @param request The request to issue
- * @param expected The expected response
+ * Issue the given request many times to check whether an error occurs. For
+ * this test, a small stack size is used, since a stack overflow is among
+ * the possible errors.
+ *
+ * @param request
+ * The request to issue
+ * @param expected
+ * The expected response
*/
public void testManyRequests(final String request, final String[] expected) throws Exception {
Runnable r = new Runnable() {
+
public void run() {
try {
PipedOutputStream requestStream = new PipedOutputStream();
@@ -108,7 +113,7 @@ public class HttpKeepAliveTest extends HttpServerTest {
t.start();
t.join();
if (error != null) {
- fail(""+error);
+ fail("" + error);
error.printStackTrace();
}
}
diff --git a/core/src/test/java/fi/iki/elonen/HttpParsingTest.java b/core/src/test/java/fi/iki/elonen/HttpParsingTest.java
index 7780651..9879bbe 100644
--- a/core/src/test/java/fi/iki/elonen/HttpParsingTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpParsingTest.java
@@ -41,6 +41,7 @@ import java.net.URLEncoder;
import static junit.framework.Assert.assertEquals;
public class HttpParsingTest extends HttpServerTest {
+
@Test
public void testNormalCharacters() throws Exception {
for (int i = 0x20; i < 0x80; i++) {
diff --git a/core/src/test/java/fi/iki/elonen/HttpPostRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpPostRequestTest.java
index 4853b00..c83a18d 100644
--- a/core/src/test/java/fi/iki/elonen/HttpPostRequestTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpPostRequestTest.java
@@ -47,11 +47,17 @@ import static junit.framework.Assert.assertEquals;
public class HttpPostRequestTest extends HttpServerTest {
public static final String CONTENT_LENGTH = "Content-Length: ";
+
public static final String FIELD = "caption";
+
public static final String VALUE = "Summer vacation";
+
public static final String FIELD2 = "location";
+
public static final String VALUE2 = "Grand Canyon";
+
public static final String POST_RAW_CONTENT_FILE_ENTRY = "postData";
+
public static final String VALUE_TEST_SIMPLE_RAW_DATA_WITH_AMPHASIS = "Test raw data & Result value";
@Test
@@ -61,7 +67,7 @@ public class HttpPostRequestTest extends HttpServerTest {
int size = content.length() + header.length();
int contentLengthHeaderValueSize = String.valueOf(size).length();
int contentLength = size + contentLengthHeaderValueSize + CONTENT_LENGTH.length();
- String input = header + CONTENT_LENGTH + (contentLength+4) + "\r\n\r\n" + content;
+ String input = header + CONTENT_LENGTH + (contentLength + 4) + "\r\n\r\n" + content;
invokeServer(input);
assertEquals(0, testServer.parms.size());
assertEquals(1, testServer.files.size());
@@ -71,17 +77,12 @@ public class HttpPostRequestTest extends HttpServerTest {
@Test
public void testSimplePostWithSingleMultipartFormField() throws Exception {
String divider = UUID.randomUUID().toString();
- String header = "POST " + URI + " HTTP/1.1\nContent-Type: " +
- "multipart/form-data; boundary=" + divider + "\n";
- String content = "--" + divider + "\n" +
- "Content-Disposition: form-data; name=\""+FIELD+"\"\n" +
- "\n" +
- VALUE +"\n" +
- "--" + divider + "--\n";
+ String header = "POST " + URI + " HTTP/1.1\nContent-Type: " + "multipart/form-data; boundary=" + divider + "\n";
+ String content = "--" + divider + "\n" + "Content-Disposition: form-data; name=\"" + FIELD + "\"\n" + "\n" + VALUE + "\n" + "--" + divider + "--\n";
int size = content.length() + header.length();
int contentLengthHeaderValueSize = String.valueOf(size).length();
int contentLength = size + contentLengthHeaderValueSize + CONTENT_LENGTH.length();
- String input = header + CONTENT_LENGTH + (contentLength+4) + "\r\n\r\n" + content;
+ String input = header + CONTENT_LENGTH + (contentLength + 4) + "\r\n\r\n" + content;
invokeServer(input);
assertEquals(1, testServer.parms.size());
@@ -91,20 +92,14 @@ public class HttpPostRequestTest extends HttpServerTest {
@Test
public void testPostWithMultipleMultipartFormFields() throws Exception {
String divider = UUID.randomUUID().toString();
- String header = "POST " + URI + " HTTP/1.1\nContent-Type: " +
- "multipart/form-data; boundary=" + divider + "\n";
- String content = "--" + divider + "\n" +
- "Content-Disposition: form-data; name=\""+FIELD+"\"\n" +
- "\n" +
- VALUE +"\n" +"--" + divider + "\n" +
- "Content-Disposition: form-data; name=\""+FIELD2+"\"\n" +
- "\n" +
- VALUE2 +"\n" +
- "--" + divider + "--\n";
+ String header = "POST " + URI + " HTTP/1.1\nContent-Type: " + "multipart/form-data; boundary=" + divider + "\n";
+ String content =
+ "--" + divider + "\n" + "Content-Disposition: form-data; name=\"" + FIELD + "\"\n" + "\n" + VALUE + "\n" + "--" + divider + "\n"
+ + "Content-Disposition: form-data; name=\"" + FIELD2 + "\"\n" + "\n" + VALUE2 + "\n" + "--" + divider + "--\n";
int size = content.length() + header.length();
int contentLengthHeaderValueSize = String.valueOf(size).length();
int contentLength = size + contentLengthHeaderValueSize + CONTENT_LENGTH.length();
- String input = header + CONTENT_LENGTH + (contentLength+4) + "\r\n\r\n" + content;
+ String input = header + CONTENT_LENGTH + (contentLength + 4) + "\r\n\r\n" + content;
invokeServer(input);
assertEquals(2, testServer.parms.size());
@@ -115,75 +110,71 @@ public class HttpPostRequestTest extends HttpServerTest {
@Test
public void testPostWithMultipleMultipartFormFieldsWhereContentTypeWasSeparatedByComma() throws Exception {
String divider = UUID.randomUUID().toString();
- String header = "POST " + URI + " HTTP/1.1\nContent-Type: " +
- "multipart/form-data, boundary=" + divider + "\n";
- String content = "--" + divider + "\n" +
- "Content-Disposition: form-data; name=\""+FIELD+"\"\n" +
- "\n" +
- VALUE +"\n" +"--" + divider + "\n" +
- "Content-Disposition: form-data; name=\""+FIELD2+"\"\n" +
- "\n" +
- VALUE2 +"\n" +
- "--" + divider + "--\n";
+ String header = "POST " + URI + " HTTP/1.1\nContent-Type: " + "multipart/form-data, boundary=" + divider + "\n";
+ String content =
+ "--" + divider + "\n" + "Content-Disposition: form-data; name=\"" + FIELD + "\"\n" + "\n" + VALUE + "\n" + "--" + divider + "\n"
+ + "Content-Disposition: form-data; name=\"" + FIELD2 + "\"\n" + "\n" + VALUE2 + "\n" + "--" + divider + "--\n";
int size = content.length() + header.length();
int contentLengthHeaderValueSize = String.valueOf(size).length();
int contentLength = size + contentLengthHeaderValueSize + CONTENT_LENGTH.length();
- String input = header + CONTENT_LENGTH + (contentLength+4) + "\r\n\r\n" + content;
+ String input = header + CONTENT_LENGTH + (contentLength + 4) + "\r\n\r\n" + content;
invokeServer(input);
assertEquals(2, testServer.parms.size());
assertEquals(VALUE, testServer.parms.get(FIELD));
assertEquals(VALUE2, testServer.parms.get(FIELD2));
}
-
+
@Test
public void testPostWithMultipartFormUpload() throws Exception {
String filename = "GrandCanyon.txt";
String fileContent = VALUE;
String input = preparePostWithMultipartForm(filename, fileContent);
-
+
invokeServer(input);
-
+
assertEquals(1, testServer.parms.size());
BufferedReader reader = new BufferedReader(new FileReader(testServer.files.get(FIELD)));
List<String> lines = readLinesFromFile(reader);
- assertLinesOfText(new String[]{fileContent}, lines);
+ assertLinesOfText(new String[]{
+ fileContent
+ }, lines);
}
-
+
@Test
public void testPostWithMultipartFormUploadFilenameHasSpaces() throws Exception {
- String fileNameWithSpace = "Grand Canyon.txt";
- String fileContent = VALUE;
- String input = preparePostWithMultipartForm(fileNameWithSpace, fileContent);
-
- invokeServer(input);
-
- String fileNameAfter = new ArrayList<String>(testServer.parms.values()).get(0);
-
- assertEquals(fileNameWithSpace, fileNameAfter);
+ String fileNameWithSpace = "Grand Canyon.txt";
+ String fileContent = VALUE;
+ String input = preparePostWithMultipartForm(fileNameWithSpace, fileContent);
+
+ invokeServer(input);
+
+ String fileNameAfter = new ArrayList<String>(testServer.parms.values()).get(0);
+
+ assertEquals(fileNameWithSpace, fileNameAfter);
}
-
+
/**
* contains common preparation steps for testing POST with Multipart Form
- * @param fileName Name of file to be uploaded
- * @param fileContent Content of file to be uploaded
- * @return input String with POST request complete information including header, length and content
+ *
+ * @param fileName
+ * Name of file to be uploaded
+ * @param fileContent
+ * Content of file to be uploaded
+ * @return input String with POST request complete information including
+ * header, length and content
*/
private String preparePostWithMultipartForm(String fileName, String fileContent) {
String divider = UUID.randomUUID().toString();
- String header = "POST " + URI + " HTTP/1.1\nContent-Type: " +
- "multipart/form-data, boundary=" + divider + "\n";
- String content = "--" + divider + "\n" +
- "Content-Disposition: form-data; name=\""+FIELD+"\"; filename=\""+fileName+"\"\n" +
- "Content-Type: image/jpeg\r\n"+
- "\r\n" +
- fileContent +"\r\n" +
- "--" + divider + "--\n";
+ String header = "POST " + URI + " HTTP/1.1\nContent-Type: " + "multipart/form-data, boundary=" + divider + "\n";
+ String content =
+ "--" + divider + "\n" + "Content-Disposition: form-data; name=\"" + FIELD + "\"; filename=\"" + fileName + "\"\n" + "Content-Type: image/jpeg\r\n" + "\r\n"
+ + fileContent + "\r\n" + "--" + divider + "--\n";
int size = content.length() + header.length();
int contentLengthHeaderValueSize = String.valueOf(size).length();
int contentLength = size + contentLengthHeaderValueSize + CONTENT_LENGTH.length();
- String input = header + CONTENT_LENGTH + (contentLength+5) + "\r\n\r\n" + content;
-
+ String input = header + CONTENT_LENGTH + (contentLength + 5) + "\r\n\r\n" + content;
+
return input;
}
diff --git a/core/src/test/java/fi/iki/elonen/HttpPutRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpPutRequestTest.java
index 71f3f97..e2755f9 100644
--- a/core/src/test/java/fi/iki/elonen/HttpPutRequestTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpPutRequestTest.java
@@ -49,12 +49,12 @@ public class HttpPutRequestTest extends HttpServerTest {
ByteArrayOutputStream outputStream = invokeServer("PUT " + URI + " HTTP/1.1\r\n\r\nBodyData 1\nLine 2");
String[] expectedOutput = {
- "HTTP/1.1 200 OK",
- "Content-Type: text/html",
- "Date: .*",
- "Connection: keep-alive",
- "Content-Length: 0",
- ""
+ "HTTP/1.1 200 OK",
+ "Content-Type: text/html",
+ "Date: .*",
+ "Connection: keep-alive",
+ "Content-Length: 0",
+ ""
};
assertResponse(outputStream, expectedOutput);
@@ -63,8 +63,8 @@ public class HttpPutRequestTest extends HttpServerTest {
BufferedReader reader = null;
try {
String[] expectedInputToServeMethodViaFile = {
- "BodyData 1",
- "Line 2"
+ "BodyData 1",
+ "Line 2"
};
reader = new BufferedReader(new FileReader(testServer.files.get("content")));
List<String> lines = readLinesFromFile(reader);
diff --git a/core/src/test/java/fi/iki/elonen/HttpServerTest.java b/core/src/test/java/fi/iki/elonen/HttpServerTest.java
index 82454bc..f7fbb7b 100644
--- a/core/src/test/java/fi/iki/elonen/HttpServerTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpServerTest.java
@@ -47,12 +47,14 @@ import java.util.Map;
import static junit.framework.Assert.*;
/**
- * @author Paul S. Hawke (paul.hawke@gmail.com)
- * On: 3/10/13 at 8:32 PM
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 3/10/13 at 8:32 PM
*/
public class HttpServerTest {
+
public static final String URI = "http://www.myserver.org/pub/WWW/someFile.html";
+
protected TestServer testServer;
+
private TestTempFileManager tempFileManager;
@Before
@@ -77,12 +79,10 @@ public class HttpServerTest {
}
protected void assertLinesOfText(String[] expected, List<String> lines) {
-// assertEquals(expected.length, lines.size());
+ // assertEquals(expected.length, lines.size());
for (int i = 0; i < expected.length; i++) {
String line = lines.get(i);
- assertTrue("Output line " + i + " doesn't match expectation.\n" +
- " Output: " + line + "\n" +
- "Expected: " + expected[i], line.matches(expected[i]));
+ assertTrue("Output line " + i + " doesn't match expectation.\n" + " Output: " + line + "\n" + "Expected: " + expected[i], line.matches(expected[i]));
}
}
@@ -93,7 +93,7 @@ public class HttpServerTest {
try {
session.execute();
} catch (IOException e) {
- fail(""+e);
+ fail("" + e);
e.printStackTrace();
}
return outputStream;
@@ -117,6 +117,7 @@ public class HttpServerTest {
}
public static class TestTempFileManager extends NanoHTTPD.DefaultTempFileManager {
+
public void _clear() {
super.clear();
}
@@ -128,14 +129,23 @@ public class HttpServerTest {
}
public static class TestServer extends NanoHTTPD {
+
public Response response = new Response("");
+
public String uri;
+
public Method method;
+
public Map<String, String> header;
+
public Map<String, String> parms;
+
public Map<String, String> files;
+
public Map<String, List<String>> decodedParamters;
+
public Map<String, List<String>> decodedParamtersFromParameter;
+
public String queryParameterString;
public TestServer() {
@@ -150,7 +160,8 @@ public class HttpServerTest {
return new HTTPSession(tempFileManager, inputStream, outputStream, inetAddress);
}
- @Override public Response serve(IHTTPSession session) {
+ @Override
+ public Response serve(IHTTPSession session) {
this.uri = session.getUri();
this.method = session.getMethod();
this.header = session.getHeaders();
diff --git a/core/src/test/java/fi/iki/elonen/HttpSessionHeadersTest.java b/core/src/test/java/fi/iki/elonen/HttpSessionHeadersTest.java
index a3d0f81..3402533 100644
--- a/core/src/test/java/fi/iki/elonen/HttpSessionHeadersTest.java
+++ b/core/src/test/java/fi/iki/elonen/HttpSessionHeadersTest.java
@@ -43,7 +43,9 @@ import java.net.InetAddress;
import static org.junit.Assert.assertEquals;
public class HttpSessionHeadersTest extends HttpServerTest {
+
private static final String DUMMY_REQUEST_CONTENT = "dummy request content";
+
private static final TestTempFileManager TEST_TEMP_FILE_MANAGER = new TestTempFileManager();
@Override
@@ -56,8 +58,12 @@ public class HttpSessionHeadersTest extends HttpServerTest {
public void testHeadersRemoteIp() throws Exception {
ByteArrayInputStream inputStream = new ByteArrayInputStream(DUMMY_REQUEST_CONTENT.getBytes());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- String[] ipAddresses = { "127.0.0.1", "192.168.1.1", "192.30.252.129" };
- for(String ipAddress : ipAddresses) {
+ String[] ipAddresses = {
+ "127.0.0.1",
+ "192.168.1.1",
+ "192.30.252.129"
+ };
+ for (String ipAddress : ipAddresses) {
InetAddress inetAddress = InetAddress.getByName(ipAddress);
NanoHTTPD.HTTPSession session = testServer.createSession(TEST_TEMP_FILE_MANAGER, inputStream, outputStream, inetAddress);
assertEquals(ipAddress, session.getHeaders().get("remote-addr"));
diff --git a/core/src/test/java/fi/iki/elonen/InvalidRequestTest.java b/core/src/test/java/fi/iki/elonen/InvalidRequestTest.java
index fd3d196..2c40cd1 100644
--- a/core/src/test/java/fi/iki/elonen/InvalidRequestTest.java
+++ b/core/src/test/java/fi/iki/elonen/InvalidRequestTest.java
@@ -41,7 +41,7 @@ public class InvalidRequestTest extends HttpServerTest {
@Test
public void testGetRequestWithoutProtocol() {
- invokeServer("GET " + URI + "\r\nX-Important-Header: foo" );
+ invokeServer("GET " + URI + "\r\nX-Important-Header: foo");
assertNotNull(testServer.parms);
assertTrue(testServer.header.size() > 0);
@@ -58,10 +58,9 @@ public class InvalidRequestTest extends HttpServerTest {
assertNotNull(testServer.uri);
}
-
@Test
public void testGetRequestWithProtocol() {
- invokeServer("GET " + URI + " HTTP/1.1\r\nX-Important-Header: foo" );
+ invokeServer("GET " + URI + " HTTP/1.1\r\nX-Important-Header: foo");
assertNotNull(testServer.parms);
assertTrue(testServer.header.size() > 0);
@@ -77,4 +76,4 @@ public class InvalidRequestTest extends HttpServerTest {
assertNotNull(testServer.files);
assertNotNull(testServer.uri);
}
-} \ No newline at end of file
+}
diff --git a/core/src/test/java/fi/iki/elonen/integration/CookieIntegrationTest.java b/core/src/test/java/fi/iki/elonen/integration/CookieIntegrationTest.java
index 7a8cfcb..f765a38 100644
--- a/core/src/test/java/fi/iki/elonen/integration/CookieIntegrationTest.java
+++ b/core/src/test/java/fi/iki/elonen/integration/CookieIntegrationTest.java
@@ -48,8 +48,7 @@ import java.util.List;
import static org.junit.Assert.*;
/**
- * @author Paul S. Hawke (paul.hawke@gmail.com)
- * On: 9/2/13 at 10:10 PM
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 9/2/13 at 10:10 PM
*/
public class CookieIntegrationTest extends IntegrationTestBase<CookieIntegrationTest.CookieTestServer> {
@@ -92,19 +91,23 @@ public class CookieIntegrationTest extends IntegrationTestBase<CookieIntegration
assertTrue(testServer.cookiesReceived.get(0).getHTTPHeader().contains("name=value"));
}
- @Override public CookieTestServer createTestServer() {
+ @Override
+ public CookieTestServer createTestServer() {
return new CookieTestServer();
}
public static class CookieTestServer extends NanoHTTPD {
+
List<Cookie> cookiesReceived = new ArrayList<Cookie>();
+
List<Cookie> cookiesToSend = new ArrayList<Cookie>();
public CookieTestServer() {
super(8192);
}
- @Override public Response serve(IHTTPSession session) {
+ @Override
+ public Response serve(IHTTPSession session) {
CookieHandler cookies = session.getCookies();
for (String cookieName : cookies) {
cookiesReceived.add(new Cookie(cookieName, cookies.read(cookieName)));
diff --git a/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java b/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java
index 97adafa..ea4041d 100644
--- a/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java
+++ b/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java
@@ -59,8 +59,7 @@ import java.util.Map;
import static org.junit.Assert.assertEquals;
/**
- * @author Paul S. Hawke (paul.hawke@gmail.com)
- * On: 5/19/13 at 5:36 PM
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 5/19/13 at 5:36 PM
*/
public class GetAndPostIntegrationTest extends IntegrationTestBase<GetAndPostIntegrationTest.TestServer> {
@@ -129,11 +128,13 @@ public class GetAndPostIntegrationTest extends IntegrationTestBase<GetAndPostInt
assertEquals("POST:testPostRequestWithMultipartEncodedParameters-params=2;age=120;gender=Male", responseBody);
}
- @Override public TestServer createTestServer() {
+ @Override
+ public TestServer createTestServer() {
return new TestServer();
}
public static class TestServer extends NanoHTTPD {
+
public String response;
public TestServer() {
diff --git a/core/src/test/java/fi/iki/elonen/integration/IntegrationTestBase.java b/core/src/test/java/fi/iki/elonen/integration/IntegrationTestBase.java
index 6940f48..9ad6b73 100644
--- a/core/src/test/java/fi/iki/elonen/integration/IntegrationTestBase.java
+++ b/core/src/test/java/fi/iki/elonen/integration/IntegrationTestBase.java
@@ -42,11 +42,12 @@ import org.junit.Before;
import java.io.IOException;
/**
- * @author Paul S. Hawke (paul.hawke@gmail.com)
- * On: 9/2/13 at 10:02 PM
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 9/2/13 at 10:02 PM
*/
public abstract class IntegrationTestBase<T extends NanoHTTPD> {
+
protected DefaultHttpClient httpclient;
+
protected T testServer;
@Before
diff --git a/core/src/test/java/fi/iki/elonen/integration/PutStreamIntegrationTest.java b/core/src/test/java/fi/iki/elonen/integration/PutStreamIntegrationTest.java
index 8a80b01..6bdde4d 100644
--- a/core/src/test/java/fi/iki/elonen/integration/PutStreamIntegrationTest.java
+++ b/core/src/test/java/fi/iki/elonen/integration/PutStreamIntegrationTest.java
@@ -61,18 +61,19 @@ public class PutStreamIntegrationTest extends IntegrationTestBase<PutStreamInteg
assertEquals("PUT:" + expected, responseBody);
}
- @Override public TestServer createTestServer() {
+ @Override
+ public TestServer createTestServer() {
return new TestServer();
}
public static class TestServer extends NanoHTTPD {
+
public TestServer() {
super(8192);
}
@Override
- public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms, Map<String, String> files)
- {
+ public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms, Map<String, String> files) {
throw new UnsupportedOperationException();
}
@@ -87,8 +88,7 @@ public class PutStreamIntegrationTest extends IntegrationTestBase<PutStreamInteg
DataInputStream dataInputStream = new DataInputStream(session.getInputStream());
body = new byte[contentLength];
dataInputStream.readFully(body, 0, contentLength);
- }
- catch(IOException e) {
+ } catch (IOException e) {
return new Response(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, e.getMessage());
}
diff --git a/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPlugin.java b/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPlugin.java
index 6c1fc14..92640a9 100644
--- a/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPlugin.java
+++ b/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPlugin.java
@@ -47,26 +47,27 @@ import java.util.logging.Logger;
import org.pegdown.PegDownProcessor;
/**
- * @author Paul S. Hawke (paul.hawke@gmail.com)
- * On: 9/13/13 at 4:03 AM
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 9/13/13 at 4:03 AM
*/
public class MarkdownWebServerPlugin implements WebServerPlugin {
-
+
/**
* logger to log to.
*/
private static Logger LOG = Logger.getLogger(MarkdownWebServerPlugin.class.getName());
-
+
private final PegDownProcessor processor;
public MarkdownWebServerPlugin() {
processor = new PegDownProcessor();
}
- @Override public void initialize(Map<String, String> commandLineOptions) {
+ @Override
+ public void initialize(Map<String, String> commandLineOptions) {
}
- @Override public boolean canServeUri(String uri, File rootDir) {
+ @Override
+ public boolean canServeUri(String uri, File rootDir) {
File f = new File(rootDir, uri);
return f.exists();
}
@@ -74,8 +75,7 @@ public class MarkdownWebServerPlugin implements WebServerPlugin {
@Override
public NanoHTTPD.Response serveFile(String uri, Map<String, String> headers, NanoHTTPD.IHTTPSession session, File file, String mimeType) {
String markdownSource = readSource(file);
- return markdownSource == null ? null :
- new NanoHTTPD.Response(OK, MIME_HTML, processor.markdownToHtml(markdownSource));
+ return markdownSource == null ? null : new NanoHTTPD.Response(OK, MIME_HTML, processor.markdownToHtml(markdownSource));
}
private String readSource(File file) {
@@ -95,7 +95,7 @@ public class MarkdownWebServerPlugin implements WebServerPlugin {
reader.close();
return sb.toString();
} catch (Exception e) {
- LOG.log(Level.SEVERE, "could not read source",e);
+ LOG.log(Level.SEVERE, "could not read source", e);
return null;
} finally {
try {
@@ -106,7 +106,7 @@ public class MarkdownWebServerPlugin implements WebServerPlugin {
reader.close();
}
} catch (IOException ignored) {
- LOG.log(Level.FINEST, "close failed",ignored);
+ LOG.log(Level.FINEST, "close failed", ignored);
}
}
}
diff --git a/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPluginInfo.java b/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPluginInfo.java
index 35bd1a3..d7f1c4c 100644
--- a/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPluginInfo.java
+++ b/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPluginInfo.java
@@ -34,19 +34,26 @@ package fi.iki.elonen;
*/
/**
- * @author Paul S. Hawke (paul.hawke@gmail.com)
- * On: 9/13/13 at 4:01 AM
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 9/13/13 at 4:01 AM
*/
public class MarkdownWebServerPluginInfo implements WebServerPluginInfo {
- @Override public String[] getMimeTypes() {
- return new String[]{"text/markdown"};
+
+ @Override
+ public String[] getMimeTypes() {
+ return new String[]{
+ "text/markdown"
+ };
}
- @Override public String[] getIndexFilesForMimeType(String mime) {
- return new String[]{"index.md"};
+ @Override
+ public String[] getIndexFilesForMimeType(String mime) {
+ return new String[]{
+ "index.md"
+ };
}
- @Override public WebServerPlugin getWebServerPlugin(String mimeType) {
+ @Override
+ public WebServerPlugin getWebServerPlugin(String mimeType) {
return new MarkdownWebServerPlugin();
}
}
diff --git a/pom.xml b/pom.xml
index 7e979a6..38ec306 100644
--- a/pom.xml
+++ b/pom.xml
@@ -361,6 +361,25 @@
<exists>src/main/java</exists>
</file>
</activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
+ <artifactId>maven-java-formatter-plugin</artifactId>
+ <version>0.4</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>format</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <configFile>${project.basedir}/../src/main/formatter/formatter.xml</configFile>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
<reporting>
<plugins>
<plugin>
@@ -386,27 +405,5 @@
</plugins>
</reporting>
</profile>
- <profile>
- <id>format</id>
- <build>
- <plugins>
- <plugin>
- <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
- <artifactId>maven-java-formatter-plugin</artifactId>
- <version>0.4</version>
- <executions>
- <execution>
- <goals>
- <goal>format</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <configFile>${project.basedir}/../src/main/formatter/formatter.xml</configFile>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
</profiles>
</project>
diff --git a/samples/src/main/java/fi/iki/elonen/HelloServer.java b/samples/src/main/java/fi/iki/elonen/HelloServer.java
index 0a212e0..a01d9a8 100644
--- a/samples/src/main/java/fi/iki/elonen/HelloServer.java
+++ b/samples/src/main/java/fi/iki/elonen/HelloServer.java
@@ -41,36 +41,34 @@ import java.util.logging.Logger;
*/
public class HelloServer extends NanoHTTPD {
- /**
- * logger to log to.
- */
- private static Logger LOG = Logger.getLogger(HelloServer.class.getName());
+ /**
+ * logger to log to.
+ */
+ private static Logger LOG = Logger.getLogger(HelloServer.class.getName());
- public HelloServer() {
- super(8080);
- }
+ public HelloServer() {
+ super(8080);
+ }
- @Override
- public Response serve(IHTTPSession session) {
- Method method = session.getMethod();
- String uri = session.getUri();
- LOG.info(method + " '" + uri + "' ");
+ @Override
+ public Response serve(IHTTPSession session) {
+ Method method = session.getMethod();
+ String uri = session.getUri();
+ LOG.info(method + " '" + uri + "' ");
- String msg = "<html><body><h1>Hello server</h1>\n";
- Map<String, String> parms = session.getParms();
- if (parms.get("username") == null)
- msg += "<form action='?' method='get'>\n"
- + " <p>Your name: <input type='text' name='username'></p>\n"
- + "</form>\n";
- else
- msg += "<p>Hello, " + parms.get("username") + "!</p>";
+ String msg = "<html><body><h1>Hello server</h1>\n";
+ Map<String, String> parms = session.getParms();
+ if (parms.get("username") == null)
+ msg += "<form action='?' method='get'>\n" + " <p>Your name: <input type='text' name='username'></p>\n" + "</form>\n";
+ else
+ msg += "<p>Hello, " + parms.get("username") + "!</p>";
- msg += "</body></html>\n";
+ msg += "</body></html>\n";
- return new NanoHTTPD.Response(msg);
- }
+ return new NanoHTTPD.Response(msg);
+ }
- public static void main(String[] args) {
- ServerRunner.run(HelloServer.class);
- }
+ public static void main(String[] args) {
+ ServerRunner.run(HelloServer.class);
+ }
}
diff --git a/samples/src/main/java/fi/iki/elonen/TempFilesServer.java b/samples/src/main/java/fi/iki/elonen/TempFilesServer.java
index 6eba33e..2e0828f 100644
--- a/samples/src/main/java/fi/iki/elonen/TempFilesServer.java
+++ b/samples/src/main/java/fi/iki/elonen/TempFilesServer.java
@@ -39,10 +39,10 @@ import java.util.List;
import fi.iki.elonen.debug.DebugServer;
/**
- * @author Paul S. Hawke (paul.hawke@gmail.com)
- * On: 3/9/13 at 12:47 AM
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 3/9/13 at 12:47 AM
*/
public class TempFilesServer extends DebugServer {
+
public static void main(String[] args) {
TempFilesServer server = new TempFilesServer();
server.setTempFileManagerFactory(new ExampleManagerFactory());
@@ -50,6 +50,7 @@ public class TempFilesServer extends DebugServer {
}
private static class ExampleManagerFactory implements TempFileManagerFactory {
+
@Override
public TempFileManager create() {
return new ExampleManager();
@@ -57,7 +58,9 @@ public class TempFilesServer extends DebugServer {
}
private static class ExampleManager implements TempFileManager {
+
private final String tmpdir;
+
private final List<TempFile> tempFiles;
private ExampleManager() {
@@ -80,9 +83,10 @@ public class TempFilesServer extends DebugServer {
}
for (TempFile file : tempFiles) {
try {
- System.out.println(" "+file.getName());
+ System.out.println(" " + file.getName());
file.delete();
- } catch (Exception ignored) {}
+ } catch (Exception ignored) {
+ }
}
tempFiles.clear();
}
diff --git a/samples/src/main/java/fi/iki/elonen/debug/DebugServer.java b/samples/src/main/java/fi/iki/elonen/debug/DebugServer.java
index 6988598..7780576 100644
--- a/samples/src/main/java/fi/iki/elonen/debug/DebugServer.java
+++ b/samples/src/main/java/fi/iki/elonen/debug/DebugServer.java
@@ -41,6 +41,7 @@ import fi.iki.elonen.NanoHTTPD;
import fi.iki.elonen.ServerRunner;
public class DebugServer extends NanoHTTPD {
+
public DebugServer() {
super(8080);
}
@@ -49,9 +50,9 @@ public class DebugServer extends NanoHTTPD {
ServerRunner.run(DebugServer.class);
}
- @Override public Response serve(IHTTPSession session) {
- Map<String, List<String>> decodedQueryParameters =
- decodeParameters(session.getQueryParameterString());
+ @Override
+ public Response serve(IHTTPSession session) {
+ Map<String, List<String>> decodedQueryParameters = decodeParameters(session.getQueryParameterString());
StringBuilder sb = new StringBuilder();
sb.append("<html>");
@@ -59,26 +60,20 @@ public class DebugServer extends NanoHTTPD {
sb.append("<body>");
sb.append("<h1>Debug Server</h1>");
- sb.append("<p><blockquote><b>URI</b> = ").append(
- String.valueOf(session.getUri())).append("<br />");
+ sb.append("<p><blockquote><b>URI</b> = ").append(String.valueOf(session.getUri())).append("<br />");
- sb.append("<b>Method</b> = ").append(
- String.valueOf(session.getMethod())).append("</blockquote></p>");
+ sb.append("<b>Method</b> = ").append(String.valueOf(session.getMethod())).append("</blockquote></p>");
- sb.append("<h3>Headers</h3><p><blockquote>").
- append(toString(session.getHeaders())).append("</blockquote></p>");
+ sb.append("<h3>Headers</h3><p><blockquote>").append(toString(session.getHeaders())).append("</blockquote></p>");
- sb.append("<h3>Parms</h3><p><blockquote>").
- append(toString(session.getParms())).append("</blockquote></p>");
+ sb.append("<h3>Parms</h3><p><blockquote>").append(toString(session.getParms())).append("</blockquote></p>");
- sb.append("<h3>Parms (multi values?)</h3><p><blockquote>").
- append(toString(decodedQueryParameters)).append("</blockquote></p>");
+ sb.append("<h3>Parms (multi values?)</h3><p><blockquote>").append(toString(decodedQueryParameters)).append("</blockquote></p>");
try {
Map<String, String> files = new HashMap<String, String>();
session.parseBody(files);
- sb.append("<h3>Files</h3><p><blockquote>").
- append(toString(files)).append("</blockquote></p>");
+ sb.append("<h3>Files</h3><p><blockquote>").append(toString(files)).append("</blockquote></p>");
} catch (Exception e) {
e.printStackTrace();
}
@@ -106,7 +101,6 @@ public class DebugServer extends NanoHTTPD {
}
private void listItem(StringBuilder sb, Map.Entry<String, ? extends Object> entry) {
- sb.append("<li><code><b>").append(entry.getKey()).
- append("</b> = ").append(entry.getValue()).append("</code></li>");
+ sb.append("<li><code><b>").append(entry.getKey()).append("</b> = ").append(entry.getValue()).append("</code></li>");
}
}
diff --git a/webserver/src/main/java/fi/iki/elonen/InternalRewrite.java b/webserver/src/main/java/fi/iki/elonen/InternalRewrite.java
index ad6b16e..f5dcd91 100644
--- a/webserver/src/main/java/fi/iki/elonen/InternalRewrite.java
+++ b/webserver/src/main/java/fi/iki/elonen/InternalRewrite.java
@@ -38,11 +38,12 @@ import java.util.Map;
import fi.iki.elonen.NanoHTTPD.Response;
/**
- * @author Paul S. Hawke (paul.hawke@gmail.com)
- * On: 9/15/13 at 2:52 PM
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 9/15/13 at 2:52 PM
*/
public class InternalRewrite extends Response {
+
private final String uri;
+
private final Map<String, String> headers;
public InternalRewrite(Map<String, String> headers, String uri) {
diff --git a/webserver/src/main/java/fi/iki/elonen/ServerRunner.java b/webserver/src/main/java/fi/iki/elonen/ServerRunner.java
index cfb1d6f..2a4c699 100644
--- a/webserver/src/main/java/fi/iki/elonen/ServerRunner.java
+++ b/webserver/src/main/java/fi/iki/elonen/ServerRunner.java
@@ -38,16 +38,17 @@ import java.util.logging.Level;
import java.util.logging.Logger;
public class ServerRunner {
+
/**
* logger to log to.
*/
private static Logger LOG = Logger.getLogger(ServerRunner.class.getName());
-
+
public static <T extends NanoHTTPD> void run(Class<T> serverClass) {
try {
executeInstance((NanoHTTPD) serverClass.newInstance());
} catch (Exception e) {
- LOG.log(Level.SEVERE, "Cound nor create server",e);
+ LOG.log(Level.SEVERE, "Cound nor create server", e);
}
}
diff --git a/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java b/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java
index 13306d8..147bbf9 100644
--- a/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java
+++ b/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java
@@ -51,84 +51,81 @@ import java.util.ServiceLoader;
import java.util.StringTokenizer;
public class SimpleWebServer extends NanoHTTPD {
+
/**
* Common mime type for dynamic content: binary
*/
public static final String MIME_DEFAULT_BINARY = "application/octet-stream";
+
/**
* Default Index file names.
*/
@SuppressWarnings("serial")
- public static final List<String> INDEX_FILE_NAMES = new ArrayList<String>() {{
- add("index.html");
- add("index.htm");
- }};
+ public static final List<String> INDEX_FILE_NAMES = new ArrayList<String>() {
+
+ {
+ add("index.html");
+ add("index.htm");
+ }
+ };
+
/**
* Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE
*/
@SuppressWarnings("serial")
- private static final Map<String, String> MIME_TYPES = new HashMap<String, String>() {{
- put("css", "text/css");
- put("htm", "text/html");
- put("html", "text/html");
- put("xml", "text/xml");
- put("java", "text/x-java-source, text/java");
- put("md", "text/plain");
- put("txt", "text/plain");
- put("asc", "text/plain");
- put("gif", "image/gif");
- put("jpg", "image/jpeg");
- put("jpeg", "image/jpeg");
- put("png", "image/png");
- put("mp3", "audio/mpeg");
- put("m3u", "audio/mpeg-url");
- put("mp4", "video/mp4");
- put("ogv", "video/ogg");
- put("flv", "video/x-flv");
- put("mov", "video/quicktime");
- put("swf", "application/x-shockwave-flash");
- put("js", "application/javascript");
- put("pdf", "application/pdf");
- put("doc", "application/msword");
- put("ogg", "application/x-ogg");
- put("zip", "application/octet-stream");
- put("exe", "application/octet-stream");
- put("class", "application/octet-stream");
- }};
+ private static final Map<String, String> MIME_TYPES = new HashMap<String, String>() {
+
+ {
+ put("css", "text/css");
+ put("htm", "text/html");
+ put("html", "text/html");
+ put("xml", "text/xml");
+ put("java", "text/x-java-source, text/java");
+ put("md", "text/plain");
+ put("txt", "text/plain");
+ put("asc", "text/plain");
+ put("gif", "image/gif");
+ put("jpg", "image/jpeg");
+ put("jpeg", "image/jpeg");
+ put("png", "image/png");
+ put("mp3", "audio/mpeg");
+ put("m3u", "audio/mpeg-url");
+ put("mp4", "video/mp4");
+ put("ogv", "video/ogg");
+ put("flv", "video/x-flv");
+ put("mov", "video/quicktime");
+ put("swf", "application/x-shockwave-flash");
+ put("js", "application/javascript");
+ put("pdf", "application/pdf");
+ put("doc", "application/msword");
+ put("ogg", "application/x-ogg");
+ put("zip", "application/octet-stream");
+ put("exe", "application/octet-stream");
+ put("class", "application/octet-stream");
+ }
+ };
+
/**
* The distribution licence
*/
- private static final String LICENCE =
- "Copyright (c) 2012-2013 by Paul S. Hawke, 2001,2005-2013 by Jarno Elonen, 2010 by Konstantinos Togias\n"
- + "\n"
- + "Redistribution and use in source and binary forms, with or without\n"
- + "modification, are permitted provided that the following conditions\n"
- + "are met:\n"
- + "\n"
- + "Redistributions of source code must retain the above copyright notice,\n"
- + "this list of conditions and the following disclaimer. Redistributions in\n"
- + "binary form must reproduce the above copyright notice, this list of\n"
- + "conditions and the following disclaimer in the documentation and/or other\n"
- + "materials provided with the distribution. The name of the author may not\n"
- + "be used to endorse or promote products derived from this software without\n"
- + "specific prior written permission. \n"
- + " \n"
- + "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
- + "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"
- + "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"
- + "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
- + "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
- + "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
- + "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
- + "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
- + "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
+ private static final String LICENCE = "Copyright (c) 2012-2013 by Paul S. Hawke, 2001,2005-2013 by Jarno Elonen, 2010 by Konstantinos Togias\n" + "\n"
+ + "Redistribution and use in source and binary forms, with or without\n" + "modification, are permitted provided that the following conditions\n" + "are met:\n"
+ + "\n" + "Redistributions of source code must retain the above copyright notice,\n" + "this list of conditions and the following disclaimer. Redistributions in\n"
+ + "binary form must reproduce the above copyright notice, this list of\n" + "conditions and the following disclaimer in the documentation and/or other\n"
+ + "materials provided with the distribution. The name of the author may not\n" + "be used to endorse or promote products derived from this software without\n"
+ + "specific prior written permission. \n" + " \n" + "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
+ + "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n" + "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"
+ + "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n" + "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
+ + "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" + "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
+ + "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" + "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
+ "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
+
private static Map<String, WebServerPlugin> mimeTypeHandlers = new HashMap<String, WebServerPlugin>();
+
private final boolean quiet;
protected List<File> rootDirs;
-
public SimpleWebServer(String host, int port, File wwwroot, boolean quiet) {
super(host, port);
this.quiet = quiet;
@@ -146,9 +143,9 @@ public class SimpleWebServer extends NanoHTTPD {
this.init();
}
- /**
- * Used to initialize and customize the server.
- */
+ /**
+ * Used to initialize and customize the server.
+ */
public void init() {
}
@@ -191,7 +188,7 @@ public class SimpleWebServer extends NanoHTTPD {
}
options.put("host", host);
- options.put("port", ""+port);
+ options.put("port", "" + port);
options.put("quiet", String.valueOf(quiet));
StringBuilder sb = new StringBuilder();
for (File dir : rootDirs) {
@@ -200,7 +197,8 @@ public class SimpleWebServer extends NanoHTTPD {
}
try {
sb.append(dir.getCanonicalPath());
- } catch (IOException ignored) {}
+ } catch (IOException ignored) {
+ }
}
options.put("home", sb.toString());
@@ -246,7 +244,8 @@ public class SimpleWebServer extends NanoHTTPD {
}
/**
- * URL-encodes everything between "/"-characters. Encodes spaces as '%20' instead of '+'.
+ * URL-encodes everything between "/"-characters. Encodes spaces as '%20'
+ * instead of '+'.
*/
private String encodeUri(String uri) {
String newUri = "";
@@ -318,18 +317,19 @@ public class SimpleWebServer extends NanoHTTPD {
return getNotFoundResponse();
}
- // Browsers get confused without '/' after the directory, send a redirect.
+ // Browsers get confused without '/' after the directory, send a
+ // redirect.
File f = new File(homeDir, uri);
if (f.isDirectory() && !uri.endsWith("/")) {
uri += "/";
- Response res = createResponse(Response.Status.REDIRECT, NanoHTTPD.MIME_HTML, "<html><body>Redirected: <a href=\"" +
- uri + "\">" + uri + "</a></body></html>");
+ Response res = createResponse(Response.Status.REDIRECT, NanoHTTPD.MIME_HTML, "<html><body>Redirected: <a href=\"" + uri + "\">" + uri + "</a></body></html>");
res.addHeader("Location", uri);
return res;
}
if (f.isDirectory()) {
- // First look for index files (index.html, index.htm, etc) and if none found, list the directory if readable.
+ // First look for index files (index.html, index.htm, etc) and if
+ // none found, list the directory if readable.
String indexFile = findIndexFileInDirectory(f);
if (indexFile == null) {
if (f.canRead()) {
@@ -359,18 +359,15 @@ public class SimpleWebServer extends NanoHTTPD {
}
protected Response getNotFoundResponse() {
- return createResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT,
- "Error 404, file not found.");
+ return createResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found.");
}
protected Response getForbiddenResponse(String s) {
- return createResponse(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: "
- + s);
+ return createResponse(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: " + s);
}
protected Response getInternalErrorResponse(String s) {
- return createResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT,
- "INTERNAL ERROR: " + s);
+ return createResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "INTERNAL ERROR: " + s);
}
private boolean canServeUri(String uri, File homeDir) {
@@ -388,7 +385,8 @@ public class SimpleWebServer extends NanoHTTPD {
}
/**
- * Serves file from homeDir and its' subdirectories (only). Uses only URI, ignores all headers and HTTP parameters.
+ * Serves file from homeDir and its' subdirectories (only). Uses only URI,
+ * ignores all headers and HTTP parameters.
*/
Response serveFile(String uri, Map<String, String> header, File file, String mime) {
Response res;
@@ -414,7 +412,8 @@ public class SimpleWebServer extends NanoHTTPD {
}
}
- // Change return code and add Content-Range header when skipping is requested
+ // Change return code and add Content-Range header when skipping is
+ // requested
long fileLen = file.length();
if (range != null && startFrom >= 0) {
if (startFrom >= fileLen) {
@@ -432,6 +431,7 @@ public class SimpleWebServer extends NanoHTTPD {
final long dataLen = newLen;
FileInputStream fis = new FileInputStream(file) {
+
@Override
public int available() throws IOException {
return (int) dataLen;
@@ -496,12 +496,9 @@ public class SimpleWebServer extends NanoHTTPD {
protected String listDirectory(String uri, File f) {
String heading = "Directory " + uri;
- StringBuilder msg = new StringBuilder("<html><head><title>" + heading + "</title><style><!--\n" +
- "span.dirname { font-weight: bold; }\n" +
- "span.filesize { font-size: 75%; }\n" +
- "// -->\n" +
- "</style>" +
- "</head><body><h1>" + heading + "</h1>");
+ StringBuilder msg =
+ new StringBuilder("<html><head><title>" + heading + "</title><style><!--\n" + "span.dirname { font-weight: bold; }\n" + "span.filesize { font-size: 75%; }\n"
+ + "// -->\n" + "</style>" + "</head><body><h1>" + heading + "</h1>");
String up = null;
if (uri.length() > 1) {
@@ -513,6 +510,7 @@ public class SimpleWebServer extends NanoHTTPD {
}
List<String> files = Arrays.asList(f.list(new FilenameFilter() {
+
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isFile();
@@ -520,6 +518,7 @@ public class SimpleWebServer extends NanoHTTPD {
}));
Collections.sort(files);
List<String> directories = Arrays.asList(f.list(new FilenameFilter() {
+
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
@@ -535,7 +534,8 @@ public class SimpleWebServer extends NanoHTTPD {
}
for (String directory : directories) {
String dir = directory + "/";
- msg.append("<li><a rel=\"directory\" href=\"").append(encodeUri(uri + dir)).append("\"><span class=\"dirname\">").append(dir).append("</span></a></b></li>");
+ msg.append("<li><a rel=\"directory\" href=\"").append(encodeUri(uri + dir)).append("\"><span class=\"dirname\">").append(dir)
+ .append("</span></a></b></li>");
}
msg.append("</section>");
}
diff --git a/webserver/src/main/java/fi/iki/elonen/WebServerPlugin.java b/webserver/src/main/java/fi/iki/elonen/WebServerPlugin.java
index 3835de9..cdfc3ff 100644
--- a/webserver/src/main/java/fi/iki/elonen/WebServerPlugin.java
+++ b/webserver/src/main/java/fi/iki/elonen/WebServerPlugin.java
@@ -39,9 +39,8 @@ import java.util.Map;
import fi.iki.elonen.NanoHTTPD.IHTTPSession;
/**
-* @author Paul S. Hawke (paul.hawke@gmail.com)
-* On: 9/14/13 at 8:09 AM
-*/
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 9/14/13 at 8:09 AM
+ */
public interface WebServerPlugin {
void initialize(Map<String, String> commandLineOptions);
diff --git a/webserver/src/main/java/fi/iki/elonen/WebServerPluginInfo.java b/webserver/src/main/java/fi/iki/elonen/WebServerPluginInfo.java
index 4e9a007..c1ef6e8 100644
--- a/webserver/src/main/java/fi/iki/elonen/WebServerPluginInfo.java
+++ b/webserver/src/main/java/fi/iki/elonen/WebServerPluginInfo.java
@@ -34,10 +34,10 @@ package fi.iki.elonen;
*/
/**
-* @author Paul S. Hawke (paul.hawke@gmail.com)
-* On: 9/14/13 at 8:09 AM
-*/
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 9/14/13 at 8:09 AM
+ */
public interface WebServerPluginInfo {
+
String[] getMimeTypes();
String[] getIndexFilesForMimeType(String mime);
diff --git a/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java b/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java
index 9c3b8c7..8163c10 100644
--- a/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java
+++ b/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java
@@ -53,23 +53,32 @@ import fi.iki.elonen.NanoWebSocketServer.WebSocketFrame.CloseFrame;
import fi.iki.elonen.NanoWebSocketServer.WebSocketFrame.OpCode;
public abstract class NanoWebSocketServer extends NanoHTTPD {
+
/**
* logger to log to.
*/
private static Logger LOG = Logger.getLogger(NanoWebSocketServer.class.getName());
-
- public static final String HEADER_UPGRADE = "upgrade";
- public static final String HEADER_UPGRADE_VALUE = "websocket";
- public static final String HEADER_CONNECTION = "connection";
- public static final String HEADER_CONNECTION_VALUE = "Upgrade";
- public static final String HEADER_WEBSOCKET_VERSION = "sec-websocket-version";
- public static final String HEADER_WEBSOCKET_VERSION_VALUE = "13";
- public static final String HEADER_WEBSOCKET_KEY = "sec-websocket-key";
- public static final String HEADER_WEBSOCKET_ACCEPT = "sec-websocket-accept";
- public static final String HEADER_WEBSOCKET_PROTOCOL = "sec-websocket-protocol";
-
- private final static String WEBSOCKET_KEY_MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
-
+
+ public static final String HEADER_UPGRADE = "upgrade";
+
+ public static final String HEADER_UPGRADE_VALUE = "websocket";
+
+ public static final String HEADER_CONNECTION = "connection";
+
+ public static final String HEADER_CONNECTION_VALUE = "Upgrade";
+
+ public static final String HEADER_WEBSOCKET_VERSION = "sec-websocket-version";
+
+ public static final String HEADER_WEBSOCKET_VERSION_VALUE = "13";
+
+ public static final String HEADER_WEBSOCKET_KEY = "sec-websocket-key";
+
+ public static final String HEADER_WEBSOCKET_ACCEPT = "sec-websocket-accept";
+
+ public static final String HEADER_WEBSOCKET_PROTOCOL = "sec-websocket-protocol";
+
+ private final static String WEBSOCKET_KEY_MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
public NanoWebSocketServer(int port) {
super(port);
}
@@ -83,13 +92,11 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
Map<String, String> headers = session.getHeaders();
if (isWebsocketRequested(session)) {
if (!HEADER_WEBSOCKET_VERSION_VALUE.equalsIgnoreCase(headers.get(HEADER_WEBSOCKET_VERSION))) {
- return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT,
- "Invalid Websocket-Version " + headers.get(HEADER_WEBSOCKET_VERSION));
+ return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Invalid Websocket-Version " + headers.get(HEADER_WEBSOCKET_VERSION));
}
if (!headers.containsKey(HEADER_WEBSOCKET_KEY)) {
- return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT,
- "Missing Websocket-Key");
+ return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Missing Websocket-Key");
}
WebSocket webSocket = openWebSocket(session);
@@ -97,8 +104,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
try {
handshakeResponse.addHeader(HEADER_WEBSOCKET_ACCEPT, makeAcceptKey(headers.get(HEADER_WEBSOCKET_KEY)));
} catch (NoSuchAlgorithmException e) {
- return new Response(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT,
- "The SHA-1 Algorithm required for websockets is not available on the server.");
+ return new Response(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "The SHA-1 Algorithm required for websockets is not available on the server.");
}
if (headers.containsKey(HEADER_WEBSOCKET_PROTOCOL)) {
@@ -123,7 +129,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
String connection = headers.get(HEADER_CONNECTION);
return (connection != null && connection.toLowerCase().contains(HEADER_CONNECTION_VALUE.toLowerCase()));
}
-
+
public WebSocket openWebSocket(IHTTPSession handshake) {
return new WebSocket(handshake);
}
@@ -141,11 +147,13 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
/**
* Translates the specified byte array into Base64 string.
* <p>
- * Android has android.util.Base64, sun has sun.misc.Base64Encoder, Java 8 hast java.util.Base64,
- * I have this from stackoverflow: http://stackoverflow.com/a/4265472
+ * Android has android.util.Base64, sun has sun.misc.Base64Encoder, Java 8
+ * hast java.util.Base64, I have this from stackoverflow:
+ * http://stackoverflow.com/a/4265472
* </p>
- *
- * @param buf the byte array (not null)
+ *
+ * @param buf
+ * the byte array (not null)
* @return the translated Base64 string (not null)
*/
private static String encodeBase64(byte[] buf) {
@@ -172,21 +180,31 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
}
return new String(ar);
}
-
+
public static enum State {
- UNCONNECTED, CONNECTING, OPEN, CLOSING, CLOSED
+ UNCONNECTED,
+ CONNECTING,
+ OPEN,
+ CLOSING,
+ CLOSED
}
public class WebSocket {
+
private InputStream in;
+
private OutputStream out;
+
private WebSocketFrame.OpCode continuousOpCode = null;
+
private List<WebSocketFrame> continuousFrames = new LinkedList<WebSocketFrame>();
+
private State state = State.UNCONNECTED;
+
private final NanoHTTPD.IHTTPSession handshakeRequest;
- private final NanoHTTPD.Response handshakeResponse = new NanoHTTPD.Response(
- NanoHTTPD.Response.Status.SWITCH_PROTOCOL, null, (InputStream) null) {
+ private final NanoHTTPD.Response handshakeResponse = new NanoHTTPD.Response(NanoHTTPD.Response.Status.SWITCH_PROTOCOL, null, (InputStream) null) {
+
@Override
protected void send(OutputStream out) {
WebSocket.this.out = out;
@@ -201,8 +219,8 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
this.handshakeRequest = handshakeRequest;
this.in = handshakeRequest.getInputStream();
- handshakeResponse.addHeader(HEADER_UPGRADE, HEADER_UPGRADE_VALUE);
- handshakeResponse.addHeader(HEADER_CONNECTION, HEADER_CONNECTION_VALUE);
+ handshakeResponse.addHeader(HEADER_UPGRADE, HEADER_UPGRADE_VALUE);
+ handshakeResponse.addHeader(HEADER_CONNECTION, HEADER_CONNECTION_VALUE);
}
public NanoHTTPD.IHTTPSession getHandshakeRequest() {
@@ -234,7 +252,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
}
private void handleWebsocketFrame(WebSocketFrame frame) throws IOException {
- onFrameReceived(frame);
+ onFrameReceived(frame);
if (frame.getOpCode() == OpCode.Close) {
handleCloseFrame(frame);
} else if (frame.getOpCode() == OpCode.Ping) {
@@ -260,10 +278,10 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
reason = ((CloseFrame) frame).getCloseReason();
}
if (state == State.CLOSING) {
- //Answer for my requested close
+ // Answer for my requested close
doClose(code, reason, false);
} else {
- //Answer close request from other endpoint and close self
+ // Answer close request from other endpoint and close self
State oldState = state;
state = State.CLOSING;
if (oldState == State.OPEN) {
@@ -275,7 +293,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
private void handleFrameFragment(WebSocketFrame frame) throws IOException {
if (frame.getOpCode() != OpCode.Continuation) {
- //First
+ // First
if (continuousOpCode != null) {
throw new WebSocketException(CloseCode.ProtocolError, "Previous continuous frame sequence not completed.");
}
@@ -283,7 +301,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
continuousFrames.clear();
continuousFrames.add(frame);
} else if (frame.isFin()) {
- //Last
+ // Last
if (continuousOpCode == null) {
throw new WebSocketException(CloseCode.ProtocolError, "Continuous frame sequence was not started.");
}
@@ -291,16 +309,16 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
continuousOpCode = null;
continuousFrames.clear();
} else if (continuousOpCode == null) {
- //Unexpected
+ // Unexpected
throw new WebSocketException(CloseCode.ProtocolError, "Continuous frame sequence was not started.");
} else {
- //Intermediate
+ // Intermediate
continuousFrames.add(frame);
}
}
public synchronized void sendFrame(WebSocketFrame frame) throws IOException {
- onSendFrame(frame);
+ onSendFrame(frame);
frame.write(out);
}
@@ -314,53 +332,58 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
try {
in.close();
} catch (IOException e) {
- LOG.log(Level.FINE, "close failed",e);
+ LOG.log(Level.FINE, "close failed", e);
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
- LOG.log(Level.FINE, "close failed",e);
+ LOG.log(Level.FINE, "close failed", e);
}
}
state = State.CLOSED;
onClose(this, code, reason, initiatedByRemote);
}
- // --------------------------------Public Facade---------------------------
-
+ // --------------------------------Public
+ // Facade---------------------------
+
public void ping(byte[] payload) throws IOException {
- sendFrame(new WebSocketFrame(OpCode.Ping, true, payload));
+ sendFrame(new WebSocketFrame(OpCode.Ping, true, payload));
}
-
+
public void send(byte[] payload) throws IOException {
- sendFrame(new WebSocketFrame(OpCode.Binary, true, payload));
+ sendFrame(new WebSocketFrame(OpCode.Binary, true, payload));
}
-
+
public void send(String payload) throws IOException {
- sendFrame(new WebSocketFrame(OpCode.Text, true, payload));
+ sendFrame(new WebSocketFrame(OpCode.Text, true, payload));
}
-
+
public void close(CloseCode code, String reason) throws IOException {
- State oldState = state;
- state = State.CLOSING;
- if (oldState == State.OPEN) {
- sendFrame(new CloseFrame(code, reason));
- } else {
- doClose(code, reason, false);
- }
+ State oldState = state;
+ state = State.CLOSING;
+ if (oldState == State.OPEN) {
+ sendFrame(new CloseFrame(code, reason));
+ } else {
+ doClose(code, reason, false);
+ }
}
}
-
+
public static class WebSocketFrame {
+
private OpCode opCode;
+
private boolean fin;
+
private byte[] maskingKey;
private byte[] payload;
private transient int _payloadLength;
+
private transient String _payloadString;
private WebSocketFrame(OpCode opCode, boolean fin) {
@@ -524,11 +547,10 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
throw new WebSocketException(CloseCode.ProtocolError, "Invalid data frame 2byte length. (not using minimal length encoding)");
}
} else if (_payloadLength == 127) {
- long _payloadLength = ((long) checkedRead(in.read())) << 56 |
- ((long) checkedRead(in.read())) << 48 |
- ((long) checkedRead(in.read())) << 40 |
- ((long) checkedRead(in.read())) << 32 |
- checkedRead(in.read()) << 24 | checkedRead(in.read()) << 16 | checkedRead(in.read()) << 8 | checkedRead(in.read());
+ long _payloadLength =
+ ((long) checkedRead(in.read())) << 56 | ((long) checkedRead(in.read())) << 48 | ((long) checkedRead(in.read())) << 40
+ | ((long) checkedRead(in.read())) << 32 | checkedRead(in.read()) << 24 | checkedRead(in.read()) << 16 | checkedRead(in.read()) << 8
+ | checkedRead(in.read());
if (_payloadLength < 65536) {
throw new WebSocketException(CloseCode.ProtocolError, "Invalid data frame 4byte length. (not using minimal length encoding)");
}
@@ -569,7 +591,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
}
}
- //Test for Unicode errors
+ // Test for Unicode errors
if (getOpCode() == OpCode.Text) {
_payloadString = binary2Text(getBinaryPayload());
}
@@ -592,7 +614,8 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
out.write(_payloadLength);
} else {
out.write(isMasked() ? 0xFF : 127);
- out.write(_payloadLength >>> 56 & 0); //integer only contains 31 bit
+ out.write(_payloadLength >>> 56 & 0); // integer only contains
+ // 31 bit
out.write(_payloadLength >>> 48 & 0);
out.write(_payloadLength >>> 40 & 0);
out.write(_payloadLength >>> 32 & 0);
@@ -602,7 +625,6 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
out.write(_payloadLength);
}
-
if (isMasked()) {
out.write(maskingKey);
for (int i = 0; i < _payloadLength; i++) {
@@ -619,15 +641,15 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
public static final Charset TEXT_CHARSET = Charset.forName("UTF-8");
public static String binary2Text(byte[] payload) throws CharacterCodingException {
- return new String(payload, TEXT_CHARSET);
+ return new String(payload, TEXT_CHARSET);
}
public static String binary2Text(byte[] payload, int offset, int length) throws CharacterCodingException {
- return new String(payload, offset, length, TEXT_CHARSET);
+ return new String(payload, offset, length, TEXT_CHARSET);
}
public static byte[] text2Binary(String payload) throws CharacterCodingException {
- return payload.getBytes(TEXT_CHARSET);
+ return payload.getBytes(TEXT_CHARSET);
}
@Override
@@ -642,7 +664,8 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
}
private String payloadToString() {
- if (payload == null) return "null";
+ if (payload == null)
+ return "null";
else {
final StringBuilder sb = new StringBuilder();
sb.append('[').append(payload.length).append("b] ");
@@ -666,7 +689,12 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
// --------------------------------CONSTANTS-------------------------------
public static enum OpCode {
- Continuation(0), Text(1), Binary(2), Close(8), Ping(9), Pong(10);
+ Continuation(0),
+ Text(1),
+ Binary(2),
+ Close(8),
+ Ping(9),
+ Pong(10);
private final byte code;
@@ -693,9 +721,18 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
}
public static enum CloseCode {
- NormalClosure(1000), GoingAway(1001), ProtocolError(1002), UnsupportedData(1003), NoStatusRcvd(1005),
- AbnormalClosure(1006), InvalidFramePayloadData(1007), PolicyViolation(1008), MessageTooBig(1009),
- MandatoryExt(1010), InternalServerError(1011), TLSHandshake(1015);
+ NormalClosure(1000),
+ GoingAway(1001),
+ ProtocolError(1002),
+ UnsupportedData(1003),
+ NoStatusRcvd(1005),
+ AbnormalClosure(1006),
+ InvalidFramePayloadData(1007),
+ PolicyViolation(1008),
+ MessageTooBig(1009),
+ MandatoryExt(1010),
+ InternalServerError(1011),
+ TLSHandshake(1015);
private final int code;
@@ -720,15 +757,16 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
// ------------------------------------------------------------------------
public static class CloseFrame extends WebSocketFrame {
+
private CloseCode _closeCode;
+
private String _closeReason;
private CloseFrame(WebSocketFrame wrap) throws CharacterCodingException {
super(wrap);
assert wrap.getOpCode() == OpCode.Close;
if (wrap.getBinaryPayload().length >= 2) {
- _closeCode = CloseCode.find((wrap.getBinaryPayload()[0] & 0xFF) << 8 |
- (wrap.getBinaryPayload()[1] & 0xFF));
+ _closeCode = CloseCode.find((wrap.getBinaryPayload()[0] & 0xFF) << 8 | (wrap.getBinaryPayload()[1] & 0xFF));
_closeReason = binary2Text(getBinaryPayload(), 2, getBinaryPayload().length - 2);
}
}
@@ -761,9 +799,11 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
}
public static class WebSocketException extends IOException {
+
private static final long serialVersionUID = 1L;
-
- private CloseCode code;
+
+ private CloseCode code;
+
private String reason;
public WebSocketException(Exception cause) {
@@ -788,7 +828,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
return reason;
}
}
-
+
// --------------------------------Listener--------------------------------
protected abstract void onPong(WebSocket webSocket, WebSocketFrame pongFrame);
@@ -798,13 +838,12 @@ public abstract class NanoWebSocketServer extends NanoHTTPD {
protected abstract void onClose(WebSocket webSocket, CloseCode code, String reason, boolean initiatedByRemote);
protected abstract void onException(WebSocket webSocket, IOException e);
-
+
protected void onFrameReceived(WebSocketFrame webSocket) {
- // only for debugging
+ // only for debugging
}
public void onSendFrame(WebSocketFrame webSocket) {
- // only for debugging
+ // only for debugging
}
}
-
diff --git a/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java b/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java
index 8aad58e..68c1a7e 100644
--- a/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java
+++ b/websocket/src/main/java/fi/iki/elonen/samples/echo/DebugWebSocketServer.java
@@ -40,15 +40,15 @@ import java.util.logging.Logger;
import fi.iki.elonen.NanoWebSocketServer;
/**
-* @author Paul S. Hawke (paul.hawke@gmail.com)
-* On: 4/23/14 at 10:31 PM
-*/
+ * @author Paul S. Hawke (paul.hawke@gmail.com) On: 4/23/14 at 10:31 PM
+ */
public class DebugWebSocketServer extends NanoWebSocketServer {
+
/**
* logger to log to.
*/
private static Logger LOG = Logger.getLogger(DebugWebSocketServer.class.getName());
-
+
private final boolean debug;
public DebugWebSocketServer(int port, boolean debug) {
@@ -76,15 +76,14 @@ public class DebugWebSocketServer extends NanoWebSocketServer {
@Override
protected void onClose(WebSocket socket, WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) {
if (debug) {
- System.out.println("C [" + (initiatedByRemote ? "Remote" : "Self") + "] " +
- (code != null ? code : "UnknownCloseCode[" + code + "]") +
- (reason != null && !reason.isEmpty() ? ": " + reason : ""));
+ System.out.println("C [" + (initiatedByRemote ? "Remote" : "Self") + "] " + (code != null ? code : "UnknownCloseCode[" + code + "]")
+ + (reason != null && !reason.isEmpty() ? ": " + reason : ""));
}
}
@Override
protected void onException(WebSocket socket, IOException e) {
- LOG.log(Level.SEVERE,"exception occured",e);
+ LOG.log(Level.SEVERE, "exception occured", e);
}
@Override
diff --git a/websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java b/websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java
index 9a90815..3060146 100644
--- a/websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java
+++ b/websocket/src/main/java/fi/iki/elonen/samples/echo/EchoSocketSample.java
@@ -38,6 +38,7 @@ import java.io.IOException;
import fi.iki.elonen.NanoWebSocketServer;
public class EchoSocketSample {
+
public static void main(String[] args) throws IOException {
final boolean debugMode = args.length >= 2 && args[1].toLowerCase().equals("-d");
NanoWebSocketServer ws = new DebugWebSocketServer(args.length > 0 ? Integer.parseInt(args[0]) : 9090, debugMode);
@@ -52,4 +53,3 @@ public class EchoSocketSample {
}
}
-
diff --git a/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java b/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java
index 7519646..ec14156 100644
--- a/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java
+++ b/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java
@@ -61,8 +61,8 @@ public class WebSocketResponseHandlerTest {
@Before
public void setUp() {
- nanoWebSocketServer = Mockito.mock(NanoWebSocketServer.class, Mockito.CALLS_REAL_METHODS);
-
+ nanoWebSocketServer = Mockito.mock(NanoWebSocketServer.class, Mockito.CALLS_REAL_METHODS);
+
headers = new HashMap<String, String>();
headers.put("upgrade", "websocket");
headers.put("connection", "Upgrade");