diff options
33 files changed, 997 insertions, 971 deletions
diff --git a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java index 2a7713e..d32ade4 100644 --- a/core/src/main/java/fi/iki/elonen/NanoHTTPD.java +++ b/core/src/main/java/fi/iki/elonen/NanoHTTPD.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -34,6 +34,7 @@ package fi.iki.elonen; */ import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.File; @@ -43,6 +44,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.PushbackInputStream; import java.io.RandomAccessFile; @@ -79,6 +81,9 @@ import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.TrustManagerFactory; +import fi.iki.elonen.NanoHTTPD.Response.IStatus; +import fi.iki.elonen.NanoHTTPD.Response.Status; + /** * A simple, tiny, nicely embeddable HTTP server in Java * <p/> @@ -231,7 +236,7 @@ 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. - * + * * @author LordFokas */ public class CookieHandler implements Iterable<String> { @@ -256,7 +261,7 @@ 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. */ @@ -271,7 +276,7 @@ public abstract class NanoHTTPD { /** * Read a cookie from the HTTP Headers. - * + * * @param name * The cookie's name. * @return The cookie's value if it exists, null otherwise. @@ -286,7 +291,7 @@ public abstract class NanoHTTPD { /** * Sets a cookie. - * + * * @param name * The cookie's name. * @param value @@ -301,7 +306,7 @@ public abstract class NanoHTTPD { /** * 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. @@ -730,11 +735,11 @@ public abstract class NanoHTTPD { // exception up the call stack. throw ste; } catch (IOException ioe) { - Response r = new Response(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage()); + Response r = newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage()); r.send(this.outputStream); safeClose(this.outputStream); } catch (ResponseException re) { - Response r = new Response(re.getStatus(), NanoHTTPD.MIME_PLAINTEXT, re.getMessage()); + Response r = newFixedLengthResponse(re.getStatus(), NanoHTTPD.MIME_PLAINTEXT, re.getMessage()); r.send(this.outputStream); safeClose(this.outputStream); } finally { @@ -993,7 +998,7 @@ public abstract class NanoHTTPD { /** * Adds the files in the request body to the files map. - * + * * @param files * map to modify */ @@ -1107,63 +1112,19 @@ public abstract class NanoHTTPD { private boolean chunkedTransfer; /** - * Create a response with known length. - */ - public static Response NewFixedLengthResponse(IStatus status, String mimeType, InputStream data, int totalBytes) { - return new Response(status, mimeType, data, totalBytes); - } - - /** - * Create a response with unknown length (using HTTP 1.1 chunking). - */ - public static Response NewChunkedResponse(IStatus status, String mimeType, InputStream data) { - return new Response(status, mimeType, data, -1); - } - - @Deprecated - public Response(IStatus status, String mimeType, InputStream data) { - this.status = status; - this.mimeType = mimeType; - this.data = data; - this.contentLength = -1; - this.chunkedTransfer = true; - } - - /** * Creates a fixed length response if totalBytes>=0, otherwise chunked. */ protected Response(IStatus status, String mimeType, InputStream data, int totalBytes) { this.status = status; this.mimeType = mimeType; - this.data = data; - this.contentLength = totalBytes; - this.chunkedTransfer = totalBytes < 0; - } - - /** - * Convenience method that makes an InputStream out of a given UTF-8 - * string. - */ - public Response(IStatus status, String mimeType, String txt) { - this.status = status; - this.mimeType = mimeType; - this.contentLength = 0; - try { - this.data = txt != null ? new ByteArrayInputStream(txt.getBytes("UTF-8")) : null; - this.contentLength = (this.data != null) ? this.data.available() : 0; - } catch (java.io.UnsupportedEncodingException uee) { - NanoHTTPD.LOG.log(Level.SEVERE, "encoding problem", uee); - } catch (java.io.IOException ioe) { - NanoHTTPD.LOG.log(Level.SEVERE, "ByteArrayInputStream.available() failed?!?", ioe); + if (data == null) { + this.data = new ByteArrayInputStream(new byte[0]); + this.contentLength = 0; + } else { + this.data = data; + this.contentLength = totalBytes; } - } - - /** - * Default constructor: response = Status.OK, mime = MIME_HTML and your - * supplied message - */ - public Response(String msg) { - this(Status.OK, NanoHTTPD.MIME_HTML, msg); + this.chunkedTransfer = this.contentLength < 0; } /** @@ -1213,7 +1174,7 @@ public abstract class NanoHTTPD { if (this.status == null) { throw new Error("sendResponse(): Status can't be null."); } - PrintWriter pw = new PrintWriter(outputStream); + PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8")), false); pw.print("HTTP/1.1 " + this.status.getDescription() + " \r\n"); if (mime != null) { @@ -1563,7 +1524,7 @@ public abstract class NanoHTTPD { /** * create a instance of the client handler, subclasses can return a subclass * of the ClientHandler. - * + * * @param finalAccept * the socket the cleint is connected to * @param inputStream @@ -1577,7 +1538,7 @@ public abstract class NanoHTTPD { /** * Instantiate the server runnable, can be overwritten by subclasses to * provide a subclass of the ServerRunnable. - * + * * @param timeout * the socet timeout to use. * @return the server runnable. @@ -1590,7 +1551,7 @@ public abstract class NanoHTTPD { * 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. @@ -1608,7 +1569,7 @@ public abstract class NanoHTTPD { * 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 @@ -1636,7 +1597,7 @@ 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 @@ -1668,11 +1629,50 @@ public abstract class NanoHTTPD { } /** + * Create a response with unknown length (using HTTP 1.1 chunking). + */ + public Response newChunkedResponse(IStatus status, String mimeType, InputStream data) { + return new Response(status, mimeType, data, -1); + } + + /** + * Create a response with known length. + */ + public Response newFixedLengthResponse(IStatus status, String mimeType, InputStream data, int totalBytes) { + return new Response(status, mimeType, data, totalBytes); + } + + /** + * Create a text response with known length. + */ + public Response newFixedLengthResponse(IStatus status, String mimeType, String txt) { + if (txt == null) { + return newFixedLengthResponse(status, mimeType, new ByteArrayInputStream(new byte[0]), 0); + } else { + byte[] bytes; + try { + bytes = txt.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + NanoHTTPD.LOG.log(Level.SEVERE, "encoding problem, responding nothing", e); + bytes = new byte[0]; + } + return newFixedLengthResponse(status, mimeType, new ByteArrayInputStream(bytes), bytes.length); + } + } + + /** + * Create a text response with known length. + */ + public Response newFixedLengthResponse(String msg) { + return newFixedLengthResponse(Status.OK, NanoHTTPD.MIME_HTML, msg); + } + + /** * Override this to customize the server. * <p/> * <p/> * (By default, this returns a 404 "Not Found" plain text error response.) - * + * * @param session * The HTTP session * @return HTTP response, see class Response for details @@ -1684,9 +1684,9 @@ public abstract class NanoHTTPD { try { session.parseBody(files); } catch (IOException ioe) { - return new Response(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage()); + return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage()); } catch (ResponseException re) { - return new Response(re.getStatus(), NanoHTTPD.MIME_PLAINTEXT, re.getMessage()); + return newFixedLengthResponse(re.getStatus(), NanoHTTPD.MIME_PLAINTEXT, re.getMessage()); } } @@ -1700,7 +1700,7 @@ 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" @@ -1715,12 +1715,12 @@ public abstract class NanoHTTPD { */ @Deprecated 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, NanoHTTPD.MIME_PLAINTEXT, "Not Found"); + return newFixedLengthResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Not Found"); } /** * Pluggable strategy for asynchronously executing requests. - * + * * @param asyncRunner * new strategy for handling threads. */ @@ -1730,7 +1730,7 @@ public abstract class NanoHTTPD { /** * Pluggable strategy for creating and cleaning up temporary files. - * + * * @param tempFileManagerFactory * new strategy for handling temp files. */ @@ -1740,7 +1740,7 @@ public abstract class NanoHTTPD { /** * Start the server. - * + * * @throws IOException * if the socket is in use. */ @@ -1750,7 +1750,7 @@ public abstract class NanoHTTPD { /** * Start the server. - * + * * @param timeout * timeout to use for socket connections. * @throws IOException @@ -1791,4 +1791,5 @@ public abstract class NanoHTTPD { public final boolean wasStarted() { return this.myServerSocket != null && this.myThread != null; } + } diff --git a/core/src/test/java/fi/iki/elonen/HttpChunkedResponseTest.java b/core/src/test/java/fi/iki/elonen/HttpChunkedResponseTest.java index 779e43f..d740b18 100644 --- a/core/src/test/java/fi/iki/elonen/HttpChunkedResponseTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpChunkedResponseTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,14 +33,34 @@ package fi.iki.elonen; * #L% */ +import static fi.iki.elonen.NanoHTTPD.Response.Status.OK; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PipedInputStream; -import static fi.iki.elonen.NanoHTTPD.Response.Status.OK; - public class HttpChunkedResponseTest extends HttpServerTest { + private static class ChunkedInputStream extends PipedInputStream { + + int chunk = 0; + + String[] chunks; + + private ChunkedInputStream(String[] chunks) { + this.chunks = chunks; + } + + @Override + public synchronized int read(byte[] buffer) throws IOException { + // Too implementation-linked, but... + for (int i = 0; i < this.chunks[this.chunk].length(); ++i) { + buffer[i] = (byte) this.chunks[this.chunk].charAt(i); + } + return this.chunks[this.chunk++].length(); + } + } + @org.junit.Test public void thatChunkedContentIsChunked() throws Exception { PipedInputStream pipedInputStream = new ChunkedInputStream(new String[]{ @@ -65,31 +85,12 @@ public class HttpChunkedResponseTest extends HttpServerTest { "0", "" }; - testServer.response = new NanoHTTPD.Response(OK, "what/ever", pipedInputStream); - testServer.response.setChunkedTransfer(true); + this.testServer.response = new NanoHTTPD(0) { + }.newChunkedResponse(OK, "what/ever", pipedInputStream); + this.testServer.response.setChunkedTransfer(true); ByteArrayOutputStream byteArrayOutputStream = invokeServer("GET / HTTP/1.0"); assertResponse(byteArrayOutputStream, expected); } - - private static class ChunkedInputStream extends PipedInputStream { - - int chunk = 0; - - String[] chunks; - - private ChunkedInputStream(String[] chunks) { - this.chunks = chunks; - } - - @Override - public synchronized int read(byte[] buffer) throws IOException { - // Too implementation-linked, but... - for (int i = 0; i < chunks[chunk].length(); ++i) { - buffer[i] = (byte) chunks[chunk].charAt(i); - } - return chunks[chunk++].length(); - } - } } diff --git a/core/src/test/java/fi/iki/elonen/HttpDeleteRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpDeleteRequestTest.java index 4756b1d..00b8953 100644 --- a/core/src/test/java/fi/iki/elonen/HttpDeleteRequestTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpDeleteRequestTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,21 +33,19 @@ package fi.iki.elonen; * #L% */ -import org.junit.Test; - import java.io.ByteArrayOutputStream; import java.io.InputStream; -import java.util.List; -import static junit.framework.Assert.*; +import org.junit.Test; public class HttpDeleteRequestTest extends HttpServerTest { @Test public void testDeleteRequestThatDoesntSendBackResponseBody_EmptyString() throws Exception { - testServer.response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.NO_CONTENT, NanoHTTPD.MIME_HTML, ""); + this.testServer.response = new NanoHTTPD(0) { + }.newFixedLengthResponse(NanoHTTPD.Response.Status.NO_CONTENT, NanoHTTPD.MIME_HTML, ""); - ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1"); + ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1"); String[] expected = { "HTTP/1.1 204 No Content", @@ -62,10 +60,11 @@ 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); + public void testDeleteRequestThatDoesntSendBackResponseBody_NullInputStream() throws Exception { + this.testServer.response = new NanoHTTPD(0) { + }.newChunkedResponse(NanoHTTPD.Response.Status.NO_CONTENT, NanoHTTPD.MIME_HTML, (InputStream) null); - ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1"); + ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1"); String[] expected = { "HTTP/1.1 204 No Content", @@ -80,10 +79,11 @@ 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); + public void testDeleteRequestThatDoesntSendBackResponseBody_NullString() throws Exception { + this.testServer.response = new NanoHTTPD(0) { + }.newFixedLengthResponse(NanoHTTPD.Response.Status.NO_CONTENT, NanoHTTPD.MIME_HTML, (String) null); - ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1"); + ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1"); String[] expected = { "HTTP/1.1 204 No Content", @@ -98,13 +98,14 @@ public class HttpDeleteRequestTest extends HttpServerTest { } @Test - public void testDeleteRequestThatSendsBackResponseBody_Success() throws Exception { - testServer.response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "application/xml", "<body />"); + public void testDeleteRequestThatSendsBackResponseBody_Accepted() throws Exception { + this.testServer.response = new NanoHTTPD(0) { + }.newFixedLengthResponse(NanoHTTPD.Response.Status.ACCEPTED, "application/xml", "<body />"); - ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1"); + ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1"); String[] expected = { - "HTTP/1.1 200 OK", + "HTTP/1.1 202 Accepted", "Content-Type: application/xml", "Date: .*", "Connection: keep-alive", @@ -117,13 +118,14 @@ public class HttpDeleteRequestTest extends HttpServerTest { } @Test - public void testDeleteRequestThatSendsBackResponseBody_Accepted() throws Exception { - testServer.response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.ACCEPTED, "application/xml", "<body />"); + public void testDeleteRequestThatSendsBackResponseBody_Success() throws Exception { + this.testServer.response = new NanoHTTPD(0) { + }.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/xml", "<body />"); - ByteArrayOutputStream outputStream = invokeServer("DELETE " + URI + " HTTP/1.1"); + ByteArrayOutputStream outputStream = invokeServer("DELETE " + HttpServerTest.URI + " HTTP/1.1"); String[] expected = { - "HTTP/1.1 202 Accepted", + "HTTP/1.1 200 OK", "Content-Type: application/xml", "Date: .*", "Connection: keep-alive", diff --git a/core/src/test/java/fi/iki/elonen/HttpGetRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpGetRequestTest.java index 9980d2e..0566502 100644 --- a/core/src/test/java/fi/iki/elonen/HttpGetRequestTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpGetRequestTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,173 +33,177 @@ package fi.iki.elonen; * #L% */ -import org.junit.Test; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.util.List; -import static junit.framework.Assert.*; +import org.junit.Test; public class HttpGetRequestTest extends HttpServerTest { @Test - public void testFullyQualifiedWorkingGetRequest() throws Exception { - 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", - "" - }; - - assertResponse(outputStream, expected); + public void testDecodingFieldWithEmptyValueAndFieldWithMissingValueGiveDifferentResults() { + invokeServer("GET " + HttpServerTest.URI + "?foo&bar= HTTP/1.1"); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(0, this.testServer.decodedParamters.get("foo").size()); + assertTrue(this.testServer.decodedParamters.get("bar") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("bar").size()); + assertEquals("", this.testServer.decodedParamters.get("bar").get(0)); } @Test - public void testOutputOfServeSentBackToClient() throws Exception { - String responseBody = "Success!"; - testServer.response = new NanoHTTPD.Response(responseBody); - 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 - }; + public void testDecodingMixtureOfParameters() { + invokeServer("GET " + HttpServerTest.URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1"); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(2, this.testServer.decodedParamters.get("foo").size()); + assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0)); + assertEquals("baz", this.testServer.decodedParamters.get("foo").get(1)); + assertTrue(this.testServer.decodedParamters.get("zot") instanceof List); + assertEquals(0, this.testServer.decodedParamters.get("zot").size()); + assertTrue(this.testServer.decodedParamters.get("zim") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("zim").size()); + assertEquals("", this.testServer.decodedParamters.get("zim").get(0)); + } - assertResponse(outputStream, expected); + @Test + public void testDecodingParametersFromParameterMap() { + invokeServer("GET " + HttpServerTest.URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1"); + assertEquals(this.testServer.decodedParamters, this.testServer.decodedParamtersFromParameter); } + // -------------------------------------------------------------------------------------------------------- + // // + @Test - public void testEmptyHeadersSuppliedToServeMethodFromSimpleWorkingGetRequest() { - invokeServer("GET " + URI + " HTTP/1.1"); - assertNotNull(testServer.parms); - assertNotNull(testServer.header); - assertNotNull(testServer.files); - assertNotNull(testServer.uri); + public void testDecodingParametersWithSingleValue() { + invokeServer("GET " + HttpServerTest.URI + "?foo=bar&baz=zot HTTP/1.1"); + assertEquals("foo=bar&baz=zot", this.testServer.queryParameterString); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("foo").size()); + assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0)); + assertTrue(this.testServer.decodedParamters.get("baz") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("baz").size()); + assertEquals("zot", this.testServer.decodedParamters.get("baz").get(0)); } @Test - public void testSingleUserAgentHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() { - String userAgent = "jUnit 4.8.2 Unit Test"; - invokeServer("GET " + URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\n"); - assertEquals(userAgent, testServer.header.get("user-agent")); - assertEquals(NanoHTTPD.Method.GET, testServer.method); - assertEquals(URI, testServer.uri); + public void testDecodingParametersWithSingleValueAndMissingValue() { + invokeServer("GET " + HttpServerTest.URI + "?foo&baz=zot HTTP/1.1"); + assertEquals("foo&baz=zot", this.testServer.queryParameterString); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(0, this.testServer.decodedParamters.get("foo").size()); + assertTrue(this.testServer.decodedParamters.get("baz") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("baz").size()); + assertEquals("zot", this.testServer.decodedParamters.get("baz").get(0)); } @Test - public void testMultipleHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() { - String userAgent = "jUnit 4.8.2 Unit Test"; - String accept = "text/html"; - invokeServer("GET " + URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\nAccept: " + accept); - assertEquals(userAgent, testServer.header.get("user-agent")); - assertEquals(accept, testServer.header.get("accept")); + public void testDecodingSingleFieldRepeated() { + invokeServer("GET " + HttpServerTest.URI + "?foo=bar&foo=baz HTTP/1.1"); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(2, this.testServer.decodedParamters.get("foo").size()); + assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0)); + assertEquals("baz", this.testServer.decodedParamters.get("foo").get(1)); } @Test - public void testSingleGetParameter() { - invokeServer("GET " + URI + "?foo=bar HTTP/1.1"); - assertEquals("bar", testServer.parms.get("foo")); + public void testEmptyHeadersSuppliedToServeMethodFromSimpleWorkingGetRequest() { + invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1"); + assertNotNull(this.testServer.parms); + assertNotNull(this.testServer.header); + assertNotNull(this.testServer.files); + assertNotNull(this.testServer.uri); } @Test - public void testSingleGetParameterWithNoValue() { - invokeServer("GET " + URI + "?foo HTTP/1.1"); - assertEquals("", testServer.parms.get("foo")); + public void testFullyQualifiedWorkingGetRequest() throws Exception { + ByteArrayOutputStream outputStream = invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1"); + + String[] expected = { + "HTTP/1.1 200 OK", + "Content-Type: text/html", + "Date: .*", + "Connection: keep-alive", + "Content-Length: 0", + "" + }; + + assertResponse(outputStream, expected); } @Test public void testMultipleGetParameters() { - invokeServer("GET " + URI + "?foo=bar&baz=zot HTTP/1.1"); - assertEquals("bar", testServer.parms.get("foo")); - assertEquals("zot", testServer.parms.get("baz")); + invokeServer("GET " + HttpServerTest.URI + "?foo=bar&baz=zot HTTP/1.1"); + assertEquals("bar", this.testServer.parms.get("foo")); + assertEquals("zot", this.testServer.parms.get("baz")); } @Test public void testMultipleGetParametersWithMissingValue() { - invokeServer("GET " + URI + "?foo=&baz=zot HTTP/1.1"); - assertEquals("", testServer.parms.get("foo")); - assertEquals("zot", testServer.parms.get("baz")); + invokeServer("GET " + HttpServerTest.URI + "?foo=&baz=zot HTTP/1.1"); + assertEquals("", this.testServer.parms.get("foo")); + assertEquals("zot", this.testServer.parms.get("baz")); } @Test public void testMultipleGetParametersWithMissingValueAndRequestHeaders() { - invokeServer("GET " + URI + "?foo=&baz=zot HTTP/1.1\nAccept: text/html"); - assertEquals("", testServer.parms.get("foo")); - assertEquals("zot", testServer.parms.get("baz")); - assertEquals("text/html", testServer.header.get("accept")); + invokeServer("GET " + HttpServerTest.URI + "?foo=&baz=zot HTTP/1.1\nAccept: text/html"); + assertEquals("", this.testServer.parms.get("foo")); + assertEquals("zot", this.testServer.parms.get("baz")); + assertEquals("text/html", this.testServer.header.get("accept")); } @Test - public void testDecodingParametersWithSingleValue() { - invokeServer("GET " + URI + "?foo=bar&baz=zot HTTP/1.1"); - assertEquals("foo=bar&baz=zot", testServer.queryParameterString); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(1, testServer.decodedParamters.get("foo").size()); - assertEquals("bar", testServer.decodedParamters.get("foo").get(0)); - assertTrue(testServer.decodedParamters.get("baz") instanceof List); - assertEquals(1, testServer.decodedParamters.get("baz").size()); - assertEquals("zot", testServer.decodedParamters.get("baz").get(0)); + public void testMultipleHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() { + String userAgent = "jUnit 4.8.2 Unit Test"; + String accept = "text/html"; + invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\nAccept: " + accept); + assertEquals(userAgent, this.testServer.header.get("user-agent")); + assertEquals(accept, this.testServer.header.get("accept")); } @Test - public void testDecodingParametersWithSingleValueAndMissingValue() { - invokeServer("GET " + URI + "?foo&baz=zot HTTP/1.1"); - assertEquals("foo&baz=zot", testServer.queryParameterString); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(0, testServer.decodedParamters.get("foo").size()); - assertTrue(testServer.decodedParamters.get("baz") instanceof List); - assertEquals(1, testServer.decodedParamters.get("baz").size()); - assertEquals("zot", testServer.decodedParamters.get("baz").get(0)); - } + public void testOutputOfServeSentBackToClient() throws Exception { + String responseBody = "Success!"; + this.testServer.response = new NanoHTTPD(0) { + }.newFixedLengthResponse(responseBody); + ByteArrayOutputStream outputStream = invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1"); - @Test - public void testDecodingFieldWithEmptyValueAndFieldWithMissingValueGiveDifferentResults() { - invokeServer("GET " + URI + "?foo&bar= HTTP/1.1"); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(0, testServer.decodedParamters.get("foo").size()); - assertTrue(testServer.decodedParamters.get("bar") instanceof List); - assertEquals(1, testServer.decodedParamters.get("bar").size()); - assertEquals("", testServer.decodedParamters.get("bar").get(0)); + String[] expected = { + "HTTP/1.1 200 OK", + "Content-Type: text/html", + "Date: .*", + "Connection: keep-alive", + "Content-Length: 8", + "", + responseBody + }; + + assertResponse(outputStream, expected); } @Test - public void testDecodingSingleFieldRepeated() { - invokeServer("GET " + URI + "?foo=bar&foo=baz HTTP/1.1"); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(2, testServer.decodedParamters.get("foo").size()); - assertEquals("bar", testServer.decodedParamters.get("foo").get(0)); - assertEquals("baz", testServer.decodedParamters.get("foo").get(1)); + public void testSingleGetParameter() { + invokeServer("GET " + HttpServerTest.URI + "?foo=bar HTTP/1.1"); + assertEquals("bar", this.testServer.parms.get("foo")); } @Test - public void testDecodingMixtureOfParameters() { - invokeServer("GET " + URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1"); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(2, testServer.decodedParamters.get("foo").size()); - assertEquals("bar", testServer.decodedParamters.get("foo").get(0)); - assertEquals("baz", testServer.decodedParamters.get("foo").get(1)); - assertTrue(testServer.decodedParamters.get("zot") instanceof List); - assertEquals(0, testServer.decodedParamters.get("zot").size()); - assertTrue(testServer.decodedParamters.get("zim") instanceof List); - assertEquals(1, testServer.decodedParamters.get("zim").size()); - assertEquals("", testServer.decodedParamters.get("zim").get(0)); + public void testSingleGetParameterWithNoValue() { + invokeServer("GET " + HttpServerTest.URI + "?foo HTTP/1.1"); + assertEquals("", this.testServer.parms.get("foo")); } @Test - public void testDecodingParametersFromParameterMap() { - invokeServer("GET " + URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1"); - assertEquals(testServer.decodedParamters, testServer.decodedParamtersFromParameter); + public void testSingleUserAgentHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() { + String userAgent = "jUnit 4.8.2 Unit Test"; + invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\n"); + assertEquals(userAgent, this.testServer.header.get("user-agent")); + assertEquals(NanoHTTPD.Method.GET, this.testServer.method); + assertEquals(HttpServerTest.URI, this.testServer.uri); } - // -------------------------------------------------------------------------------------------------------- - // // } diff --git a/core/src/test/java/fi/iki/elonen/HttpHeadRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpHeadRequestTest.java index 2602fd9..4df669d 100644 --- a/core/src/test/java/fi/iki/elonen/HttpHeadRequestTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpHeadRequestTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,12 +33,14 @@ package fi.iki.elonen; * #L% */ -import org.junit.Test; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.util.List; -import static junit.framework.Assert.*; +import org.junit.Test; public class HttpHeadRequestTest extends HttpServerTest { @@ -46,148 +48,150 @@ public class HttpHeadRequestTest extends HttpServerTest { public void setUp() { super.setUp(); String responseBody = "Success!"; - testServer.response = new NanoHTTPD.Response(responseBody); + this.testServer.response = new NanoHTTPD(0) { + }.newFixedLengthResponse(responseBody); } @Test - public void testHeadRequestDoesntSendBackResponseBody() throws Exception { - 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", - "" - }; - - assertResponse(outputStream, expected); + public void testDecodingFieldWithEmptyValueAndFieldWithMissingValueGiveDifferentResults() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo&bar= HTTP/1.1"); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(0, this.testServer.decodedParamters.get("foo").size()); + assertTrue(this.testServer.decodedParamters.get("bar") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("bar").size()); + assertEquals("", this.testServer.decodedParamters.get("bar").get(0)); } @Test - public void testEmptyHeadersSuppliedToServeMethodFromSimpleWorkingGetRequest() { - invokeServer("HEAD " + URI + " HTTP/1.1"); - assertNotNull(testServer.parms); - assertNotNull(testServer.header); - assertNotNull(testServer.files); - assertNotNull(testServer.uri); + public void testDecodingMixtureOfParameters() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1"); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(2, this.testServer.decodedParamters.get("foo").size()); + assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0)); + assertEquals("baz", this.testServer.decodedParamters.get("foo").get(1)); + assertTrue(this.testServer.decodedParamters.get("zot") instanceof List); + assertEquals(0, this.testServer.decodedParamters.get("zot").size()); + assertTrue(this.testServer.decodedParamters.get("zim") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("zim").size()); + assertEquals("", this.testServer.decodedParamters.get("zim").get(0)); } @Test - public void testSingleUserAgentHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() { - String userAgent = "jUnit 4.8.2 Unit Test"; - invokeServer("HEAD " + URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\n"); - assertEquals(userAgent, testServer.header.get("user-agent")); - assertEquals(NanoHTTPD.Method.HEAD, testServer.method); - assertEquals(URI, testServer.uri); + public void testDecodingParametersFromParameterMap() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1"); + assertEquals(this.testServer.decodedParamters, this.testServer.decodedParamtersFromParameter); } + // -------------------------------------------------------------------------------------------------------- + // // + @Test - public void testMultipleHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() { - String userAgent = "jUnit 4.8.2 Unit Test"; - String accept = "text/html"; - invokeServer("HEAD " + URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\nAccept: " + accept); - assertEquals(userAgent, testServer.header.get("user-agent")); - assertEquals(accept, testServer.header.get("accept")); + public void testDecodingParametersWithSingleValue() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&baz=zot HTTP/1.1"); + assertEquals("foo=bar&baz=zot", this.testServer.queryParameterString); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("foo").size()); + assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0)); + assertTrue(this.testServer.decodedParamters.get("baz") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("baz").size()); + assertEquals("zot", this.testServer.decodedParamters.get("baz").get(0)); } @Test - public void testSingleGetParameter() { - invokeServer("HEAD " + URI + "?foo=bar HTTP/1.1"); - assertEquals("bar", testServer.parms.get("foo")); + public void testDecodingParametersWithSingleValueAndMissingValue() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo&baz=zot HTTP/1.1"); + assertEquals("foo&baz=zot", this.testServer.queryParameterString); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(0, this.testServer.decodedParamters.get("foo").size()); + assertTrue(this.testServer.decodedParamters.get("baz") instanceof List); + assertEquals(1, this.testServer.decodedParamters.get("baz").size()); + assertEquals("zot", this.testServer.decodedParamters.get("baz").get(0)); } @Test - public void testSingleGetParameterWithNoValue() { - invokeServer("HEAD " + URI + "?foo HTTP/1.1"); - assertEquals("", testServer.parms.get("foo")); + public void testDecodingSingleFieldRepeated() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&foo=baz HTTP/1.1"); + assertTrue(this.testServer.decodedParamters.get("foo") instanceof List); + assertEquals(2, this.testServer.decodedParamters.get("foo").size()); + assertEquals("bar", this.testServer.decodedParamters.get("foo").get(0)); + assertEquals("baz", this.testServer.decodedParamters.get("foo").get(1)); } @Test - public void testMultipleGetParameters() { - invokeServer("HEAD " + URI + "?foo=bar&baz=zot HTTP/1.1"); - assertEquals("bar", testServer.parms.get("foo")); - assertEquals("zot", testServer.parms.get("baz")); + public void testEmptyHeadersSuppliedToServeMethodFromSimpleWorkingGetRequest() { + invokeServer("HEAD " + HttpServerTest.URI + " HTTP/1.1"); + assertNotNull(this.testServer.parms); + assertNotNull(this.testServer.header); + assertNotNull(this.testServer.files); + assertNotNull(this.testServer.uri); } @Test - public void testMultipleGetParametersWithMissingValue() { - invokeServer("HEAD " + URI + "?foo=&baz=zot HTTP/1.1"); - assertEquals("", testServer.parms.get("foo")); - assertEquals("zot", testServer.parms.get("baz")); + public void testHeadRequestDoesntSendBackResponseBody() throws Exception { + ByteArrayOutputStream outputStream = invokeServer("HEAD " + HttpServerTest.URI + " HTTP/1.1"); + + String[] expected = { + "HTTP/1.1 200 OK", + "Content-Type: text/html", + "Date: .*", + "Connection: keep-alive", + "Content-Length: 8", + "" + }; + + assertResponse(outputStream, expected); } @Test - public void testMultipleGetParametersWithMissingValueAndRequestHeaders() { - invokeServer("HEAD " + URI + "?foo=&baz=zot HTTP/1.1\nAccept: text/html"); - assertEquals("", testServer.parms.get("foo")); - assertEquals("zot", testServer.parms.get("baz")); - assertEquals("text/html", testServer.header.get("accept")); + public void testMultipleGetParameters() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar&baz=zot HTTP/1.1"); + assertEquals("bar", this.testServer.parms.get("foo")); + assertEquals("zot", this.testServer.parms.get("baz")); } @Test - public void testDecodingParametersWithSingleValue() { - invokeServer("HEAD " + URI + "?foo=bar&baz=zot HTTP/1.1"); - assertEquals("foo=bar&baz=zot", testServer.queryParameterString); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(1, testServer.decodedParamters.get("foo").size()); - assertEquals("bar", testServer.decodedParamters.get("foo").get(0)); - assertTrue(testServer.decodedParamters.get("baz") instanceof List); - assertEquals(1, testServer.decodedParamters.get("baz").size()); - assertEquals("zot", testServer.decodedParamters.get("baz").get(0)); + public void testMultipleGetParametersWithMissingValue() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo=&baz=zot HTTP/1.1"); + assertEquals("", this.testServer.parms.get("foo")); + assertEquals("zot", this.testServer.parms.get("baz")); } @Test - public void testDecodingParametersWithSingleValueAndMissingValue() { - invokeServer("HEAD " + URI + "?foo&baz=zot HTTP/1.1"); - assertEquals("foo&baz=zot", testServer.queryParameterString); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(0, testServer.decodedParamters.get("foo").size()); - assertTrue(testServer.decodedParamters.get("baz") instanceof List); - assertEquals(1, testServer.decodedParamters.get("baz").size()); - assertEquals("zot", testServer.decodedParamters.get("baz").get(0)); + public void testMultipleGetParametersWithMissingValueAndRequestHeaders() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo=&baz=zot HTTP/1.1\nAccept: text/html"); + assertEquals("", this.testServer.parms.get("foo")); + assertEquals("zot", this.testServer.parms.get("baz")); + assertEquals("text/html", this.testServer.header.get("accept")); } @Test - public void testDecodingFieldWithEmptyValueAndFieldWithMissingValueGiveDifferentResults() { - invokeServer("HEAD " + URI + "?foo&bar= HTTP/1.1"); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(0, testServer.decodedParamters.get("foo").size()); - assertTrue(testServer.decodedParamters.get("bar") instanceof List); - assertEquals(1, testServer.decodedParamters.get("bar").size()); - assertEquals("", testServer.decodedParamters.get("bar").get(0)); + public void testMultipleHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() { + String userAgent = "jUnit 4.8.2 Unit Test"; + String accept = "text/html"; + invokeServer("HEAD " + HttpServerTest.URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\nAccept: " + accept); + assertEquals(userAgent, this.testServer.header.get("user-agent")); + assertEquals(accept, this.testServer.header.get("accept")); } @Test - public void testDecodingSingleFieldRepeated() { - invokeServer("HEAD " + URI + "?foo=bar&foo=baz HTTP/1.1"); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(2, testServer.decodedParamters.get("foo").size()); - assertEquals("bar", testServer.decodedParamters.get("foo").get(0)); - assertEquals("baz", testServer.decodedParamters.get("foo").get(1)); + public void testSingleGetParameter() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo=bar HTTP/1.1"); + assertEquals("bar", this.testServer.parms.get("foo")); } @Test - public void testDecodingMixtureOfParameters() { - invokeServer("HEAD " + URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1"); - assertTrue(testServer.decodedParamters.get("foo") instanceof List); - assertEquals(2, testServer.decodedParamters.get("foo").size()); - assertEquals("bar", testServer.decodedParamters.get("foo").get(0)); - assertEquals("baz", testServer.decodedParamters.get("foo").get(1)); - assertTrue(testServer.decodedParamters.get("zot") instanceof List); - assertEquals(0, testServer.decodedParamters.get("zot").size()); - assertTrue(testServer.decodedParamters.get("zim") instanceof List); - assertEquals(1, testServer.decodedParamters.get("zim").size()); - assertEquals("", testServer.decodedParamters.get("zim").get(0)); + public void testSingleGetParameterWithNoValue() { + invokeServer("HEAD " + HttpServerTest.URI + "?foo HTTP/1.1"); + assertEquals("", this.testServer.parms.get("foo")); } @Test - public void testDecodingParametersFromParameterMap() { - invokeServer("HEAD " + URI + "?foo=bar&foo=baz&zot&zim= HTTP/1.1"); - assertEquals(testServer.decodedParamters, testServer.decodedParamtersFromParameter); + public void testSingleUserAgentHeaderSuppliedToServeMethodFromSimpleWorkingGetRequest() { + String userAgent = "jUnit 4.8.2 Unit Test"; + invokeServer("HEAD " + HttpServerTest.URI + " HTTP/1.1\nUser-Agent: " + userAgent + "\n"); + assertEquals(userAgent, this.testServer.header.get("user-agent")); + assertEquals(NanoHTTPD.Method.HEAD, this.testServer.method); + assertEquals(HttpServerTest.URI, this.testServer.uri); } - // -------------------------------------------------------------------------------------------------------- - // // } diff --git a/core/src/test/java/fi/iki/elonen/HttpKeepAliveTest.java b/core/src/test/java/fi/iki/elonen/HttpKeepAliveTest.java index 829d5c5..98bdfcb 100644 --- a/core/src/test/java/fi/iki/elonen/HttpKeepAliveTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpKeepAliveTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -43,9 +43,11 @@ import org.junit.Test; public class HttpKeepAliveTest extends HttpServerTest { + private Throwable error = null; + @Test public void testManyGetRequests() throws Exception { - String request = "GET " + URI + " HTTP/1.1\r\n\r\n"; + String request = "GET " + HttpServerTest.URI + " HTTP/1.1\r\n\r\n"; String[] expected = { "HTTP/1.1 200 OK", "Content-Type: text/html", @@ -60,7 +62,7 @@ public class HttpKeepAliveTest extends HttpServerTest { @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 request = "PUT " + HttpServerTest.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", @@ -72,13 +74,11 @@ public class HttpKeepAliveTest extends HttpServerTest { 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 @@ -87,6 +87,7 @@ public class HttpKeepAliveTest extends HttpServerTest { public void testManyRequests(final String request, final String[] expected) throws Exception { Runnable r = new Runnable() { + @Override public void run() { try { PipedOutputStream requestStream = new PipedOutputStream(); @@ -94,7 +95,7 @@ public class HttpKeepAliveTest extends HttpServerTest { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); NanoHTTPD.DefaultTempFileManager tempFileManager = new NanoHTTPD.DefaultTempFileManager(); try { - NanoHTTPD.HTTPSession session = testServer.createSession(tempFileManager, inputStream, outputStream); + NanoHTTPD.HTTPSession session = HttpKeepAliveTest.this.testServer.createSession(tempFileManager, inputStream, outputStream); for (int i = 0; i < 2048; i++) { requestStream.write(request.getBytes()); requestStream.flush(); @@ -105,16 +106,16 @@ public class HttpKeepAliveTest extends HttpServerTest { tempFileManager.clear(); } } catch (Throwable t) { - error = t; + HttpKeepAliveTest.this.error = t; } } }; Thread t = new Thread(null, r, "Request Thread", 1 << 17); t.start(); t.join(); - if (error != null) { - fail("" + error); - error.printStackTrace(); + if (this.error != null) { + fail("" + this.error); + this.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 9879bbe..fd819b6 100644 --- a/core/src/test/java/fi/iki/elonen/HttpParsingTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpParsingTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,34 +33,31 @@ package fi.iki.elonen; * #L% */ -import org.junit.Test; - -import java.net.URLDecoder; -import java.net.URLEncoder; - import static junit.framework.Assert.assertEquals; +import org.junit.Test; + public class HttpParsingTest extends HttpServerTest { @Test + public void testMultibyteCharacterSupport() throws Exception { + String expected = "Chinese \u738b Letters"; + String input = "Chinese+%e7%8e%8b+Letters"; + assertEquals(expected, this.testServer.decodePercent(input)); + } + + @Test public void testNormalCharacters() throws Exception { for (int i = 0x20; i < 0x80; i++) { String hex = Integer.toHexString(i); String input = "%" + hex; char expected = (char) i; - assertEquals("" + expected, testServer.decodePercent(input)); + assertEquals("" + expected, this.testServer.decodePercent(input)); } } @Test - public void testMultibyteCharacterSupport() throws Exception { - String expected = "Chinese \u738b Letters"; - String input = "Chinese+%e7%8e%8b+Letters"; - assertEquals(expected, testServer.decodePercent(input)); - } - - @Test public void testPlusInQueryParams() throws Exception { - assertEquals("foo bar", testServer.decodePercent("foo+bar")); + assertEquals("foo bar", this.testServer.decodePercent("foo+bar")); } } diff --git a/core/src/test/java/fi/iki/elonen/HttpPostRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpPostRequestTest.java index c83a18d..346eb2d 100644 --- a/core/src/test/java/fi/iki/elonen/HttpPostRequestTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpPostRequestTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,16 +33,15 @@ package fi.iki.elonen; * #L% */ -import org.junit.Test; +import static junit.framework.Assert.assertEquals; import java.io.BufferedReader; import java.io.FileReader; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.UUID; -import static junit.framework.Assert.assertEquals; +import org.junit.Test; public class HttpPostRequestTest extends HttpServerTest { @@ -60,122 +59,126 @@ public class HttpPostRequestTest extends HttpServerTest { public static final String VALUE_TEST_SIMPLE_RAW_DATA_WITH_AMPHASIS = "Test raw data & Result value"; - @Test - public void testSimpleRawPostData() throws Exception { - String header = "POST " + URI + " HTTP/1.1\n"; - String content = VALUE_TEST_SIMPLE_RAW_DATA_WITH_AMPHASIS + "\n"; + /** + * 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 + */ + private String preparePostWithMultipartForm(String fileName, String fileContent) { + String divider = UUID.randomUUID().toString(); + String header = "POST " + HttpServerTest.URI + " HTTP/1.1\nContent-Type: " + "multipart/form-data, boundary=" + divider + "\n"; + String content = + "--" + divider + "\n" + "Content-Disposition: form-data; name=\"" + HttpPostRequestTest.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 + 4) + "\r\n\r\n" + content; + int contentLength = size + contentLengthHeaderValueSize + HttpPostRequestTest.CONTENT_LENGTH.length(); + String input = header + HttpPostRequestTest.CONTENT_LENGTH + (contentLength + 5) + "\r\n\r\n" + content; + + return input; + } + + @Test + public void testPostWithMultipartFormUpload() throws Exception { + String filename = "GrandCanyon.txt"; + String fileContent = HttpPostRequestTest.VALUE; + String input = preparePostWithMultipartForm(filename, fileContent); + invokeServer(input); - assertEquals(0, testServer.parms.size()); - assertEquals(1, testServer.files.size()); - assertEquals(VALUE_TEST_SIMPLE_RAW_DATA_WITH_AMPHASIS, testServer.files.get(POST_RAW_CONTENT_FILE_ENTRY)); + + assertEquals(1, this.testServer.parms.size()); + BufferedReader reader = new BufferedReader(new FileReader(this.testServer.files.get(HttpPostRequestTest.FIELD))); + List<String> lines = readLinesFromFile(reader); + assertLinesOfText(new String[]{ + fileContent + }, lines); } @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"; - 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; + public void testPostWithMultipartFormUploadFilenameHasSpaces() throws Exception { + String fileNameWithSpace = "Grand Canyon.txt"; + String fileContent = HttpPostRequestTest.VALUE; + String input = preparePostWithMultipartForm(fileNameWithSpace, fileContent); + invokeServer(input); - assertEquals(1, testServer.parms.size()); - assertEquals(VALUE, testServer.parms.get(FIELD)); + String fileNameAfter = new ArrayList<String>(this.testServer.parms.values()).get(0); + + assertEquals(fileNameWithSpace, fileNameAfter); } @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 header = "POST " + HttpServerTest.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"; + "--" + divider + "\n" + "Content-Disposition: form-data; name=\"" + HttpPostRequestTest.FIELD + "\"\n" + "\n" + HttpPostRequestTest.VALUE + "\n" + "--" + + divider + "\n" + "Content-Disposition: form-data; name=\"" + HttpPostRequestTest.FIELD2 + "\"\n" + "\n" + HttpPostRequestTest.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; + int contentLength = size + contentLengthHeaderValueSize + HttpPostRequestTest.CONTENT_LENGTH.length(); + String input = header + HttpPostRequestTest.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)); + assertEquals(2, this.testServer.parms.size()); + assertEquals(HttpPostRequestTest.VALUE, this.testServer.parms.get(HttpPostRequestTest.FIELD)); + assertEquals(HttpPostRequestTest.VALUE2, this.testServer.parms.get(HttpPostRequestTest.FIELD2)); } @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 header = "POST " + HttpServerTest.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"; + "--" + divider + "\n" + "Content-Disposition: form-data; name=\"" + HttpPostRequestTest.FIELD + "\"\n" + "\n" + HttpPostRequestTest.VALUE + "\n" + "--" + + divider + "\n" + "Content-Disposition: form-data; name=\"" + HttpPostRequestTest.FIELD2 + "\"\n" + "\n" + HttpPostRequestTest.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; + int contentLength = size + contentLengthHeaderValueSize + HttpPostRequestTest.CONTENT_LENGTH.length(); + String input = header + HttpPostRequestTest.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)); + assertEquals(2, this.testServer.parms.size()); + assertEquals(HttpPostRequestTest.VALUE, this.testServer.parms.get(HttpPostRequestTest.FIELD)); + assertEquals(HttpPostRequestTest.VALUE2, this.testServer.parms.get(HttpPostRequestTest.FIELD2)); } @Test - public void testPostWithMultipartFormUpload() throws Exception { - String filename = "GrandCanyon.txt"; - String fileContent = VALUE; - String input = preparePostWithMultipartForm(filename, fileContent); - + public void testSimplePostWithSingleMultipartFormField() throws Exception { + String divider = UUID.randomUUID().toString(); + String header = "POST " + HttpServerTest.URI + " HTTP/1.1\nContent-Type: " + "multipart/form-data; boundary=" + divider + "\n"; + String content = + "--" + divider + "\n" + "Content-Disposition: form-data; name=\"" + HttpPostRequestTest.FIELD + "\"\n" + "\n" + HttpPostRequestTest.VALUE + "\n" + "--" + + divider + "--\n"; + int size = content.length() + header.length(); + int contentLengthHeaderValueSize = String.valueOf(size).length(); + int contentLength = size + contentLengthHeaderValueSize + HttpPostRequestTest.CONTENT_LENGTH.length(); + String input = header + HttpPostRequestTest.CONTENT_LENGTH + (contentLength + 4) + "\r\n\r\n" + content; 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); + assertEquals(1, this.testServer.parms.size()); + assertEquals(HttpPostRequestTest.VALUE, this.testServer.parms.get(HttpPostRequestTest.FIELD)); } @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); - } - - /** - * 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 - */ - 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"; + public void testSimpleRawPostData() throws Exception { + String header = "POST " + HttpServerTest.URI + " HTTP/1.1\n"; + String content = HttpPostRequestTest.VALUE_TEST_SIMPLE_RAW_DATA_WITH_AMPHASIS + "\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; - - return input; + int contentLength = size + contentLengthHeaderValueSize + HttpPostRequestTest.CONTENT_LENGTH.length(); + String input = header + HttpPostRequestTest.CONTENT_LENGTH + (contentLength + 4) + "\r\n\r\n" + content; + invokeServer(input); + assertEquals(0, this.testServer.parms.size()); + assertEquals(1, this.testServer.files.size()); + assertEquals(HttpPostRequestTest.VALUE_TEST_SIMPLE_RAW_DATA_WITH_AMPHASIS, this.testServer.files.get(HttpPostRequestTest.POST_RAW_CONTENT_FILE_ENTRY)); } } diff --git a/core/src/test/java/fi/iki/elonen/HttpPutRequestTest.java b/core/src/test/java/fi/iki/elonen/HttpPutRequestTest.java index e2755f9..9cc037a 100644 --- a/core/src/test/java/fi/iki/elonen/HttpPutRequestTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpPutRequestTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,20 +33,20 @@ package fi.iki.elonen; * #L% */ -import org.junit.Test; +import static junit.framework.Assert.assertTrue; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.FileReader; import java.util.List; -import static junit.framework.Assert.*; +import org.junit.Test; public class HttpPutRequestTest extends HttpServerTest { @Test public void testPutRequestSendsContent() throws Exception { - ByteArrayOutputStream outputStream = invokeServer("PUT " + URI + " HTTP/1.1\r\n\r\nBodyData 1\nLine 2"); + ByteArrayOutputStream outputStream = invokeServer("PUT " + HttpServerTest.URI + " HTTP/1.1\r\n\r\nBodyData 1\nLine 2"); String[] expectedOutput = { "HTTP/1.1 200 OK", @@ -59,14 +59,14 @@ public class HttpPutRequestTest extends HttpServerTest { assertResponse(outputStream, expectedOutput); - assertTrue(testServer.files.containsKey("content")); + assertTrue(this.testServer.files.containsKey("content")); BufferedReader reader = null; try { String[] expectedInputToServeMethodViaFile = { "BodyData 1", "Line 2" }; - reader = new BufferedReader(new FileReader(testServer.files.get("content"))); + reader = new BufferedReader(new FileReader(this.testServer.files.get("content"))); List<String> lines = readLinesFromFile(reader); assertLinesOfText(expectedInputToServeMethodViaFile, lines); } finally { diff --git a/core/src/test/java/fi/iki/elonen/HttpServerTest.java b/core/src/test/java/fi/iki/elonen/HttpServerTest.java index f7fbb7b..3e3c7a0 100644 --- a/core/src/test/java/fi/iki/elonen/HttpServerTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpServerTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,104 +33,35 @@ package fi.iki.elonen; * #L% */ -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.*; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.StringReader; import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import static junit.framework.Assert.*; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; /** * @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 - public void setUp() { - testServer = new TestServer(); - tempFileManager = new TestTempFileManager(); - } - - @After - public void tearDown() { - tempFileManager._clear(); - } - - @Test - public void testServerExists() { - assertNotNull(testServer); - } - - protected void assertResponse(ByteArrayOutputStream outputStream, String[] expected) throws IOException { - List<String> lines = getOutputLines(outputStream); - assertLinesOfText(expected, lines); - } - - protected void assertLinesOfText(String[] expected, List<String> lines) { - // 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])); - } - } - - protected ByteArrayOutputStream invokeServer(String request) { - ByteArrayInputStream inputStream = new ByteArrayInputStream(request.getBytes()); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - NanoHTTPD.HTTPSession session = testServer.createSession(tempFileManager, inputStream, outputStream); - try { - session.execute(); - } catch (IOException e) { - fail("" + e); - e.printStackTrace(); - } - return outputStream; - } - - protected List<String> getOutputLines(ByteArrayOutputStream outputStream) throws IOException { - BufferedReader reader = new BufferedReader(new StringReader(outputStream.toString())); - return readLinesFromFile(reader); - } - - protected List<String> readLinesFromFile(BufferedReader reader) throws IOException { - List<String> lines = new ArrayList<String>(); - String line = ""; - while (line != null) { - line = reader.readLine(); - if (line != null) { - lines.add(line.trim()); - } - } - return lines; - } - - public static class TestTempFileManager extends NanoHTTPD.DefaultTempFileManager { - - public void _clear() { - super.clear(); - } - - @Override - public void clear() { - // ignore - } - } - public static class TestServer extends NanoHTTPD { - public Response response = new Response(""); + public Response response = newFixedLengthResponse(""); public String uri; @@ -161,6 +92,11 @@ public class HttpServerTest { } @Override + public String decodePercent(String str) { + return super.decodePercent(str); + } + + @Override public Response serve(IHTTPSession session) { this.uri = session.getUri(); this.method = session.getMethod(); @@ -168,19 +104,91 @@ public class HttpServerTest { this.parms = session.getParms(); this.files = new HashMap<String, String>(); try { - session.parseBody(files); + session.parseBody(this.files); } catch (Exception e) { e.printStackTrace(); } - queryParameterString = session.getQueryParameterString(); - this.decodedParamtersFromParameter = decodeParameters(queryParameterString); + this.queryParameterString = session.getQueryParameterString(); + this.decodedParamtersFromParameter = decodeParameters(this.queryParameterString); this.decodedParamters = decodeParameters(session.getQueryParameterString()); - return response; + return this.response; + } + } + + public static class TestTempFileManager extends NanoHTTPD.DefaultTempFileManager { + + public void _clear() { + super.clear(); } @Override - public String decodePercent(String str) { - return super.decodePercent(str); + public void clear() { + // ignore } } + + public static final String URI = "http://www.myserver.org/pub/WWW/someFile.html"; + + protected TestServer testServer; + + private TestTempFileManager tempFileManager; + + protected void assertLinesOfText(String[] expected, List<String> lines) { + // 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])); + } + } + + protected void assertResponse(ByteArrayOutputStream outputStream, String[] expected) throws IOException { + List<String> lines = getOutputLines(outputStream); + assertLinesOfText(expected, lines); + } + + protected List<String> getOutputLines(ByteArrayOutputStream outputStream) throws IOException { + BufferedReader reader = new BufferedReader(new StringReader(outputStream.toString())); + return readLinesFromFile(reader); + } + + protected ByteArrayOutputStream invokeServer(String request) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(request.getBytes()); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + NanoHTTPD.HTTPSession session = this.testServer.createSession(this.tempFileManager, inputStream, outputStream); + try { + session.execute(); + } catch (IOException e) { + fail("" + e); + e.printStackTrace(); + } + return outputStream; + } + + protected List<String> readLinesFromFile(BufferedReader reader) throws IOException { + List<String> lines = new ArrayList<String>(); + String line = ""; + while (line != null) { + line = reader.readLine(); + if (line != null) { + lines.add(line.trim()); + } + } + return lines; + } + + @Before + public void setUp() { + this.testServer = new TestServer(); + this.tempFileManager = new TestTempFileManager(); + } + + @After + public void tearDown() { + this.tempFileManager._clear(); + } + + @Test + public void testServerExists() { + assertNotNull(this.testServer); + } } diff --git a/core/src/test/java/fi/iki/elonen/HttpSessionHeadersTest.java b/core/src/test/java/fi/iki/elonen/HttpSessionHeadersTest.java index 3402533..39e40c6 100644 --- a/core/src/test/java/fi/iki/elonen/HttpSessionHeadersTest.java +++ b/core/src/test/java/fi/iki/elonen/HttpSessionHeadersTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,14 +33,14 @@ package fi.iki.elonen; * #L% */ -import org.junit.Ignore; -import org.junit.Test; +import static org.junit.Assert.assertEquals; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.net.InetAddress; -import static org.junit.Assert.assertEquals; +import org.junit.Ignore; +import org.junit.Test; public class HttpSessionHeadersTest extends HttpServerTest { @@ -56,7 +56,7 @@ public class HttpSessionHeadersTest extends HttpServerTest { @Test @Ignore public void testHeadersRemoteIp() throws Exception { - ByteArrayInputStream inputStream = new ByteArrayInputStream(DUMMY_REQUEST_CONTENT.getBytes()); + ByteArrayInputStream inputStream = new ByteArrayInputStream(HttpSessionHeadersTest.DUMMY_REQUEST_CONTENT.getBytes()); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); String[] ipAddresses = { "127.0.0.1", @@ -65,7 +65,7 @@ public class HttpSessionHeadersTest extends HttpServerTest { }; for (String ipAddress : ipAddresses) { InetAddress inetAddress = InetAddress.getByName(ipAddress); - NanoHTTPD.HTTPSession session = testServer.createSession(TEST_TEMP_FILE_MANAGER, inputStream, outputStream, inetAddress); + NanoHTTPD.HTTPSession session = this.testServer.createSession(HttpSessionHeadersTest.TEST_TEMP_FILE_MANAGER, inputStream, outputStream, inetAddress); assertEquals(ipAddress, session.getHeaders().get("remote-addr")); assertEquals(ipAddress, session.getHeaders().get("http-client-ip")); } diff --git a/core/src/test/java/fi/iki/elonen/InvalidRequestTest.java b/core/src/test/java/fi/iki/elonen/InvalidRequestTest.java index 2c40cd1..2178d63 100644 --- a/core/src/test/java/fi/iki/elonen/InvalidRequestTest.java +++ b/core/src/test/java/fi/iki/elonen/InvalidRequestTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -32,48 +32,48 @@ package fi.iki.elonen; * OF THE POSSIBILITY OF SUCH DAMAGE. * #L% */ -import org.junit.Test; - import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; +import org.junit.Test; + public class InvalidRequestTest extends HttpServerTest { @Test public void testGetRequestWithoutProtocol() { - invokeServer("GET " + URI + "\r\nX-Important-Header: foo"); + invokeServer("GET " + HttpServerTest.URI + "\r\nX-Important-Header: foo"); - assertNotNull(testServer.parms); - assertTrue(testServer.header.size() > 0); - assertNotNull(testServer.files); - assertNotNull(testServer.uri); + assertNotNull(this.testServer.parms); + assertTrue(this.testServer.header.size() > 0); + assertNotNull(this.testServer.files); + assertNotNull(this.testServer.uri); } @Test - public void testPostRequestWithoutProtocol() { - invokeServer("POST " + URI + "\r\nContent-Length: 123"); - assertNotNull(testServer.parms); - assertTrue(testServer.header.size() > 0); - assertNotNull(testServer.files); - assertNotNull(testServer.uri); + public void testGetRequestWithProtocol() { + invokeServer("GET " + HttpServerTest.URI + " HTTP/1.1\r\nX-Important-Header: foo"); + + assertNotNull(this.testServer.parms); + assertTrue(this.testServer.header.size() > 0); + assertNotNull(this.testServer.files); + assertNotNull(this.testServer.uri); } @Test - public void testGetRequestWithProtocol() { - invokeServer("GET " + URI + " HTTP/1.1\r\nX-Important-Header: foo"); - - assertNotNull(testServer.parms); - assertTrue(testServer.header.size() > 0); - assertNotNull(testServer.files); - assertNotNull(testServer.uri); + public void testPostRequestWithoutProtocol() { + invokeServer("POST " + HttpServerTest.URI + "\r\nContent-Length: 123"); + assertNotNull(this.testServer.parms); + assertTrue(this.testServer.header.size() > 0); + assertNotNull(this.testServer.files); + assertNotNull(this.testServer.uri); } @Test public void testPostRequestWithProtocol() { - invokeServer("POST " + URI + " HTTP/1.1\r\nContent-Length: 123"); - assertNotNull(testServer.parms); - assertTrue(testServer.header.size() > 0); - assertNotNull(testServer.files); - assertNotNull(testServer.uri); + invokeServer("POST " + HttpServerTest.URI + " HTTP/1.1\r\nContent-Length: 123"); + assertNotNull(this.testServer.parms); + assertTrue(this.testServer.header.size() > 0); + assertNotNull(this.testServer.files); + assertNotNull(this.testServer.uri); } } 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 f765a38..f085f3e 100644 --- a/core/src/test/java/fi/iki/elonen/integration/CookieIntegrationTest.java +++ b/core/src/test/java/fi/iki/elonen/integration/CookieIntegrationTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen.integration; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,7 +33,13 @@ package fi.iki.elonen.integration; * #L% */ -import fi.iki.elonen.NanoHTTPD; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + import org.apache.http.client.CookieStore; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpGet; @@ -41,81 +47,77 @@ import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.cookie.BasicClientCookie; import org.junit.Test; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -import static org.junit.Assert.*; +import fi.iki.elonen.NanoHTTPD; /** * @author Paul S. Hawke (paul.hawke@gmail.com) On: 9/2/13 at 10:10 PM */ public class CookieIntegrationTest extends IntegrationTestBase<CookieIntegrationTest.CookieTestServer> { - @Test - public void testNoCookies() throws Exception { - HttpGet httpget = new HttpGet("http://localhost:8192/"); - ResponseHandler<String> responseHandler = new BasicResponseHandler(); - httpclient.execute(httpget, responseHandler); + public static class CookieTestServer extends NanoHTTPD { - CookieStore cookies = httpclient.getCookieStore(); - assertEquals(0, cookies.getCookies().size()); + List<Cookie> cookiesReceived = new ArrayList<Cookie>(); + + List<Cookie> cookiesToSend = new ArrayList<Cookie>(); + + public CookieTestServer() { + super(8192); + } + + @Override + public Response serve(IHTTPSession session) { + CookieHandler cookies = session.getCookies(); + for (String cookieName : cookies) { + this.cookiesReceived.add(new Cookie(cookieName, cookies.read(cookieName))); + } + for (Cookie c : this.cookiesToSend) { + cookies.set(c); + } + return newFixedLengthResponse("Cookies!"); + } + } + + @Override + public CookieTestServer createTestServer() { + return new CookieTestServer(); } @Test public void testCookieSentBackToClient() throws Exception { - testServer.cookiesToSend.add(new NanoHTTPD.Cookie("name", "value", 30)); + this.testServer.cookiesToSend.add(new NanoHTTPD.Cookie("name", "value", 30)); HttpGet httpget = new HttpGet("http://localhost:8192/"); ResponseHandler<String> responseHandler = new BasicResponseHandler(); - httpclient.execute(httpget, responseHandler); + this.httpclient.execute(httpget, responseHandler); - CookieStore cookies = httpclient.getCookieStore(); + CookieStore cookies = this.httpclient.getCookieStore(); assertEquals(1, cookies.getCookies().size()); assertEquals("name", cookies.getCookies().get(0).getName()); assertEquals("value", cookies.getCookies().get(0).getValue()); } @Test + public void testNoCookies() throws Exception { + HttpGet httpget = new HttpGet("http://localhost:8192/"); + ResponseHandler<String> responseHandler = new BasicResponseHandler(); + this.httpclient.execute(httpget, responseHandler); + + CookieStore cookies = this.httpclient.getCookieStore(); + assertEquals(0, cookies.getCookies().size()); + } + + @Test public void testServerReceivesCookiesSentFromClient() throws Exception { BasicClientCookie clientCookie = new BasicClientCookie("name", "value"); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_YEAR, 100); clientCookie.setExpiryDate(calendar.getTime()); clientCookie.setDomain("localhost"); - httpclient.getCookieStore().addCookie(clientCookie); + this.httpclient.getCookieStore().addCookie(clientCookie); HttpGet httpget = new HttpGet("http://localhost:8192/"); ResponseHandler<String> responseHandler = new BasicResponseHandler(); - httpclient.execute(httpget, responseHandler); - - assertEquals(1, testServer.cookiesReceived.size()); - assertTrue(testServer.cookiesReceived.get(0).getHTTPHeader().contains("name=value")); - } + this.httpclient.execute(httpget, responseHandler); - @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) { - CookieHandler cookies = session.getCookies(); - for (String cookieName : cookies) { - cookiesReceived.add(new Cookie(cookieName, cookies.read(cookieName))); - } - for (Cookie c : cookiesToSend) { - cookies.set(c); - } - return new Response("Cookies!"); - } + assertEquals(1, this.testServer.cookiesReceived.size()); + assertTrue(this.testServer.cookiesReceived.get(0).getHTTPHeader().contains("name=value")); } } 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 ea4041d..127aac5 100644 --- a/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java +++ b/core/src/test/java/fi/iki/elonen/integration/GetAndPostIntegrationTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen.integration; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,9 +33,14 @@ package fi.iki.elonen.integration; * #L% */ -import fi.iki.elonen.NanoHTTPD; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + import org.apache.http.NameValuePair; -import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; @@ -44,61 +49,61 @@ import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; -import org.junit.After; -import org.junit.Before; import org.junit.Test; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; +import fi.iki.elonen.NanoHTTPD; /** * @author Paul S. Hawke (paul.hawke@gmail.com) On: 5/19/13 at 5:36 PM */ public class GetAndPostIntegrationTest extends IntegrationTestBase<GetAndPostIntegrationTest.TestServer> { - @Test - public void testSimpleGetRequest() throws Exception { - testServer.response = "testSimpleGetRequest"; + public static class TestServer extends NanoHTTPD { - HttpGet httpget = new HttpGet("http://localhost:8192/"); - ResponseHandler<String> responseHandler = new BasicResponseHandler(); - String responseBody = httpclient.execute(httpget, responseHandler); + public String response; - assertEquals("GET:testSimpleGetRequest", responseBody); - } + public TestServer() { + super(8192); + } - @Test - public void testGetRequestWithParameters() throws Exception { - testServer.response = "testGetRequestWithParameters"; + @Override + public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parms, Map<String, String> files) { + StringBuilder sb = new StringBuilder(String.valueOf(method) + ':' + this.response); - HttpGet httpget = new HttpGet("http://localhost:8192/?age=120&gender=Male"); - ResponseHandler<String> responseHandler = new BasicResponseHandler(); - String responseBody = httpclient.execute(httpget, responseHandler); + if (parms.size() > 1) { + parms.remove("NanoHttpd.QUERY_STRING"); + sb.append("-params=").append(parms.size()); + List<String> p = new ArrayList<String>(parms.keySet()); + Collections.sort(p); + for (String k : p) { + sb.append(';').append(k).append('=').append(parms.get(k)); + } + } - assertEquals("GET:testGetRequestWithParameters-params=2;age=120;gender=Male", responseBody); + return newFixedLengthResponse(sb.toString()); + } + } + + @Override + public TestServer createTestServer() { + return new TestServer(); } @Test - public void testPostWithNoParameters() throws Exception { - testServer.response = "testPostWithNoParameters"; + public void testGetRequestWithParameters() throws Exception { + this.testServer.response = "testGetRequestWithParameters"; - HttpPost httppost = new HttpPost("http://localhost:8192/"); + HttpGet httpget = new HttpGet("http://localhost:8192/?age=120&gender=Male"); ResponseHandler<String> responseHandler = new BasicResponseHandler(); - String responseBody = httpclient.execute(httppost, responseHandler); + String responseBody = this.httpclient.execute(httpget, responseHandler); - assertEquals("POST:testPostWithNoParameters", responseBody); + assertEquals("GET:testGetRequestWithParameters-params=2;age=120;gender=Male", responseBody); } @Test public void testPostRequestWithFormEncodedParameters() throws Exception { - testServer.response = "testPostRequestWithFormEncodedParameters"; + this.testServer.response = "testPostRequestWithFormEncodedParameters"; HttpPost httppost = new HttpPost("http://localhost:8192/"); List<NameValuePair> postParameters = new ArrayList<NameValuePair>(); @@ -107,14 +112,14 @@ public class GetAndPostIntegrationTest extends IntegrationTestBase<GetAndPostInt httppost.setEntity(new UrlEncodedFormEntity(postParameters)); ResponseHandler<String> responseHandler = new BasicResponseHandler(); - String responseBody = httpclient.execute(httppost, responseHandler); + String responseBody = this.httpclient.execute(httppost, responseHandler); assertEquals("POST:testPostRequestWithFormEncodedParameters-params=2;age=120;gender=Male", responseBody); } @Test public void testPostRequestWithMultipartEncodedParameters() throws Exception { - testServer.response = "testPostRequestWithMultipartEncodedParameters"; + this.testServer.response = "testPostRequestWithMultipartEncodedParameters"; HttpPost httppost = new HttpPost("http://localhost:8192/"); MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); @@ -123,39 +128,30 @@ public class GetAndPostIntegrationTest extends IntegrationTestBase<GetAndPostInt httppost.setEntity(reqEntity); ResponseHandler<String> responseHandler = new BasicResponseHandler(); - String responseBody = httpclient.execute(httppost, responseHandler); + String responseBody = this.httpclient.execute(httppost, responseHandler); assertEquals("POST:testPostRequestWithMultipartEncodedParameters-params=2;age=120;gender=Male", responseBody); } - @Override - public TestServer createTestServer() { - return new TestServer(); - } - - public static class TestServer extends NanoHTTPD { + @Test + public void testPostWithNoParameters() throws Exception { + this.testServer.response = "testPostWithNoParameters"; - public String response; + HttpPost httppost = new HttpPost("http://localhost:8192/"); + ResponseHandler<String> responseHandler = new BasicResponseHandler(); + String responseBody = this.httpclient.execute(httppost, responseHandler); - public TestServer() { - super(8192); - } + assertEquals("POST:testPostWithNoParameters", responseBody); + } - @Override - public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parms, Map<String, String> files) { - StringBuilder sb = new StringBuilder(String.valueOf(method) + ':' + response); + @Test + public void testSimpleGetRequest() throws Exception { + this.testServer.response = "testSimpleGetRequest"; - if (parms.size() > 1) { - parms.remove("NanoHttpd.QUERY_STRING"); - sb.append("-params=").append(parms.size()); - List<String> p = new ArrayList<String>(parms.keySet()); - Collections.sort(p); - for (String k : p) { - sb.append(';').append(k).append('=').append(parms.get(k)); - } - } + HttpGet httpget = new HttpGet("http://localhost:8192/"); + ResponseHandler<String> responseHandler = new BasicResponseHandler(); + String responseBody = this.httpclient.execute(httpget, responseHandler); - return new Response(sb.toString()); - } + assertEquals("GET:testSimpleGetRequest", responseBody); } } 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 9ad6b73..36de796 100644 --- a/core/src/test/java/fi/iki/elonen/integration/IntegrationTestBase.java +++ b/core/src/test/java/fi/iki/elonen/integration/IntegrationTestBase.java @@ -8,18 +8,18 @@ package fi.iki.elonen.integration; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,13 +33,13 @@ package fi.iki.elonen.integration; * #L% */ -import fi.iki.elonen.NanoHTTPD; -import org.apache.http.client.HttpClient; +import java.io.IOException; + import org.apache.http.impl.client.DefaultHttpClient; import org.junit.After; import org.junit.Before; -import java.io.IOException; +import fi.iki.elonen.NanoHTTPD; /** * @author Paul S. Hawke (paul.hawke@gmail.com) On: 9/2/13 at 10:02 PM @@ -50,12 +50,14 @@ public abstract class IntegrationTestBase<T extends NanoHTTPD> { protected T testServer; + public abstract T createTestServer(); + @Before public void setUp() { - testServer = createTestServer(); - httpclient = new DefaultHttpClient(); + this.testServer = createTestServer(); + this.httpclient = new DefaultHttpClient(); try { - testServer.start(); + this.testServer.start(); } catch (IOException e) { e.printStackTrace(); } @@ -63,9 +65,7 @@ public abstract class IntegrationTestBase<T extends NanoHTTPD> { @After public void tearDown() { - httpclient.getConnectionManager().shutdown(); - testServer.stop(); + this.httpclient.getConnectionManager().shutdown(); + this.testServer.stop(); } - - public abstract T createTestServer(); } 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 6bdde4d..0232dc0 100644 --- a/core/src/test/java/fi/iki/elonen/integration/PutStreamIntegrationTest.java +++ b/core/src/test/java/fi/iki/elonen/integration/PutStreamIntegrationTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen.integration; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -49,23 +49,6 @@ import fi.iki.elonen.NanoHTTPD; public class PutStreamIntegrationTest extends IntegrationTestBase<PutStreamIntegrationTest.TestServer> { - @Test - public void testSimplePutRequest() throws Exception { - String expected = "This HttpPut request has a content-length of 48."; - - HttpPut httpput = new HttpPut("http://localhost:8192/"); - httpput.setEntity(new ByteArrayEntity(expected.getBytes())); - ResponseHandler<String> responseHandler = new BasicResponseHandler(); - String responseBody = httpclient.execute(httpput, responseHandler); - - assertEquals("PUT:" + expected, responseBody); - } - - @Override - public TestServer createTestServer() { - return new TestServer(); - } - public static class TestServer extends NanoHTTPD { public TestServer() { @@ -73,11 +56,6 @@ public class PutStreamIntegrationTest extends IntegrationTestBase<PutStreamInteg } @Override - public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms, Map<String, String> files) { - throw new UnsupportedOperationException(); - } - - @Override public Response serve(IHTTPSession session) { Method method = session.getMethod(); Map<String, String> headers = session.getHeaders(); @@ -89,11 +67,33 @@ public class PutStreamIntegrationTest extends IntegrationTestBase<PutStreamInteg body = new byte[contentLength]; dataInputStream.readFully(body, 0, contentLength); } catch (IOException e) { - return new Response(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, e.getMessage()); + return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, e.getMessage()); } String response = String.valueOf(method) + ':' + new String(body); - return new Response(response); + return newFixedLengthResponse(response); } + + @Override + public Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms, Map<String, String> files) { + throw new UnsupportedOperationException(); + } + } + + @Override + public TestServer createTestServer() { + return new TestServer(); + } + + @Test + public void testSimplePutRequest() throws Exception { + String expected = "This HttpPut request has a content-length of 48."; + + HttpPut httpput = new HttpPut("http://localhost:8192/"); + httpput.setEntity(new ByteArrayEntity(expected.getBytes())); + ResponseHandler<String> responseHandler = new BasicResponseHandler(); + String responseBody = this.httpclient.execute(httpput, responseHandler); + + assertEquals("PUT:" + expected, responseBody); } } diff --git a/core/src/test/java/fi/iki/elonen/integration/ShutdownTest.java b/core/src/test/java/fi/iki/elonen/integration/ShutdownTest.java index fc3b57b..c650f52 100644 --- a/core/src/test/java/fi/iki/elonen/integration/ShutdownTest.java +++ b/core/src/test/java/fi/iki/elonen/integration/ShutdownTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen.integration; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,10 +33,7 @@ package fi.iki.elonen.integration; * #L% */ -import static org.junit.Assert.*; -import fi.iki.elonen.NanoHTTPD; - -import org.junit.Test; +import static org.junit.Assert.fail; import java.io.IOException; import java.io.InputStream; @@ -44,8 +41,24 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; +import org.junit.Test; + +import fi.iki.elonen.NanoHTTPD; + public class ShutdownTest { + private class TestServer extends NanoHTTPD { + + public TestServer() { + super(8092); + } + + @Override + public Response serve(IHTTPSession session) { + return newFixedLengthResponse("Whatever"); + } + } + @Test public void connectionsAreClosedWhenServerStops() throws IOException { TestServer server = new TestServer(); @@ -71,16 +84,4 @@ public class ShutdownTest { in.close(); } - private class TestServer extends NanoHTTPD { - - public TestServer() { - super(8092); - } - - @Override - public Response serve(IHTTPSession session) { - return new Response("Whatever"); - } - } - } 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 43d081c..24bc08a 100644 --- a/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPlugin.java +++ b/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPlugin.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -36,9 +36,11 @@ package fi.iki.elonen; import static fi.iki.elonen.NanoHTTPD.Response.Status.OK; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -107,6 +109,13 @@ 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, NanoHTTPD.MIME_HTML, this.processor.markdownToHtml(markdownSource)); + byte[] bytes; + try { + bytes = this.processor.markdownToHtml(markdownSource).getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + MarkdownWebServerPlugin.LOG.log(Level.SEVERE, "encoding problem, responding nothing", e); + bytes = new byte[0]; + } + return markdownSource == null ? null : new NanoHTTPD.Response(OK, NanoHTTPD.MIME_HTML, new ByteArrayInputStream(bytes), bytes.length); } } 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 29cdc1e..66c2f19 100644 --- a/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPluginInfo.java +++ b/markdown-plugin/src/main/java/fi/iki/elonen/MarkdownWebServerPluginInfo.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. diff --git a/samples/src/main/java/fi/iki/elonen/HelloServer.java b/samples/src/main/java/fi/iki/elonen/HelloServer.java index 7b8c9f0..ef250d5 100644 --- a/samples/src/main/java/fi/iki/elonen/HelloServer.java +++ b/samples/src/main/java/fi/iki/elonen/HelloServer.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -46,6 +46,10 @@ public class HelloServer extends NanoHTTPD { */ private static final Logger LOG = Logger.getLogger(HelloServer.class.getName()); + public static void main(String[] args) { + ServerRunner.run(HelloServer.class); + } + public HelloServer() { super(8080); } @@ -54,21 +58,18 @@ public class HelloServer extends NanoHTTPD { public Response serve(IHTTPSession session) { Method method = session.getMethod(); String uri = session.getUri(); - LOG.info(method + " '" + uri + "' "); + HelloServer.LOG.info(method + " '" + uri + "' "); String msg = "<html><body><h1>Hello server</h1>\n"; Map<String, String> parms = session.getParms(); - if (parms.get("username") == null) + if (parms.get("username") == null) { msg += "<form action='?' method='get'>\n" + " <p>Your name: <input type='text' name='username'></p>\n" + "</form>\n"; - else + } else { msg += "<p>Hello, " + parms.get("username") + "!</p>"; + } msg += "</body></html>\n"; - return new NanoHTTPD.Response(msg); - } - - public static void main(String[] args) { - ServerRunner.run(HelloServer.class); + return newFixedLengthResponse(msg); } } diff --git a/samples/src/main/java/fi/iki/elonen/TempFilesServer.java b/samples/src/main/java/fi/iki/elonen/TempFilesServer.java index 2e0828f..aacd926 100644 --- a/samples/src/main/java/fi/iki/elonen/TempFilesServer.java +++ b/samples/src/main/java/fi/iki/elonen/TempFilesServer.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -43,20 +43,6 @@ import fi.iki.elonen.debug.DebugServer; */ public class TempFilesServer extends DebugServer { - public static void main(String[] args) { - TempFilesServer server = new TempFilesServer(); - server.setTempFileManagerFactory(new ExampleManagerFactory()); - ServerRunner.executeInstance(server); - } - - private static class ExampleManagerFactory implements TempFileManagerFactory { - - @Override - public TempFileManager create() { - return new ExampleManager(); - } - } - private static class ExampleManager implements TempFileManager { private final String tmpdir; @@ -64,31 +50,45 @@ public class TempFilesServer extends DebugServer { private final List<TempFile> tempFiles; private ExampleManager() { - tmpdir = System.getProperty("java.io.tmpdir"); - tempFiles = new ArrayList<TempFile>(); - } - - @Override - public TempFile createTempFile() throws Exception { - DefaultTempFile tempFile = new DefaultTempFile(tmpdir); - tempFiles.add(tempFile); - System.out.println("Created tempFile: " + tempFile.getName()); - return tempFile; + this.tmpdir = System.getProperty("java.io.tmpdir"); + this.tempFiles = new ArrayList<TempFile>(); } @Override public void clear() { - if (!tempFiles.isEmpty()) { + if (!this.tempFiles.isEmpty()) { System.out.println("Cleaning up:"); } - for (TempFile file : tempFiles) { + for (TempFile file : this.tempFiles) { try { System.out.println(" " + file.getName()); file.delete(); } catch (Exception ignored) { } } - tempFiles.clear(); + this.tempFiles.clear(); } + + @Override + public TempFile createTempFile() throws Exception { + DefaultTempFile tempFile = new DefaultTempFile(this.tmpdir); + this.tempFiles.add(tempFile); + System.out.println("Created tempFile: " + tempFile.getName()); + return tempFile; + } + } + + private static class ExampleManagerFactory implements TempFileManagerFactory { + + @Override + public TempFileManager create() { + return new ExampleManager(); + } + } + + public static void main(String[] args) { + TempFilesServer server = new TempFilesServer(); + server.setTempFileManagerFactory(new ExampleManagerFactory()); + ServerRunner.executeInstance(server); } } 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 7780576..10f777d 100644 --- a/samples/src/main/java/fi/iki/elonen/debug/DebugServer.java +++ b/samples/src/main/java/fi/iki/elonen/debug/DebugServer.java @@ -8,18 +8,18 @@ package fi.iki.elonen.debug; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -42,12 +42,16 @@ import fi.iki.elonen.ServerRunner; public class DebugServer extends NanoHTTPD { + public static void main(String[] args) { + ServerRunner.run(DebugServer.class); + } + public DebugServer() { super(8080); } - public static void main(String[] args) { - ServerRunner.run(DebugServer.class); + 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>"); } @Override @@ -80,7 +84,7 @@ public class DebugServer extends NanoHTTPD { sb.append("</body>"); sb.append("</html>"); - return new Response(sb.toString()); + return newFixedLengthResponse(sb.toString()); } private String toString(Map<String, ? extends Object> map) { @@ -99,8 +103,4 @@ public class DebugServer extends NanoHTTPD { sb.append("</ul>"); return sb.toString(); } - - 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>"); - } } diff --git a/webserver/src/main/java/fi/iki/elonen/InternalRewrite.java b/webserver/src/main/java/fi/iki/elonen/InternalRewrite.java index 3d4ca76..fe9d2a4 100644 --- a/webserver/src/main/java/fi/iki/elonen/InternalRewrite.java +++ b/webserver/src/main/java/fi/iki/elonen/InternalRewrite.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,6 +33,7 @@ package fi.iki.elonen; * #L% */ +import java.io.ByteArrayInputStream; import java.util.Map; import fi.iki.elonen.NanoHTTPD.Response; @@ -47,7 +48,7 @@ public class InternalRewrite extends Response { private final Map<String, String> headers; public InternalRewrite(Map<String, String> headers, String uri) { - super(null); + super(Status.OK, NanoHTTPD.MIME_HTML, new ByteArrayInputStream(new byte[0]), 0); this.headers = headers; this.uri = uri; } diff --git a/webserver/src/main/java/fi/iki/elonen/ServerRunner.java b/webserver/src/main/java/fi/iki/elonen/ServerRunner.java index d08eb01..039aac0 100644 --- a/webserver/src/main/java/fi/iki/elonen/ServerRunner.java +++ b/webserver/src/main/java/fi/iki/elonen/ServerRunner.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. diff --git a/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java b/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java index d485fb1..fec6c1d 100644 --- a/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java +++ b/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -37,7 +37,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; -import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; @@ -50,6 +49,8 @@ import java.util.Map; import java.util.ServiceLoader; import java.util.StringTokenizer; +import fi.iki.elonen.NanoHTTPD.Response.IStatus; + public class SimpleWebServer extends NanoHTTPD { /** @@ -251,20 +252,6 @@ public class SimpleWebServer extends NanoHTTPD { return canServeUri; } - // Announce that the file server accepts partial content requests - private Response createResponse(Response.Status status, String mimeType, InputStream message) { - Response res = new Response(status, mimeType, message); - res.addHeader("Accept-Ranges", "bytes"); - return res; - } - - // Announce that the file server accepts partial content requests - private Response createResponse(Response.Status status, String mimeType, String message) { - Response res = new Response(status, mimeType, message); - res.addHeader("Accept-Ranges", "bytes"); - return res; - } - /** * URL-encodes everything between "/"-characters. Encodes spaces as '%20' * instead of '+'. @@ -299,11 +286,11 @@ public class SimpleWebServer extends NanoHTTPD { } protected Response getForbiddenResponse(String s) { - return createResponse(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: " + s); + return newFixedLengthResponse(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 newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "INTERNAL ERROR: " + s); } // Get MIME type from file name extension, if possible @@ -317,7 +304,7 @@ public class SimpleWebServer extends NanoHTTPD { } protected Response getNotFoundResponse() { - return createResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found."); + return newFixedLengthResponse(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found."); } /** @@ -395,6 +382,13 @@ public class SimpleWebServer extends NanoHTTPD { return msg.toString(); } + @Override + public Response newFixedLengthResponse(IStatus status, String mimeType, String message) { + Response response = super.newFixedLengthResponse(status, mimeType, message); + response.addHeader("Accept-Ranges", "bytes"); + return response; + } + private Response respond(Map<String, String> headers, IHTTPSession session, String uri) { // Remove URL arguments uri = uri.trim().replace(File.separatorChar, '/'); @@ -422,7 +416,8 @@ public class SimpleWebServer extends NanoHTTPD { 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 = + newFixedLengthResponse(Response.Status.REDIRECT, NanoHTTPD.MIME_HTML, "<html><body>Redirected: <a href=\"" + uri + "\">" + uri + "</a></body></html>"); res.addHeader("Location", uri); return res; } @@ -434,7 +429,7 @@ public class SimpleWebServer extends NanoHTTPD { if (indexFile == null) { if (f.canRead()) { // No index file, list the directory if it is readable - return createResponse(Response.Status.OK, NanoHTTPD.MIME_HTML, listDirectory(uri, f)); + return newFixedLengthResponse(Response.Status.OK, NanoHTTPD.MIME_HTML, listDirectory(uri, f)); } else { return getForbiddenResponse("No directory listing."); } @@ -521,7 +516,7 @@ public class SimpleWebServer extends NanoHTTPD { long fileLen = file.length(); if (range != null && startFrom >= 0) { if (startFrom >= fileLen) { - res = createResponse(Response.Status.RANGE_NOT_SATISFIABLE, NanoHTTPD.MIME_PLAINTEXT, ""); + res = newFixedLengthResponse(Response.Status.RANGE_NOT_SATISFIABLE, NanoHTTPD.MIME_PLAINTEXT, ""); res.addHeader("Content-Range", "bytes 0-0/" + fileLen); res.addHeader("ETag", etag); } else { @@ -543,16 +538,18 @@ public class SimpleWebServer extends NanoHTTPD { }; fis.skip(startFrom); - res = createResponse(Response.Status.PARTIAL_CONTENT, mime, fis); + res = newFixedLengthResponse(Response.Status.PARTIAL_CONTENT, mime, fis, (int) file.length()); + res.addHeader("Accept-Ranges", "bytes"); res.addHeader("Content-Length", "" + dataLen); res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen); res.addHeader("ETag", etag); } } else { if (etag.equals(header.get("if-none-match"))) { - res = createResponse(Response.Status.NOT_MODIFIED, mime, ""); + res = newFixedLengthResponse(Response.Status.NOT_MODIFIED, mime, ""); } else { - res = createResponse(Response.Status.OK, mime, new FileInputStream(file)); + res = newFixedLengthResponse(Response.Status.OK, mime, new FileInputStream(file), (int) file.length()); + res.addHeader("Accept-Ranges", "bytes"); res.addHeader("Content-Length", "" + fileLen); res.addHeader("ETag", etag); } diff --git a/webserver/src/main/java/fi/iki/elonen/WebServerPlugin.java b/webserver/src/main/java/fi/iki/elonen/WebServerPlugin.java index 8b490d3..bfd5000 100644 --- a/webserver/src/main/java/fi/iki/elonen/WebServerPlugin.java +++ b/webserver/src/main/java/fi/iki/elonen/WebServerPlugin.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. diff --git a/webserver/src/main/java/fi/iki/elonen/WebServerPluginInfo.java b/webserver/src/main/java/fi/iki/elonen/WebServerPluginInfo.java index 0fe5f4e..72a5df9 100644 --- a/webserver/src/main/java/fi/iki/elonen/WebServerPluginInfo.java +++ b/webserver/src/main/java/fi/iki/elonen/WebServerPluginInfo.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. diff --git a/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java b/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java index a37d194..979b2f3 100644 --- a/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java +++ b/websocket/src/main/java/fi/iki/elonen/NanoWebSocketServer.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -739,7 +739,7 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { * hast java.util.Base64, I have this from stackoverflow: * http://stackoverflow.com/a/4265472 * </p> - * + * * @param buf * the byte array (not null) * @return the translated Base64 string (not null) @@ -825,12 +825,12 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { Map<String, String> headers = session.getHeaders(); if (isWebsocketRequested(session)) { if (!NanoWebSocketServer.HEADER_WEBSOCKET_VERSION_VALUE.equalsIgnoreCase(headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_VERSION))) { - return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Invalid Websocket-Version " - + headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_VERSION)); + return newFixedLengthResponse(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, + "Invalid Websocket-Version " + headers.get(NanoWebSocketServer.HEADER_WEBSOCKET_VERSION)); } if (!headers.containsKey(NanoWebSocketServer.HEADER_WEBSOCKET_KEY)) { - return new Response(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Missing Websocket-Key"); + return newFixedLengthResponse(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Missing Websocket-Key"); } WebSocket webSocket = openWebSocket(session); @@ -838,7 +838,8 @@ public abstract class NanoWebSocketServer extends NanoHTTPD { try { handshakeResponse.addHeader(NanoWebSocketServer.HEADER_WEBSOCKET_ACCEPT, makeAcceptKey(headers.get(NanoWebSocketServer.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 newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, + "The SHA-1 Algorithm required for websockets is not available on the server."); } if (headers.containsKey(NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL)) { 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 8f6aa78..27226ee 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 @@ -8,18 +8,18 @@ package fi.iki.elonen.samples.echo; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 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 3060146..cdd5acb 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 @@ -8,18 +8,18 @@ package fi.iki.elonen.samples.echo; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. diff --git a/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java b/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java index ec14156..2c673b1 100644 --- a/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java +++ b/websocket/src/test/java/fi/iki/elonen/WebSocketResponseHandlerTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,8 +33,10 @@ package fi.iki.elonen; * #L% */ -import static junit.framework.Assert.*; -import static org.mockito.Mockito.*; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static org.mockito.Mockito.when; import java.util.HashMap; import java.util.Map; @@ -61,67 +63,67 @@ public class WebSocketResponseHandlerTest { @Before public void setUp() { - nanoWebSocketServer = Mockito.mock(NanoWebSocketServer.class, Mockito.CALLS_REAL_METHODS); + this.nanoWebSocketServer = Mockito.mock(NanoWebSocketServer.class, Mockito.CALLS_REAL_METHODS); - headers = new HashMap<String, String>(); - headers.put("upgrade", "websocket"); - headers.put("connection", "Upgrade"); - headers.put("sec-websocket-key", "x3JJHMbDL1EzLkh9GBhXDw=="); - headers.put("sec-websocket-protocol", "chat, superchat"); - headers.put("sec-websocket-version", "13"); + this.headers = new HashMap<String, String>(); + this.headers.put("upgrade", "websocket"); + this.headers.put("connection", "Upgrade"); + this.headers.put("sec-websocket-key", "x3JJHMbDL1EzLkh9GBhXDw=="); + this.headers.put("sec-websocket-protocol", "chat, superchat"); + this.headers.put("sec-websocket-version", "13"); - when(session.getHeaders()).thenReturn(headers); + when(this.session.getHeaders()).thenReturn(this.headers); } @Test - public void testHandshakeReturnsResponseWithExpectedHeaders() { - Response handshakeResponse = nanoWebSocketServer.serve(session); + public void testConnectionHeaderHandlesKeepAlive_FixingFirefoxConnectIssue() { + this.headers.put("connection", "keep-alive, Upgrade"); + Response handshakeResponse = this.nanoWebSocketServer.serve(this.session); assertNotNull(handshakeResponse); - - assertEquals(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_WEBSOCKET_ACCEPT), "HSmrc0sMlYUkAGmm5OPpG2HaGWk="); - assertEquals(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL), "chat"); } @Test - public void testWrongWebsocketVersionReturnsErrorResponse() { - headers.put("sec-websocket-version", "12"); - - Response handshakeResponse = nanoWebSocketServer.serve(session); + public void testHandshakeReturnsResponseWithExpectedHeaders() { + Response handshakeResponse = this.nanoWebSocketServer.serve(this.session); assertNotNull(handshakeResponse); - assertEquals(Response.Status.BAD_REQUEST, handshakeResponse.getStatus()); + + assertEquals(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_WEBSOCKET_ACCEPT), "HSmrc0sMlYUkAGmm5OPpG2HaGWk="); + assertEquals(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_WEBSOCKET_PROTOCOL), "chat"); } @Test public void testMissingKeyReturnsErrorResponse() { - headers.remove("sec-websocket-key"); + this.headers.remove("sec-websocket-key"); - Response handshakeResponse = nanoWebSocketServer.serve(session); + Response handshakeResponse = this.nanoWebSocketServer.serve(this.session); assertNotNull(handshakeResponse); assertEquals(Response.Status.BAD_REQUEST, handshakeResponse.getStatus()); } @Test - public void testWrongUpgradeHeaderReturnsNullResponse() { - headers.put("upgrade", "not a websocket"); - Response handshakeResponse = nanoWebSocketServer.serve(session); + public void testWrongConnectionHeaderReturnsNullResponse() { + this.headers.put("connection", "Junk"); + Response handshakeResponse = this.nanoWebSocketServer.serve(this.session); assertNull(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_UPGRADE)); } @Test - public void testWrongConnectionHeaderReturnsNullResponse() { - headers.put("connection", "Junk"); - Response handshakeResponse = nanoWebSocketServer.serve(session); + public void testWrongUpgradeHeaderReturnsNullResponse() { + this.headers.put("upgrade", "not a websocket"); + Response handshakeResponse = this.nanoWebSocketServer.serve(this.session); assertNull(handshakeResponse.getHeader(NanoWebSocketServer.HEADER_UPGRADE)); } @Test - public void testConnectionHeaderHandlesKeepAlive_FixingFirefoxConnectIssue() { - headers.put("connection", "keep-alive, Upgrade"); - Response handshakeResponse = nanoWebSocketServer.serve(session); + public void testWrongWebsocketVersionReturnsErrorResponse() { + this.headers.put("sec-websocket-version", "12"); + + Response handshakeResponse = this.nanoWebSocketServer.serve(this.session); assertNotNull(handshakeResponse); + assertEquals(Response.Status.BAD_REQUEST, handshakeResponse.getStatus()); } } diff --git a/websocket/src/test/java/fi/iki/elonen/samples/echo/EchoWebSocketsTest.java b/websocket/src/test/java/fi/iki/elonen/samples/echo/EchoWebSocketsTest.java index 96945f4..ff8b1d6 100644 --- a/websocket/src/test/java/fi/iki/elonen/samples/echo/EchoWebSocketsTest.java +++ b/websocket/src/test/java/fi/iki/elonen/samples/echo/EchoWebSocketsTest.java @@ -8,18 +8,18 @@ package fi.iki.elonen.samples.echo; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -51,13 +51,13 @@ public class EchoWebSocketsTest { @BeforeClass public static void setUp() throws Exception { - server = new DebugWebSocketServer(9191, true); - server.start(); + EchoWebSocketsTest.server = new DebugWebSocketServer(9191, true); + EchoWebSocketsTest.server.start(); } @AfterClass public static void tearDown() throws Exception { - server.stop(); + EchoWebSocketsTest.server.stop(); } @Test diff --git a/websocket/src/test/java/fi/iki/elonen/samples/echo/SimpleEchoSocket.java b/websocket/src/test/java/fi/iki/elonen/samples/echo/SimpleEchoSocket.java index af33f84..ca5023c 100644 --- a/websocket/src/test/java/fi/iki/elonen/samples/echo/SimpleEchoSocket.java +++ b/websocket/src/test/java/fi/iki/elonen/samples/echo/SimpleEchoSocket.java @@ -8,18 +8,18 @@ package fi.iki.elonen.samples.echo; * %% * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * 3. Neither the name of the nanohttpd nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -54,21 +54,10 @@ public class SimpleEchoSocket { private final List<String> receivedMessages = new ArrayList<String>(); - public List<String> getReceivedMessages() { - return receivedMessages; - } - - public List<String> getToSendMessages() { - return toSendMessages; - } - private final List<String> toSendMessages = new ArrayList<String>(); private final CountDownLatch closeLatch; - @SuppressWarnings("unused") - private Session session; - public SimpleEchoSocket() { this.closeLatch = new CountDownLatch(1); } @@ -77,21 +66,27 @@ public class SimpleEchoSocket { return this.closeLatch.await(duration, unit); } + public List<String> getReceivedMessages() { + return this.receivedMessages; + } + + public List<String> getToSendMessages() { + return this.toSendMessages; + } + @OnWebSocketClose public void onClose(int statusCode, String reason) { System.out.printf("Connection closed: %d - %s%n", statusCode, reason); - this.session = null; this.closeLatch.countDown(); } @OnWebSocketConnect public void onConnect(Session session) { System.out.printf("Got connect: %s%n", session); - this.session = session; try { Future<Void> fut; - for (String message : toSendMessages) { + for (String message : this.toSendMessages) { fut = session.getRemote().sendStringByFuture(message); fut.get(5, TimeUnit.SECONDS); } @@ -104,6 +99,6 @@ public class SimpleEchoSocket { @OnWebSocketMessage public void onMessage(String msg) { System.out.printf("Got msg: %s%n", msg); - receivedMessages.add(msg); + this.receivedMessages.add(msg); } } |