package org.deftserver.web; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ConnectException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.nio.channels.UnresolvedAddressException; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicHeader; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.deftserver.example.kv.KeyValueStore; import org.deftserver.example.kv.KeyValueStoreClient; import org.deftserver.io.IOLoop; import org.deftserver.io.timeout.Timeout; import org.deftserver.web.handler.RequestHandler; import org.deftserver.web.http.HttpException; import org.deftserver.web.http.HttpRequest; import org.deftserver.web.http.client.AsynchronousHttpClient; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import com.google.common.collect.Maps; import com.ning.http.client.AsyncCompletionHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Response; public class DeftSystemTest { private static final int PORT = 8081; public static final String expectedPayload = "hello test"; private static class ExampleRequestHandler extends RequestHandler { @Override public void get(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write(expectedPayload); } } private static class WRequestHandler extends RequestHandler { @Override public void get(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write("1"); } } private static class WWRequestHandler extends RequestHandler { @Override public void get(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write("1"); response.write("2"); } } private static class WWFWRequestHandler extends RequestHandler { @Override public void get(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write("1"); response.write("2"); response.flush(); response.write("3"); } } private static class WFWFRequestHandler extends RequestHandler { @Override public void get(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write("1"); response.flush(); response.write("2"); response.flush(); } } private static class WFFFWFFFRequestHandler extends RequestHandler { @Override public void get(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write("1"); response.flush(); response.flush(); response.flush(); response.write("2"); response.flush(); response.flush(); response.flush(); } } private static class DeleteRequestHandler extends RequestHandler { @Override public void delete(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write("del"); response.flush(); response.write("ete"); response.flush(); } } private static class PostRequestHandler extends RequestHandler { @Override public void post(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write("po"); response.flush(); response.write("st"); response.flush(); } } private static class PutRequestHandler extends RequestHandler { @Override public void put(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write("p"); response.flush(); response.write("ut"); response.flush(); } } private static class CapturingRequestRequestHandler extends RequestHandler { @Override public void get(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write(request.getRequestedPath()); } } private static class ThrowingHttpExceptionRequestHandler extends RequestHandler { @Override public void get(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { throw new HttpException(500, "exception message"); } } private static class AsyncThrowingHttpExceptionRequestHandler extends RequestHandler { @Asynchronous @Override public void get(org.deftserver.web.http.HttpRequest request, org.deftserver.web.http.HttpResponse response) { throw new HttpException(500, "exception message"); } } public static class NoBodyRequestHandler extends RequestHandler { @Override public void get(HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.setStatusCode(200); } } public static class MovedPermanentlyRequestHandler extends RequestHandler { @Override public void get(HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.setStatusCode(301); response.setHeader("Location", "/"); } } public static class UserDefinedStaticContentHandler extends RequestHandler { @Override public void get(HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write(new File("src/test/resources/test.txt")); } } public static class KeyValueStoreExampleRequestHandler extends RequestHandler { private final KeyValueStoreClient client = new KeyValueStoreClient(KeyValueStore.HOST, KeyValueStore.PORT); public KeyValueStoreExampleRequestHandler() { new KeyValueStore().start(); client.connect(); } @Override @Asynchronous public void get(HttpRequest request, final org.deftserver.web.http.HttpResponse response) { client.get("deft", new AsyncResult<String>() { @Override public void onFailure(Throwable caught) { /* ignore */} @Override public void onSuccess(String result) { response.write(result).finish(); } }); } } public static class _450KBResponseEntityRequestHandler extends RequestHandler { public static String entity; static { int iterations = 450*1024; StringBuilder sb = new StringBuilder(); for (int i = 1; i <= iterations; i++) { sb.append("a"); } entity = sb.toString(); } @Override public void get(HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write(entity); } } public static class EchoingPostBodyRequestHandler extends RequestHandler { @Override public void post(HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write(request.getBody()); } } public static class AuthenticatedRequestHandler extends RequestHandler { @Override @Authenticated public void get(HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write(request.getHeader("user")); } @Override public String getCurrentUser(HttpRequest request) { return request.getHeader("user"); } } private static class QueryParamsRequestHandler extends RequestHandler { @Override public void get(HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.write(request.getParameter("key1") + " " + request.getParameter("key2")); } } private static class ChunkedRequestHandler extends RequestHandler { @Override public void get(HttpRequest request, org.deftserver.web.http.HttpResponse response) { response.setHeader("Transfer-Encoding", "chunked"); sleep(300); response.write("1\r\n"); response.write("a\r\n").flush(); sleep(300); response.write("5\r\n"); response.write("roger\r\n").flush(); sleep(300); response.write("2\r\n"); response.write("ab\r\n").flush(); sleep(300); response.write("0\r\n"); response.write("\r\n"); } private static void sleep(long ms) { try { Thread.sleep(ms); } catch (InterruptedException ignore) { /* nop */ } } } @BeforeClass public static void setup() { Map<String, RequestHandler> reqHandlers = new HashMap<String, RequestHandler>(); reqHandlers.put("/", new ExampleRequestHandler()); reqHandlers.put("/w", new WRequestHandler()); reqHandlers.put("/ww", new WWRequestHandler()); reqHandlers.put("/wwfw", new WWFWRequestHandler()); reqHandlers.put("/wfwf", new WFWFRequestHandler()); reqHandlers.put("/wfffwfff", new WFFFWFFFRequestHandler()); reqHandlers.put("/delete", new DeleteRequestHandler()); reqHandlers.put("/post", new PostRequestHandler()); reqHandlers.put("/put", new PutRequestHandler()); reqHandlers.put("/capturing/([0-9]+)", new CapturingRequestRequestHandler()); reqHandlers.put("/throw", new ThrowingHttpExceptionRequestHandler()); reqHandlers.put("/async_throw", new AsyncThrowingHttpExceptionRequestHandler()); reqHandlers.put("/no_body", new NoBodyRequestHandler()); reqHandlers.put("/moved_perm", new MovedPermanentlyRequestHandler()); reqHandlers.put("/static_file_handler", new UserDefinedStaticContentHandler()); reqHandlers.put("/keyvalue", new KeyValueStoreExampleRequestHandler()); reqHandlers.put("/450kb_body", new _450KBResponseEntityRequestHandler()); reqHandlers.put("/echo", new EchoingPostBodyRequestHandler()); reqHandlers.put("/authenticated", new AuthenticatedRequestHandler()); reqHandlers.put("/query_params", new QueryParamsRequestHandler()); reqHandlers.put("/chunked", new ChunkedRequestHandler()); final Application application = new Application(reqHandlers); application.setStaticContentDir("src/test/resources"); // start deft instance from a new thread because the start invocation is blocking // (invoking thread will be I/O loop thread) new Thread(new Runnable() { @Override public void run() { new HttpServer(application).listen(PORT); IOLoop.INSTANCE.start(); } }).start(); } @AfterClass public static void tearDown() throws InterruptedException { IOLoop.INSTANCE.addCallback(new AsyncCallback() { @Override public void onCallback() { IOLoop.INSTANCE.stop(); }}); Thread.sleep(300); } @Test public void simpleGetRequestTest() throws ClientProtocolException, IOException { doSimpleGetRequest(); } private void doSimpleGetRequest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/"); HttpResponse response = httpclient.execute(httpget); List<String> expectedHeaders = Arrays.asList(new String[] {"Server", "Date", "Content-Length", "Etag", "Connection"}); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(expectedHeaders.size(), response.getAllHeaders().length); for (String header : expectedHeaders) { assertTrue(response.getFirstHeader(header) != null); } assertEquals(expectedPayload, convertStreamToString(response.getEntity().getContent()).trim()); assertEquals(expectedPayload.length()+"", response.getFirstHeader("Content-Length").getValue()); } /** * Test a RH that does a single write * @throws ClientProtocolException * @throws IOException */ @Test public void wTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/w"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("1", payLoad); assertEquals(5, response.getAllHeaders().length); assertEquals("1", response.getFirstHeader("Content-Length").getValue()); } @Test public void wwTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/ww"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("12", payLoad); assertEquals(5, response.getAllHeaders().length); assertEquals("2", response.getFirstHeader("Content-Length").getValue()); } @Test public void wwfwTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/wwfw"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("123", payLoad); assertEquals(3, response.getAllHeaders().length); } @Test public void wfwfTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/wfwf"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("12", payLoad); assertEquals(3, response.getAllHeaders().length); } @Test public void wfffwfffTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/wfffwfff"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("12", payLoad); assertEquals(3, response.getAllHeaders().length); } @Test public void deleteTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpDelete httpdelete = new HttpDelete("http://localhost:" + PORT + "/delete"); HttpResponse response = httpclient.execute(httpdelete); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("delete", payLoad); } @Test public void PostTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpPost httppost = new HttpPost("http://localhost:" + PORT + "/post"); HttpResponse response = httpclient.execute(httppost); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("post", payLoad); } @Test public void putTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpPut httpput = new HttpPut("http://localhost:" + PORT + "/put"); HttpResponse response = httpclient.execute(httpput); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("put", payLoad); } @Test public void capturingTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/capturing/1911"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("/capturing/1911", payLoad); } @Test public void erroneousCapturingTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Close")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); HttpClient httpclient = new DefaultHttpClient(params); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/capturing/r1911"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(404, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("Not Found", response.getStatusLine().getReasonPhrase()); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("Requested URL: /capturing/r1911 was not found", payLoad); } @Test public void simpleConcurrentGetRequestTest() { int nThreads = 8; int nRequests = 2048; final CountDownLatch latch = new CountDownLatch(nRequests); ExecutorService executor = Executors.newFixedThreadPool(nThreads); for (int i = 1; i <= nRequests; i++) { executor.submit(new Runnable() { @Override public void run() { try { doSimpleGetRequest(); latch.countDown(); } catch (Exception e) { e.printStackTrace(); } } }); } try { latch.await(15 * 1000, TimeUnit.MILLISECONDS); // max wait time } catch (InterruptedException e) { e.printStackTrace(); } if (latch.getCount() != 0) { assertTrue("Did not finish " + nRequests + " # of requests", false); } } @Test public void keepAliveRequestTest() throws ClientProtocolException, IOException { List<Header> headers = new LinkedList<Header>(); headers.add(new BasicHeader("Connection", "Keep-Alive")); HttpParams params = new BasicHttpParams(); params.setParameter("http.default-headers", headers); DefaultHttpClient httpclient = new DefaultHttpClient(params); for (int i = 1; i <= 25; i++) { doKeepAliveRequestTest(httpclient); } } private void doKeepAliveRequestTest(DefaultHttpClient httpclient) throws IOException, ClientProtocolException { HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(5, response.getAllHeaders().length); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals(expectedPayload, payLoad); } @Test public void HTTP_1_0_noConnectionHeaderTest() throws ClientProtocolException, IOException { HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, new ProtocolVersion("HTTP", 1, 0)); DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(5, response.getAllHeaders().length); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals(expectedPayload, payLoad); } @Test public void httpExceptionTest() throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/throw"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(500, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("Internal Server Error", response.getStatusLine().getReasonPhrase()); assertEquals(5, response.getAllHeaders().length); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("exception message", payLoad); } @Test public void asyncHttpExceptionTest() throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/async_throw"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(500, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("Internal Server Error", response.getStatusLine().getReasonPhrase()); assertEquals(5, response.getAllHeaders().length); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("exception message", payLoad); } @Test public void staticFileRequestTest() throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/src/test/resources/test.txt"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(7, response.getAllHeaders().length); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("test.txt", payLoad); } @Test public void pictureStaticFileRequestTest() throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/src/test/resources/n792205362_2067.jpg"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(7, response.getAllHeaders().length); assertEquals("54963", response.getFirstHeader("Content-Length").getValue()); assertEquals("image/jpeg", response.getFirstHeader("Content-Type").getValue()); assertNotNull(response.getFirstHeader("Last-Modified")); } @Test public void pictureStaticLargeFileRequestTest() throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/src/test/resources/f4_impact_1_original.jpg"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(7, response.getAllHeaders().length); //assertEquals("2145094", response.getFirstHeader("Content-Length").getValue()); // my mb says 2145066, imac says 2145094 assertEquals("image/jpeg", response.getFirstHeader("Content-Type").getValue()); assertNotNull(response.getFirstHeader("Last-Modified")); // TODO RS 101026 Verify that the actual body/entity is 2145094 bytes big (when we have support for "large" file) } @Test public void noBodyRequest() throws ClientProtocolException, IOException { HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/no_body"); HttpResponse response = httpclient.execute(httpget); List<String> expectedHeaders = Arrays.asList(new String[] {"Server", "Date", "Content-Length", "Connection"}); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(expectedHeaders.size(), response.getAllHeaders().length); for (String header : expectedHeaders) { assertTrue(response.getFirstHeader(header) != null); } assertEquals("", convertStreamToString(response.getEntity().getContent()).trim()); assertEquals("0", response.getFirstHeader("Content-Length").getValue()); } @Test public void movedPermanentlyRequest() throws ClientProtocolException, IOException { HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/moved_perm"); HttpResponse response = httpclient.execute(httpget); List<String> expectedHeaders = Arrays.asList(new String[] {"Server", "Date", "Content-Length", "Connection", "Etag"}); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(expectedHeaders.size(), response.getAllHeaders().length); for (String header : expectedHeaders) { assertTrue(response.getFirstHeader(header) != null); } assertEquals(expectedPayload, convertStreamToString(response.getEntity().getContent()).trim()); assertEquals(expectedPayload.length()+"", response.getFirstHeader("Content-Length").getValue()); } @Test public void sendGarbageTest() throws IOException { InetSocketAddress socketAddress = new InetSocketAddress(PORT); SocketChannel channel = SocketChannel.open(socketAddress); channel.write( ByteBuffer.wrap( new byte[] {1, 1, 1, 1} // garbage ) ); channel.close(); } @Test public void userDefinedStaticContentHandlerTest() throws ClientProtocolException, IOException { // /static_file_handler DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/static_file_handler"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(4, response.getAllHeaders().length); assertEquals("8", response.getFirstHeader("Content-Length").getValue()); } @Test public void timeoutTest() throws InterruptedException { long now = System.currentTimeMillis(); final CountDownLatch latch = new CountDownLatch(5); final AsyncCallback cb = new AsyncCallback() { @Override public void onCallback() { latch.countDown(); } }; Timeout t1 = new Timeout(now+1000, cb); Timeout t2 = new Timeout(now+1200, cb); Timeout t3 = new Timeout(now+1400, cb); Timeout t4 = new Timeout(now+1600, cb); Timeout t5 = new Timeout(now+1800, cb); IOLoop.INSTANCE.addTimeout(t1); IOLoop.INSTANCE.addTimeout(t2); IOLoop.INSTANCE.addTimeout(t3); IOLoop.INSTANCE.addTimeout(t4); IOLoop.INSTANCE.addTimeout(t5); latch.await(5 * 1000, TimeUnit.MILLISECONDS); assertTrue(latch.getCount() == 0); } @Test public void callbackTest() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(5); final AsyncCallback cb = new AsyncCallback() { @Override public void onCallback() { latch.countDown(); } }; IOLoop.INSTANCE.addCallback(cb); IOLoop.INSTANCE.addCallback(cb); IOLoop.INSTANCE.addCallback(cb); IOLoop.INSTANCE.addCallback(cb); IOLoop.INSTANCE.addCallback(cb); latch.await(5 * 1000, TimeUnit.MILLISECONDS); assertTrue(latch.getCount() == 0); } @Test public void keyValueStoreClientTest() throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/keyvalue"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(5, response.getAllHeaders().length); assertEquals("7", response.getFirstHeader("Content-Length").getValue()); assertEquals("kickass", convertStreamToString(response.getEntity().getContent()).trim()); } //ning === http://github.com/ning/async-http-client @Test public void doSimpleAsyncRequestTestWithNing() throws IOException, InterruptedException { int iterations = 100; final CountDownLatch latch = new CountDownLatch(iterations); AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); for (int i = 1; i <= iterations; i++) { asyncHttpClient.prepareGet("http://localhost:" + PORT + "/"). execute(new AsyncCompletionHandler<com.ning.http.client.Response>(){ @Override public com.ning.http.client.Response onCompleted(com.ning.http.client.Response response) throws Exception{ String body = response.getResponseBody(); assertEquals(expectedPayload, body); { List<String> expectedHeaders = Arrays.asList(new String[] {"Server", "Date", "Content-Length", "Etag", "Connection"}); assertEquals(200, response.getStatusCode()); assertEquals(expectedHeaders.size(), response.getHeaders().size()); for (String header : expectedHeaders) { assertTrue(response.getHeader(header) != null); } assertEquals(expectedPayload.length()+"", response.getHeader("Content-Length")); } latch.countDown(); return response; } @Override public void onThrowable(Throwable t){ assertTrue(false); } }); } latch.await(15 * 1000, TimeUnit.MILLISECONDS); assertEquals(0, latch.getCount()); } // TODO 101108 RS enable when /mySql (AsyncDbHandler is properly implemented) //ning === http://github.com/ning/async-http-client // @Test // public void doAsynchronousRequestTestWithNing() throws IOException, InterruptedException { // int iterations = 200; // final CountDownLatch latch = new CountDownLatch(iterations); // AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); // for (int i = 1; i <= iterations; i++) { // // asyncHttpClient.prepareGet("http://localhost:" + PORT + "/mySql"). // execute(new AsyncCompletionHandler<com.ning.http.client.Response>(){ // // @Override // public com.ning.http.client.Response onCompleted(com.ning.http.client.Response response) throws Exception{ // String body = response.getResponseBody(); // assertEquals("Name: Jim123", body); // List<String> expectedHeaders = Arrays.asList(new String[] {"Server", "Date", "Content-Length", "Etag", "Connection"}); // assertEquals(200, response.getStatusCode()); // assertEquals(expectedHeaders.size(), response.getHeaders().getHeaderNames().size()); // for (String header : expectedHeaders) { // assertTrue(response.getHeader(header) != null); // } // assertEquals(""+ "Name: Jim123".length(), response.getHeader("Content-Length")); // latch.countDown(); // return response; // } // // @Override // public void onThrowable(Throwable t){ // assertTrue(false); // } // // }); // } // latch.await(15 * 1000, TimeUnit.MILLISECONDS); // assertEquals(0, latch.getCount()); // } @Test public void _450KBEntityTest() throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/450kb_body"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(5, response.getAllHeaders().length); //assertEquals(450*1024, Integer.parseInt(response.getFirstHeader("Content-Length").getValue())/8); //assertEquals(450*1024, _450KBResponseEntityRequestHandlr.entity.getBytes(Charsets.UTF_8).length); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals(_450KBResponseEntityRequestHandler.entity, payLoad); } @Test public void smallHttpPostBodyWithUnusualCharactersTest() throws ClientProtocolException, IOException { final String body = "Räger Schildmäijår"; DefaultHttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://localhost:" + PORT + "/echo"); httppost.setEntity(new StringEntity(body)); // HTTP 1.1 says that the default charset is ISO-8859-1 HttpResponse response = httpclient.execute(httppost); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(5, response.getAllHeaders().length); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals(body, payLoad); } @Test public void smallHttpPostBodyTest() throws ClientProtocolException, IOException, InterruptedException { final String body = "Roger Schildmeijer"; final CountDownLatch latch = new CountDownLatch(1); AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); asyncHttpClient.preparePost("http://localhost:" + PORT + "/echo").setBody(body). execute(new AsyncCompletionHandler<Response>(){ @Override public Response onCompleted(Response response) throws Exception{ assertNotNull(response); assertEquals(200, response.getStatusCode()); assertEquals("OK", response.getStatusText()); assertEquals(5, response.getHeaders().size()); String payLoad = response.getResponseBody(); assertEquals(body, payLoad); latch.countDown(); return response; } @Override public void onThrowable(Throwable t) { } }); latch.await(); assertTrue(latch.getCount() == 0); } @Test public void largeHttpPostBodyTest() throws ClientProtocolException, IOException, InterruptedException { String body = "Roger Schildmeijer: 0\n"; for (int i = 1; i <= 1000; i++) { body += "Roger Schildmeijer: " + i + "\n"; } final String expectedBody = body; final CountDownLatch latch = new CountDownLatch(1); AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); asyncHttpClient.preparePost("http://localhost:" + PORT + "/echo").setBody(body). execute(new AsyncCompletionHandler<Response>(){ @Override public Response onCompleted(Response response) throws Exception{ assertNotNull(response); assertEquals(200, response.getStatusCode()); assertEquals("OK", response.getStatusText()); assertEquals(5, response.getHeaders().size()); String payLoad = response.getResponseBody(); assertEquals(expectedBody, payLoad); latch.countDown(); return response; } @Override public void onThrowable(Throwable t) { } }); latch.await(); assertTrue(latch.getCount() == 0); } @Test public void authenticatedRequestHandlerTest() throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/authenticated"); httpget.setHeader("user", "Roger Schildmeijer"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(5, response.getAllHeaders().length); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("Roger Schildmeijer", payLoad); } @Test public void notAuthenticatedRequestHandlerTest() throws ClientProtocolException, IOException { DefaultHttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/authenticated"); httpget.setHeader("wrong_header", "Roger Schildmeijer"); HttpResponse response = httpclient.execute(httpget); assertNotNull(response); assertEquals(403, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("Forbidden", response.getStatusLine().getReasonPhrase()); assertEquals(5, response.getAllHeaders().length); String payLoad = convertStreamToString(response.getEntity().getContent()).trim(); assertEquals("Authentication failed", payLoad); } @Test public void queryParamsTest() throws ClientProtocolException, IOException { HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://localhost:" + PORT + "/query_params?key1=value1&key2=value2"); HttpResponse response = httpclient.execute(httpget); List<String> expectedHeaders = Arrays.asList(new String[] {"Server", "Date", "Content-Length", "Etag", "Connection"}); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals(new ProtocolVersion("HTTP", 1, 1), response.getStatusLine().getProtocolVersion()); assertEquals("OK", response.getStatusLine().getReasonPhrase()); assertEquals(expectedHeaders.size(), response.getAllHeaders().length); for (String header : expectedHeaders) { assertTrue(response.getFirstHeader(header) != null); } final String expected = "value1 value2"; assertEquals(expected, convertStreamToString(response.getEntity().getContent()).trim()); assertEquals(expected.length()+"", response.getFirstHeader("Content-Length").getValue()); } @Test public void multipleStartStopCombinations() throws InterruptedException { final HttpServer server = new HttpServer(new Application(Maps.<String, RequestHandler>newHashMap())); final int n = 10; final CountDownLatch latch = new CountDownLatch(n); for (int i = 0; i < n; i++) { IOLoop.INSTANCE.addCallback(new AsyncCallback() { public void onCallback() { server.listen(PORT+1); }}); IOLoop.INSTANCE.addCallback(new AsyncCallback() { public void onCallback() { server.stop(); latch.countDown(); }}); } latch.await(50, TimeUnit.SECONDS); assertEquals(0, latch.getCount()); } @Test public void connectToUnresolvableAddressUsingAsynchronousHttpClient() throws InterruptedException { final String unresolvableAddress = "http://ttasfdqwertyuiop.se./start"; final CountDownLatch latch = new CountDownLatch(1); final AsynchronousHttpClient client = new AsynchronousHttpClient(); final AsyncCallback runByIOLoop = new AsyncCallback() { public void onCallback() { client.fetch(unresolvableAddress, new AsyncResult<org.deftserver.web.http.client.Response>() { public void onSuccess(org.deftserver.web.http.client.Response result) { client.close(); } public void onFailure(Throwable caught) { if (caught instanceof UnresolvedAddressException) latch.countDown(); client.close(); } }); } }; IOLoop.INSTANCE.addCallback(runByIOLoop); latch.await(30, TimeUnit.SECONDS); assertEquals(0, latch.getCount()); } @Test public void connectToUnconnectableAddressUsingAsynchronousHttpClient() throws InterruptedException { final String unconnectableAddress = "http://localhost:8039/start"; final CountDownLatch latch = new CountDownLatch(1); final AsynchronousHttpClient client = new AsynchronousHttpClient(); final AsyncCallback runByIOLoop = new AsyncCallback() { public void onCallback() { client.fetch(unconnectableAddress, new AsyncResult<org.deftserver.web.http.client.Response>() { public void onSuccess(org.deftserver.web.http.client.Response result) { client.close(); } public void onFailure(Throwable caught) { if (caught instanceof ConnectException) latch.countDown(); client.close(); } }); } }; IOLoop.INSTANCE.addCallback(runByIOLoop); latch.await(30, TimeUnit.SECONDS); assertEquals(0, latch.getCount()); } @Test public void multipleAsynchronousHttpClientTest() throws InterruptedException { for (int i = 0; i < 100; i++) { final CountDownLatch latch = new CountDownLatch(1); final String url = "http://localhost:" + PORT + "/"; final AsynchronousHttpClient http = new AsynchronousHttpClient(); final String[] result = {"BODY_PLACEHOLDER", "STATUSCODE_PLACEHOLDER"}; final AsyncResult<org.deftserver.web.http.client.Response> cb = new AsyncResult<org.deftserver.web.http.client.Response>() { public void onSuccess(org.deftserver.web.http.client.Response response) { result[0] = response.getBody(); result[1] = response.getStatusLine(); latch.countDown(); } public void onFailure(Throwable ignore) { } }; // make sure that the http.fetch(..) is invoked from the ioloop thread IOLoop.INSTANCE.addCallback(new AsyncCallback() { public void onCallback() { http.fetch(url, cb); }}); latch.await(15, TimeUnit.SECONDS); assertEquals(0, latch.getCount()); assertEquals("hello test", result[0]); assertEquals("HTTP/1.1 200 OK", result[1]); } } @Test public void AsynchronousHttpClientConnectionFailedTest() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); final String url = "http://localhost:" + (PORT+1) + "/"; final AsynchronousHttpClient http = new AsynchronousHttpClient(); final AsyncResult<org.deftserver.web.http.client.Response> cb = new AsyncResult<org.deftserver.web.http.client.Response>() { public void onSuccess(org.deftserver.web.http.client.Response response) { } public void onFailure(Throwable e) { if (e instanceof ConnectException) latch.countDown(); } }; // make sure that the http.fetch(..) is invoked from the ioloop thread IOLoop.INSTANCE.addCallback(new AsyncCallback() { public void onCallback() { http.fetch(url, cb); }}); latch.await(5, TimeUnit.SECONDS); assertEquals(0, latch.getCount()); } @Test public void AsynchronousHttpClientRedirectTest() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); //final String url = "http://localhost:" + (PORT) + "/moved_perm"; final String url = "http://localhost:" + PORT + "/moved_perm"; final AsynchronousHttpClient http = new AsynchronousHttpClient(); final AsyncResult<org.deftserver.web.http.client.Response> cb = new AsyncResult<org.deftserver.web.http.client.Response>() { public void onSuccess(org.deftserver.web.http.client.Response response) { if (response.getBody().equals(expectedPayload)) { latch.countDown(); } } public void onFailure(Throwable e) { } }; // make sure that the http.fetch(..) is invoked from the ioloop thread IOLoop.INSTANCE.addCallback(new AsyncCallback() { public void onCallback() { http.fetch(url, cb); }}); latch.await(5, TimeUnit.SECONDS); assertEquals(0, latch.getCount()); } @Test public void asynchronousHttpClientTransferEncodingChunkedTest() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); final String url = "http://localhost:" + PORT + "/chunked"; final AsynchronousHttpClient http = new AsynchronousHttpClient(); final AsyncResult<org.deftserver.web.http.client.Response> cb = new AsyncResult<org.deftserver.web.http.client.Response>() { public void onSuccess(org.deftserver.web.http.client.Response response) { if (response.getBody().equals("arogerab") && response.getHeader("Transfer-Encoding").equals("chunked")) { latch.countDown(); } } public void onFailure(Throwable e) { } }; // make sure that the http.fetch(..) is invoked from the ioloop thread IOLoop.INSTANCE.addCallback(new AsyncCallback() { public void onCallback() { http.fetch(url, cb); }}); latch.await(5, TimeUnit.SECONDS); assertEquals(0, latch.getCount()); } private String convertStreamToString(InputStream is) throws IOException { if (is != null) { StringBuilder sb = new StringBuilder(); String line; try { BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } } finally { is.close(); } return sb.toString(); } else { return ""; } } }