lib/nitro/adapter/webrick.rb in nitro-0.29.0 vs lib/nitro/adapter/webrick.rb in nitro-0.30.0

- old
+ new

@@ -30,10 +30,11 @@ else wblog = STDERR end webrick_options = server.options.dup + require 'webrick/https' if webrick_options[:SSLEnable] webrick_options.update( :BindAddress => server.address, :Port => server.port, @@ -41,10 +42,14 @@ :AccessLog => [ [wblog, WEBrick::AccessLog::COMMON_LOG_FORMAT], [wblog, WEBrick::AccessLog::REFERER_LOG_FORMAT] ] ) + + enable_record_mode($record_session_filename) if $record_session_filename + enable_playback_mode($playback_session_filename) if $playback_session_filename + @webrick = WEBrick::HTTPServer.new(webrick_options) trap('INT') { stop } @webrick.mount('/', WebrickAdapter, server) @@ -63,11 +68,80 @@ # Override this method to perform customized webrick # initialization. def initialize_webrick(server) end + + # Enables session recording. The recorded data can be used + # for automatic app testing by means of the playback mode. + def enable_record_mode(filename = 'session.yaml') + Logger.info "Recording application server session to '#{filename}'." + + require 'facets/core/file/self/create' + + $record_session = [] + $last_record_time = Time.now + + Nitro::WebrickAdapter.class_eval %{ + def do_GET(req, res) + record_context(req, res) + handle(req, res) + end + alias_method :do_POST, :do_GET + + def record_context(req, res) + delta = Time.now - $last_record_time + $last_record_time = Time.now + $record_session << [delta, req, res] + end + } + + at_exit do + File.create(filename, YAML.dump($record_session)) + end + end + + # Playback a recorded session. Typically used for testing. + + def enable_playback_mode(filename = 'session.yaml') + Logger.info "Playing back application server session from '#{filename}'." + + $playback_session = YAML.load_file(filename) + $playback_exception_count = 0 + + WEBrick::HTTPServer.class_eval %{ + def start(&block) + run(nil) + end + + def run(sock) + while true + delta, req, res = $playback_session.shift + + if delta + sleep(delta) + begin + service(req, res) + rescue Object => ex + $playback_exception_count += 1 + p '---', ex + end + else + return + end + end + end + } + + at_exit do + puts "\n\n" + puts "Playback raised #$playback_exception_count exceptions.\n" + puts "\n" + end + end + end end # A special handler for Xhtml files. @@ -125,42 +199,40 @@ def handle(req, res) unless handle_file(req, res) path = req.request_uri.path - unless path =~ /\./ - begin - path = req.request_uri.path + begin + path = req.request_uri.path - context = Context.new(@server) + context = Context.new(@server) - context.in = StringIO.new(req.body || "") + 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) + context.headers = {} + req.header.each { |h, v| context.headers[h.upcase] = v.first } + context.headers.update(req.meta_vars) - # gmosx: make compatible with fastcgi. + # gmosx: make compatible with fastcgi. - context.headers['REQUEST_URI'].slice!(/http:\/\/(.*?)\//) - context.headers['REQUEST_URI'] = '/' + context.headers['REQUEST_URI'] + context.headers['REQUEST_URI'].slice!(/http:\/\/(.*?)\//) + context.headers['REQUEST_URI'] = '/' + context.headers['REQUEST_URI'] - Cgi.parse_params(context) - Cgi.parse_cookies(context) + Cgi.parse_params(context) + Cgi.parse_cookies(context) - context.render(path) + 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 - res.chunked = true if context.out.is_a?(IO) and context["SERVER_PROTOCOL"] == "HTTP/1.1" + res.status = context.status + res.instance_variable_set(:@header, context.response_headers || {}) + res.instance_variable_set(:@cookies, context.response_cookies || {}) + res.body = context.out + res.chunked = true if context.out.is_a?(IO) and context["SERVER_PROTOCOL"] == "HTTP/1.1" - context.close - ensure - $autoreload_dirty = false - Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager) - end + context.close + ensure + $autoreload_dirty = false + Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager) and Og.manager end end end alias do_GET handle