require 'stringio' require 'mongrel' require 'mongrel/handlers' require 'nitro/cgi' require 'nitro/context' require 'nitro/dispatcher' # Speeds things up, more comaptible with OSX. Socket.do_not_reverse_lookup = true #-- # Fix for Nitro. #++ module Mongrel # :nodoc: all class HttpRequest def method_missing(name, *args) if @params.has_key?(name.to_s.upcase) return @params[name.to_s.upcase] elsif name.to_s =~ /\A(.*)=\Z/ && @params.has_key?($1.upcase) @params[$1.upcase] = args[0] else super end end end end module Nitro class Mongrel class << self attr_accessor :mongrel # Start the Webrick adapter. def start(server) # TODO add logging. mongrel_options = server.options.dup mongrel_options.update( :BindAddress => server.address, :Port => server.port, :DocumentRoot => server.public_root ) @mongrel = ::Mongrel::HttpServer.new(mongrel_options[:BindAddress], mongrel_options[:Port]) trap('INT') { exit } # works until you use breakpoint... why? @mongrel.register('/', MongrelAdapter.new(server)) initialize_mongrel(server) @mongrel.run @mongrel_thread = @mongrel.acceptor @mongrel_thread.join end # Stop the Mongrel adapter. def stop @mongrel_thread.kill end # Override this method to perform customized mongrel # initialization. def initialize_mongrel(server) end end end # A Mongrel Adapter for Nitro. class MongrelAdapter < ::Mongrel::HttpHandler attr_accessor :server def initialize(server) @server = server end def process(req, res) handle(req, res) end # Handle a static file. Also handles cached pages. def handle_file(req, res) begin rewrite(req) # TODO handle If-Modified-Since and add Last-Modified headers filename = [@server.public_root, req.path_info].join("/").gsub(%r[//], '/') File.open(filename, "rb") { |f| # TODO check whether path circumvents public_root directory? res.status = 200 res.body << f.read # XXX inefficient for large files, may cause leaks } return true rescue Object => ex return false ensure unrewrite(req) end end # Handle the request. def handle(req, res) unless handle_file(req, res) path = req.path_info begin context = Context.new(@server) context.in = if req.body.is_a? String StringIO.new(req.body) else req.body end context.headers = {} req.params.each { |h, v| if h =~ /\AHTTP_(.*)\Z/ context.headers[$1.gsub("_", "-")] = v end context.headers[h] = v } Cgi.parse_params(context) Cgi.parse_cookies(context) context.render(path) res.status = context.status res.header.out << Cgi.response_headers(context) res.body << context.out context.close ensure Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager) and Og.manager end end end def rewrite(req) if req.path_info == '/' || req.path_info == '' req.path_info = '/index.html' elsif req.path_info =~ /^([^.]+)$/ req.path_info = "#{$1}/index.html" end end # Rewrite back to the original path. def unrewrite(req) if req.path_info == '/index.html' req.path_info = '/' elsif req.path_info =~ /^([^.]+)\/index.html$/ req.path_info = $1 end end end end # * Joshua Hoke # * George Moschovitis