require 'webrick' require 'stringio' require 'glue/flexob' require 'nitro/context' require 'nitro/dispatcher' # Speeds things up, more comaptible with OSX. Socket.do_not_reverse_lookup = true module Nitro # Helper methods for the WebrickAdapter. class Webrick class << self attr_accessor :server def start(conf) conf = Conf.new(conf) unless conf.is_a?(Conf) if RUBY_PLATFORM !~ /mswin32/ accesslog = WEBrick::BasicLog::new('/dev/null') refererlog = WEBrick::BasicLog::new('/dev/null') elsif (conf.accesslog || conf.refererlog) accesslog = WEBrick::BasicLog::new(conf.accesslog || 'log/access.log') refererlog = WEBrick::BasicLog::new(conf.refererlog || 'log/referer.log') else accesslog = STDERR refererlog = STDERR end @server = WEBrick::HTTPServer.new( :BindAddress => conf.host, :Port => conf.port, :DocumentRoot => conf.dispatcher.public_root, :AccessLog => [ [accesslog, WEBrick::AccessLog::COMMON_LOG_FORMAT], [refererlog, WEBrick::AccessLog::REFERER_LOG_FORMAT] ] ) trap('INT') { @server.shutdown } @server.mount('/', WebrickAdapter, conf) @server.start end end end # A special handler for Xhtml files. class XhtmlFileHandler < WEBrick::HTTPServlet::DefaultFileHandler def do_GET(req, res) res['content-type'] = 'text/html' res.body = 'Permission denied' end end # A Webrick Adapter for Nitro. #-- # TODO: optimize the conversion from WEBrick's # parameters to the Nitro parameters. #++ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet include WEBrick # REQUEST_MUTEX = Mutex.new def initialize(server, conf) @conf = conf @conf.webrick_options ||= {} @conf.webrick_options[:HandlerTable] = { 'xhtml' => XhtmlFileHandler } # Handles static resources. Useful when running # a stand-alone webrick server. @file_handler = WEBrick::HTTPServlet::FileHandler.new(server, conf.dispatcher.public_root, @conf.webrick_options) end # Handle a static file. Also handles cached pages. def handle_file(req, res) begin rewrite(req) @file_handler.do_GET(req, res) return true rescue WEBrick::HTTPStatus::PartialContent, WEBrick::HTTPStatus::NotModified => err res.set_error(err) return true rescue return false ensure unrewrite(req) end end # Handle the request. def handle(req, res) unless handle_file(req, res) path = req.request_uri.path unless path =~ /\./ begin path = req.request_uri.path # REQUEST_MUTEX.lock context = Context.new(@conf) context.in = StringIO.new(req.body || "") context.headers = {} req.header.each { |h, v| context.headers[h.upcase] = v.first } context.headers.update(req.meta_vars) # gmosx: make compatible with fastcgi. context.headers['REQUEST_URI'].slice!(/http:\/\/(.*?)\//) context.headers['REQUEST_URI'] << '/' CgiUtils.parse_params(context) CgiUtils.parse_cookies(context) context.render(path) res.status = context.status res.instance_variable_set(:@header, context.response_headers || {}) res.instance_variable_set(:@cookies, context.response_cookies || {}) res.body = context.out context.close ensure # REQUEST_MUTEX.unlock if REQUEST_MUTEX.locked? Og.manager.put_store if defined?(Og) and Og.manager end end end end alias do_GET handle alias do_POST handle # Try to rewrite the path to a filename. def rewrite(req) if req.path == '/' req.instance_variable_set(:@path_info, '/index.html') elsif req.path =~ /^([^.]+)$/ req.instance_variable_set(:@path_info, "#{$1}/index.html") end end # Rewrite back to the original path. def unrewrite(req) if req.path == '/' req.instance_variable_set(:@path_info, '/') elsif req.path =~ /^([^.]+).html$/ req.instance_variable_set(:@path_info, $1) end end end end # * George Moschovitis