Java tutorial
/** * Copyright (C) 2011-2014 Barchart, Inc. <http://www.barchart.com/> * * All rights reserved. Licensed under the OSI BSD License. * * http://www.opensource.org/licenses/bsd-license.php */ package com.barchart.netty.server.http; import static org.junit.Assert.*; import io.netty.channel.nio.NioEventLoopGroup; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.util.Queue; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.HttpHostConnectException; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.PoolingClientConnectionManager; import org.apache.http.util.EntityUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.barchart.netty.server.Servers; import com.barchart.netty.server.http.request.HttpServerRequest; import com.barchart.netty.server.http.request.RequestHandlerBase; public class TestHttpServer { private HttpServer server; private DefaultHttpClient client; private PoolingClientConnectionManager connMgr; private int port; private TestRequestHandler basic; private TestRequestHandler async; private TestRequestHandler asyncDelayed; private TestRequestHandler clientDisconnect; private TestRequestHandler error; private TestRequestHandler channelError; private TestRequestHandler serviceHandler; private TestRequestHandler infoHandler; private ChunkedRequestHandler chunkedHandler; @Before public void setUp() throws Exception { basic = new TestRequestHandler("basic", false, 0, 0, false, false); async = new TestRequestHandler("async", true, 0, 0, false, false); asyncDelayed = new TestRequestHandler("async-delayed", true, 50, 0, false, false); clientDisconnect = new TestRequestHandler("", true, 500, 500, false, false); error = new TestRequestHandler("error", false, 0, 0, true, false); channelError = new TestRequestHandler("channel-error", false, 0, 0, false, true); infoHandler = new TestRequestHandler("info", false, 0, 0, false, false); serviceHandler = new TestRequestHandler("service", false, 0, 0, false, false); chunkedHandler = new ChunkedRequestHandler("chunked"); final ServerSocket s = new ServerSocket(0); port = s.getLocalPort(); s.close(); Thread.sleep(100); server = Servers.createHttpServer().requestHandler("/basic", basic).group(new NioEventLoopGroup(1)) .requestHandler("/async", async).requestHandler("/async-delayed", asyncDelayed) .requestHandler("/client-disconnect", clientDisconnect) .requestHandler("/channel-error", channelError).requestHandler("/error", error) .requestHandler("/service/info", infoHandler).requestHandler("/service", serviceHandler) .requestHandler("/chunked", chunkedHandler).maxConnections(1); server.listen(port, "localhost").sync(); connMgr = new PoolingClientConnectionManager(); client = new DefaultHttpClient(connMgr); } @After public void tearDown() throws Exception { connMgr.shutdown(); if (server.running()) { server.shutdown().sync(); } } @Test public void testBasicRequest() throws Exception { for (int i = 0; i < 100; i++) { final HttpGet get = new HttpGet("http://localhost:" + port + "/basic"); final HttpResponse response = client.execute(get); final String content = new BufferedReader(new InputStreamReader(response.getEntity().getContent())) .readLine().trim(); assertEquals("basic", content); } } @Test public void testChunkedRequest() throws Exception { for (int i = 0; i < 100; i++) { final HttpGet get = new HttpGet("http://localhost:" + port + "/chunked"); final HttpResponse response = client.execute(get); final String content = new BufferedReader(new InputStreamReader(response.getEntity().getContent())) .readLine().trim(); assertEquals("chunked", content); } } @Test public void testPostRequest() throws Exception { for (int i = 0; i < 100; i++) { final HttpPost post = new HttpPost("http://localhost:" + port + "/basic"); post.setHeader("Content-Type", "application/x-www-form-urlencoded"); post.setEntity(new StringEntity("id=1&id=2")); final HttpResponse response = client.execute(post); final String content = new BufferedReader(new InputStreamReader(response.getEntity().getContent())) .readLine().trim(); assertEquals("basic", content); assertEquals(1, basic.parameters.size()); assertEquals(2, basic.parameters.get("id").size()); assertEquals("1", basic.parameters.get("id").get(0)); assertEquals("2", basic.parameters.get("id").get(1)); } } @Test public void testAsyncRequest() throws Exception { final HttpGet get = new HttpGet("http://localhost:" + port + "/async"); final HttpResponse response = client.execute(get); final String content = new BufferedReader(new InputStreamReader(response.getEntity().getContent())) .readLine().trim(); assertNotNull(async.lastFuture); assertFalse(async.lastFuture.isCancelled()); assertEquals("async", content); } @Test public void testAsyncDelayedRequest() throws Exception { final HttpGet get = new HttpGet("http://localhost:" + port + "/async-delayed"); final HttpResponse response = client.execute(get); final String content = new BufferedReader(new InputStreamReader(response.getEntity().getContent())) .readLine().trim(); assertNotNull(asyncDelayed.lastFuture); assertFalse(asyncDelayed.lastFuture.isCancelled()); assertEquals("async-delayed", content); } @Test public void testUnknownHandler() throws Exception { final HttpGet get = new HttpGet("http://localhost:" + port + "/unknown"); final HttpResponse response = client.execute(get); EntityUtils.consume(response.getEntity()); assertEquals(404, response.getStatusLine().getStatusCode()); } @Test public void testServerError() throws Exception { final HttpGet get = new HttpGet("http://localhost:" + port + "/error"); final HttpResponse response = client.execute(get); EntityUtils.consume(response.getEntity()); assertEquals(500, response.getStatusLine().getStatusCode()); } @Test public void testReuseRequest() throws Exception { // Parameters were being remembered between requests in pooled objects HttpGet get = new HttpGet("http://localhost:" + port + "/basic?field=value"); HttpResponse response = client.execute(get); assertEquals(200, response.getStatusLine().getStatusCode()); EntityUtils.consume(response.getEntity()); assertEquals(1, basic.parameters.get("field").size()); assertEquals("value", basic.parameters.get("field").get(0)); get = new HttpGet("http://localhost:" + port + "/basic?field=value2"); response = client.execute(get); assertEquals(200, response.getStatusLine().getStatusCode()); EntityUtils.consume(response.getEntity()); assertEquals(1, basic.parameters.get("field").size()); assertEquals("value2", basic.parameters.get("field").get(0)); } @Test public void testMultipleRequests() throws Exception { // New Beta3 was failing on second request due to shared buffer use for (int i = 0; i < 100; i++) { final HttpGet get = new HttpGet("http://localhost:" + port + "/basic"); final HttpResponse response = client.execute(get); assertEquals(200, response.getStatusLine().getStatusCode()); EntityUtils.consume(response.getEntity()); } } @Test public void testPatternRequests() throws Exception { { final HttpGet get = new HttpGet("http://localhost:" + port + "/service/info/10"); final HttpResponse response = client.execute(get); final String content = new BufferedReader(new InputStreamReader(response.getEntity().getContent())) .readLine().trim(); assertEquals("info", content); } { final HttpGet get = new HttpGet("http://localhost:" + port + "/service/something/else"); final HttpResponse response = client.execute(get); final String content = new BufferedReader(new InputStreamReader(response.getEntity().getContent())) .readLine().trim(); assertEquals("service", content); } } @Test public void testTooManyConnections() throws Exception { final Queue<Integer> status = new LinkedBlockingQueue<Integer>(); final Runnable r = new Runnable() { @Override public void run() { try { final HttpResponse response = client .execute(new HttpGet("http://localhost:" + port + "/client-disconnect")); status.add(response.getStatusLine().getStatusCode()); EntityUtils.consume(response.getEntity()); } catch (final Exception e) { e.printStackTrace(); } } }; final Thread t1 = new Thread(r); t1.start(); final Thread t2 = new Thread(r); t2.start(); t1.join(); t2.join(); assertEquals(2, status.size()); assertTrue(status.contains(200)); assertTrue(status.contains(503)); } @Test public void testShutdown() throws Exception { final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); final AtomicBoolean pass = new AtomicBoolean(false); final Thread t = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); server.shutdown(); } catch (final InterruptedException e1) { e1.printStackTrace(); } try { client.execute(new HttpGet("http://localhost:" + port + "/basic")); } catch (final HttpHostConnectException hhce) { pass.set(true); } catch (final Exception e) { e.printStackTrace(); } } }); t.start(); final HttpGet get = new HttpGet("http://localhost:" + port + "/client-disconnect"); final HttpResponse response = client.execute(get); EntityUtils.consume(response.getEntity()); assertEquals(200, response.getStatusLine().getStatusCode()); t.join(); assertTrue(pass.get()); } @Test(expected = HttpHostConnectException.class) public void testKill() throws Exception { final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); executor.schedule(new Runnable() { @Override public void run() { server.kill(); } }, 500, TimeUnit.MILLISECONDS); final HttpGet get = new HttpGet("http://localhost:" + port + "/client-disconnect"); // Should throw exception client.execute(get).getEntity(); } // @Test // Exposed old server handler issue, "Response has already been started" public void testRepeated() throws Exception { for (int i = 0; i < 10000; i++) { testAsyncRequest(); } } private static class ChunkedRequestHandler extends RequestHandlerBase { String data; public ChunkedRequestHandler(final String data_) { data = data_; } @Override public void handle(final HttpServerRequest request) throws IOException { request.response().setChunkSize(1); request.response().write(data); request.response().finish(); } } }