Created
October 21, 2013 20:07
Revisions
-
itzg created this gist
Oct 21, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,103 @@ import org.jboss.netty.bootstrap.ServerBootstrap import org.jboss.netty.buffer.ChannelBuffers import org.jboss.netty.channel.ChannelHandlerContext import org.jboss.netty.channel.ChannelPipeline import org.jboss.netty.channel.ChannelPipelineFactory import org.jboss.netty.channel.Channels import org.jboss.netty.channel.MessageEvent import org.jboss.netty.channel.SimpleChannelUpstreamHandler import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory import org.jboss.netty.handler.codec.http.DefaultHttpResponse import org.jboss.netty.handler.codec.http.HttpHeaders import org.jboss.netty.handler.codec.http.HttpMethod import org.jboss.netty.handler.codec.http.HttpRequest import org.jboss.netty.handler.codec.http.HttpResponse import org.jboss.netty.handler.codec.http.HttpResponseStatus import org.jboss.netty.handler.codec.http.HttpServerCodec import org.jboss.netty.handler.codec.http.HttpVersion import org.slf4j.Logger import org.slf4j.LoggerFactory class SmallServer { protected static Logger logger = LoggerFactory.getLogger(SmallServer) protected final routes = [ '/content.json': { req -> '{"field":"value"}' }, '/': { """<body> Success. Here's <a href='/missing'>a link to missing content</a> </body> """ } ] protected static HttpResponse createBadResponse(HttpResponseStatus status) { def response = new DefaultHttpResponse(HttpVersion.HTTP_1_0, status) response.addHeader(HttpHeaders.Names.CONTENT_LENGTH, 0) return response } int startServer() { final def us = this ServerBootstrap serverBootstrap = new ServerBootstrap(new NioServerSocketChannelFactory()) serverBootstrap.pipelineFactory = new ChannelPipelineFactory() { ChannelPipeline getPipeline() throws Exception { Channels.pipeline(new HttpServerCodec(), new SimpleChannelUpstreamHandler() { void messageReceived(ChannelHandlerContext ctx, MessageEvent evt) throws Exception { if (evt.message instanceof HttpRequest && evt.message.method == HttpMethod.GET) { HttpRequest req = evt.message def routeHandlerEntry = us.routes.find { it.key.isCase(req.uri) } if (routeHandlerEntry) { SmallServer.logger.info("Routing ${req.uri}") def response = new DefaultHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.OK) try { def stringContent = routeHandlerEntry.value.call(req) def content = ChannelBuffers.copiedBuffer(stringContent, Charset.forName('UTF-8')) response.content = content response.addHeader(HttpHeaders.Names.CONTENT_LENGTH, content.readableBytes()) if (stringContent[0] in ['<']) { response.addHeader(HttpHeaders.Names.CONTENT_TYPE, 'text/html') } else if (stringContent[0] in ['[','{']) { response.addHeader(HttpHeaders.Names.CONTENT_TYPE, 'application/json') } evt.channel.write(response) } catch (Exception e) { SmallServer.logger.error("Handler ${req.uri} failed", e) evt.channel.write(createBadResponse(HttpResponseStatus.INTERNAL_SERVER_ERROR)) } } else { SmallServer.logger.warn("Not found: ${req.uri}") evt.channel.write(createBadResponse(HttpResponseStatus.NOT_FOUND)) } } else { SmallServer.logger.warn("Bad request: ${req}") evt.channel.write(createBadResponse(HttpResponseStatus.BAD_REQUEST)) } } }) } } def serverPort = serverBootstrap.bind(new InetSocketAddress(0)).localAddress.port println "Server is ready at http://localhost:${serverPort}" } }