/** * Copyright (C) Zhang,Yuexiang (xfeep) * */ package nginx.clojure.embed; import java.io.IOException; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import nginx.clojure.MessageAdapter; import nginx.clojure.NginxClojureRT; import nginx.clojure.NginxHttpServerChannel; import nginx.clojure.WholeMessageAdapter; import nginx.clojure.java.ArrayMap; import nginx.clojure.java.NginxJavaRequest; import nginx.clojure.java.NginxJavaRingHandler; import nginx.clojure.util.NginxSharedHashMap; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class JavaHandlersTest { public static class HelloHandler implements NginxJavaRingHandler { @Override public Object[] invoke(Map<String, Object> request) throws IOException { return new Object[]{200, null, "Hello, Embeded Nginx!"}; } } public static class WebSocketWholeMessageEcho implements NginxJavaRingHandler { @Override public Object[] invoke(Map<String, Object> request) throws IOException { NginxHttpServerChannel ch = ((NginxJavaRequest)request).hijack(true); if (ch.webSocketUpgrade(true)) { ch.addListener(ch, new WholeMessageAdapter<NginxHttpServerChannel>(9*1024){ @Override public void onOpen(NginxHttpServerChannel sc) throws IOException { System.out.println("on open!"); } @Override public void onWholeTextMessage(NginxHttpServerChannel sc, String message) throws IOException { sc.send(message, true, false); } }); } return null; } } public static class WebSocketFullFunctionEcho implements NginxJavaRingHandler { @Override public Object[] invoke(Map<String, Object> request) throws IOException { NginxJavaRequest r = (NginxJavaRequest)request; NginxHttpServerChannel sc = r.hijack(true); if (!sc.webSocketUpgrade(true)) { return null; } sc.addListener(sc, new MessageAdapter<NginxHttpServerChannel>() { int total = 0; @Override public void onOpen(NginxHttpServerChannel data) { NginxClojureRT.log.debug("WSEcho onOpen!"); } @Override public void onTextMessage(NginxHttpServerChannel sc, String message, boolean remaining) throws IOException { if (NginxClojureRT.log.isDebugEnabled()) { NginxClojureRT.log.debug("WSEcho onTextMessage: msg=%s, rem=%s", message, remaining); } total += message.length(); sc.send(message, !remaining, false); } @Override public void onBinaryMessage(NginxHttpServerChannel sc, ByteBuffer message, boolean remining) throws IOException { if (NginxClojureRT.log.isDebugEnabled()) { NginxClojureRT.log.debug("WSEcho onBinaryMessage: msg=%s, rem=%s, total=%d", message, remining, total); } total += message.remaining(); sc.send(message, !remining, false); } @Override public void onClose(NginxHttpServerChannel req) { if (NginxClojureRT.log.isDebugEnabled()) { NginxClojureRT.log.debug("WSEcho onClose: total=%d", total); } } @Override public void onClose(NginxHttpServerChannel req, long status, String reason) { if (NginxClojureRT.log.isDebugEnabled()) { NginxClojureRT.log.info("WSEcho onClose2: total=%d, status=%d, reason=%s", total, status, reason); } } @Override public void onError(NginxHttpServerChannel data, long status) { if (NginxClojureRT.log.isDebugEnabled()) { NginxClojureRT.log.info("WSEcho onError: total=%d, status=%d", total, status); } } }); return null; } } public static class WebSocketMixedWithLongPoolingHandler implements NginxJavaRingHandler { @Override public Object[] invoke(Map<String, Object> request) throws IOException { NginxHttpServerChannel sc = ((NginxJavaRequest)request).hijack(true); if (sc.webSocketUpgrade(false)) { //websocket sc.addListener(sc, new WholeMessageAdapter<NginxHttpServerChannel>(9*1024){ @Override public void onOpen(NginxHttpServerChannel sc) throws IOException { System.out.println("websocket on open!"); } @Override public void onWholeTextMessage(NginxHttpServerChannel sc, String message) throws IOException { sc.send(message, true, false); } }); }else { //long polling sc.addListener(sc, new MessageAdapter<NginxHttpServerChannel>() { @Override public void onOpen(NginxHttpServerChannel data) throws IOException { System.out.println("general long polling channel on open!"); } }); sc.sendResponse(new Object[] {200, null, request.get("query-string")}); } return null; } } public static class CloseWaitIssue implements NginxJavaRingHandler { @Override public Object[] invoke(Map<String, Object> request) throws IOException { NginxHttpServerChannel sc = ((NginxJavaRequest)request).hijack(true); if ( !sc.webSocketUpgrade(false) ) { sc.send((String)null, true, false); sc.setIgnoreFilter(false); sc.sendHeader(200, ArrayMap.create("Content-Type", "text/html").entrySet(), false, false); } return null; } } public static class SharedMapBasedCounter implements NginxJavaRingHandler { NginxSharedHashMap<String, Integer> counters; public SharedMapBasedCounter() { counters = NginxSharedHashMap.build("mycounters"); //initialized to 0 counters.putInt("SharedMapBasedCounter", 0); } @Override public Object[] invoke(Map<String, Object> request) throws IOException { int oldc = counters.atomicAddInt("SharedMapBasedCounter", 1); return new Object[]{200, null, "visted " + (oldc+1) + " times"}; } } public static class SimpleRouting implements NginxJavaRingHandler { Map<String, NginxJavaRingHandler> handlers = new HashMap<String, NginxJavaRingHandler>(); public SimpleRouting() { handlers.put("/hello", new HelloHandler()); handlers.put("/websocket-echo", new WebSocketFullFunctionEcho()); handlers.put("/websocket-whecho", new WebSocketWholeMessageEcho()); handlers.put("/websocketmixed", new WebSocketMixedWithLongPoolingHandler()); handlers.put("/closewait", new CloseWaitIssue()); handlers.put("/visitcounter", new SharedMapBasedCounter()); } @Override public Object[] invoke(Map<String, Object> request) throws IOException { return handlers.get(request.get("uri")).invoke(request); } } @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testStartAndStop() throws ParseException, ClientProtocolException, IOException { NginxEmbedServer server = NginxEmbedServer.getServer(); Map<String, String> opts = ArrayMap.create("port", "8081", "http-user-defined", "shared_map mycounters hashmap?space=32k&entries=400;"); server.start(SimpleRouting.class.getName(), opts); CloseableHttpClient httpclient = HttpClients.createDefault(); HttpGet httpget = new HttpGet("http://localhost:8081/hello"); String resp = EntityUtils.toString(httpclient.execute(httpget).getEntity()); Assert.assertEquals("Hello, Embeded Nginx!", resp); server.stop(); } public static void main(String[] args) { NginxEmbedServer server = NginxEmbedServer.getServer(); // server.setWorkDir("test/work-dir"); Map<String, String> opts = ArrayMap.create("port", "8084", "http-user-defined", "shared_map mycounters hashmap?space=32k&entries=400;"); int port = server.start(SimpleRouting.class.getName(), opts); System.out.println("return port :" + port); try { System.in.read(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } server.stop(); port = server.start(SimpleRouting.class.getName(), opts); System.out.println("return port :" + port); } }