import org.jboss.netty.handler.codec.http.HttpRequestDecoder import org.jboss.netty.handler.codec.http.HttpResponseEncoder import org.jboss.netty.handler.codec.http.HttpContentCompressor import org.jboss.netty.channel.Channels import org.jboss.netty.channel.ChannelPipelineFactory import org.jboss.netty.buffer.ChannelBuffers import org.jboss.netty.handler.codec.http.DefaultHttpResponse import org.jboss.netty.handler.codec.http.HttpResponseStatus import org.jboss.netty.handler.codec.http.HttpVersion import org.jboss.netty.handler.codec.http.HttpHeaders require_relative 'server' module Foxbat class WebPipeline include ChannelPipelineFactory HANDLER = "handler" ENCODER = "encoder" DECODER = "decoder" DEFLATER = "deflater" def initialize(app) @app = app @handler = ReadTimeoutHandler.new(EM.timer, 10) end def getPipeline pipeline = Channels.pipeline pipeline.addLast(DECODER, HttpRequestDecoder.new) pipeline.addLast(ENCODER, HttpResponseEncoder.new) pipeline.addLast(DEFLATER, HttpContentCompressor.new) pipeline.addLast(HANDLER, WebHandler.new(@app)) pipeline end end class WebHandler < SimpleChannelUpstreamHandler def initialize(app) super() @app = app end def messageReceived(ctx, e) req = e.getMessage env = to_rack(req) val = @app.call(env) resp = to_netty(val) future = e.getChannel.write(resp) listener = Object.new def listener.operationComplete(f) f.getChannel.close end future.addListener(listener) end private def to_rack(req) env = {} env['REQUEST_METHOD'] = req.getMethod.toString req.getHeaders.each do |h| header = "HTTP_" + h.getKey.upcase.gsub("-", "_") env[header] = h.getValue end env end CODES = {200 => HttpResponseStatus::OK} def to_netty(resp) code, headers, content = resp netty_response = DefaultHttpResponse.new(HttpVersion::HTTP_1_1, CODES[code]) headers.each do |k,v| netty_response.setHeader(k, v) end content = content.to_java_bytes if content.is_a?(String) buf = ChannelBuffers.copiedBuffer(content) netty_response.setContent(buf) netty_response.setHeader('Content-Length', buf.writerIndex) netty_response.setHeader('Server', 'Foxbat') netty_response end end class HttpServer < Server def initialize(host, port, klass, options, &block) super(host, port, klass, options, &block) @pipeline.releaseExternalResources @pipeline = WebPipeline.new(block) end end end