# code: # * George Moschovitis # * Elias Athanasopoulos # # (c) 2004 Navel, all rights reserved. # $Id: webrick.rb 118 2004-11-01 10:13:42Z gmosx $ require "drb" require "cgi" require "singleton" require "webrick" require "n/logger" require "n/application" require "n/utils/cache" require "n/server/request" require "n/server/request" require "n/server/handlers" require "n/server/session" require "n/server/appserver" # Override WEBrick to suit our needs. # module WEBrick class HTTPRequest alias_method :old_parse_uri, :parse_uri def parse_uri(str, scheme="http") old_parse_uri(__rewrite(str.dup), scheme) end # gmosx, FIXME: temp hack! # def __rewrite(uri) # FIXME: scan for first ONLY. realm = uri.scan(/^\/(.*?)\//) realm = realm[0][0] unless realm.empty? if rules = $rewrites[realm] for rule in rules return uri if uri.gsub!(rule[0], rule[1]) end end return uri end end # Expose some response variables. # class HTTPResponse attr_writer :header attr_writer :cookies end end module N # = Webrick AppServer # # The Application Server. Handles dynamic requests in a web application. # Dont keepalive (or use a VERY SMALL keepalive). Typically this server # is used along with a standard http server that handles other resources. # # Used temporarily unitl we build our own app server. # class Webrick < N::AppServer include WEBrick # the integrated webrock server. attr_accessor :webrick def initialize(name = "WebrickServer") super end # Start the application server. # def start accesslog = WEBrick::BasicLog::new("/dev/null") referer = WEBrick::BasicLog::new("/dev/null") @webrick = HTTPServer.new( :BindAddress => $appsrv_address, :Port => $appsrv_port, :DocumentRoot => $root_dir, # gmosx, FIXME: this shit still logs!! :Logger => Log.new(nil, WEBrick::Log::WARN), # elathan: amateur... :AccessLog => [ [accesslog, AccessLog::COMMON_LOG_FORMAT], [referer, AccessLog::REFERER_LOG_FORMAT] ] ) @webrick.mount("/", N::WebrickServlet) trap("INT") { @webrick.shutdown() } @webrick.start() end # Stop the application server. # def stop @webrick.stop end end # = WebrickServlet # # A webrick servlet that implements the Nitro Engine. # # TODO: Lots of stuff should be factored out! # class WebrickServlet < WEBrick::HTTPServlet::AbstractServlet include WEBrick # Handle a HTTP GET request. # def do_GET(wreq, wres) request = create_request(wreq) request.session = create_session(request) extension = N::StringUtils.extension_from_path(request.path) if handler = $srv_extension_map[extension] handler = handler[1] else $log.error "Cannot handle '#{request.path}'" return nil end begin $og.get_connection if $og fragment, script = handler.process(request) if fragment request.out["Content-Type"] = "text/html" unless request.out["Content-Type"] request.out_buffer = fragment.body end unless request.expires? request.expires!(Time.now()) end rescue Exception, StandardError => e $log.error "error while handling the request #{request.uri}" $log.error pp_exception(e) if $error_page_url # internal redirect to error page. # gmosx: reset handler for .rx pages. handler = $srv_extension_map["sx"][1] request.path = $error_page_url retry else # no custom error page defined. Presen a simple yet # useful error screen. request.out["Content-Type"] = "text/html" body = %{

ERROR

Click here to return to the previous page.

} if request.error_log body << %{

Request error log

#{request.error_log.join("\n")}
} end body << %{

Exception

#{pp_exception(e)}
} request.out_buffer = body end ensure $og.put_connection if $og end # gmosx: optimize me, do something more clever!!! request.session.synchronize! wres.status = request.status wres.header = request.out wres.cookies = request.out_cookies.values() wres.body = request.out_buffer end alias :do_POST :do_GET #------------------------------------------------------------------------------- private # Convert a webrick request to an engine request # FIXME: this is UNOPTIMIZED code! # def create_request(wreq) # FIXME: use a resource pool! request = N::Request.new request.uri = wreq.unparsed_uri request.translated_uri = wreq.path_info request.path = wreq.path # enforce filename if missing, FIXME: improve this. request.path << $index_filename if request.path[-1] == ?/ # request.path_info = wreq.path_info request.query_string = wreq.query_string request.method = wreq.request_method # gmosx: X-FORWARDED-FOR is used in a proxy configuration. request.remote_addr = wreq["X-FORWARDED-FOR"] || wreq["REMOTE_ADDR"] # gmosx: remove this ?? request.in = {} wreq.header.each { |k, v| # gmosx: upcase to make compatible with n2 codebase. request.in[k.upcase] = v[0] } request.parts = {} request.parameters = {} wreq.query.each { |k, v| if v.filename request.parts[k] = N::RequestPart.new(v.filename, v) else request.parameters[k] = v end } request.in_cookies = {} wreq.cookies.each { |c| request.in_cookies[c.name] = c } # gmosx: is this STILL needed?? # # INVESTIGATE, FIXME: this is a hack! # apache prepends $srv_url and fucks up msie. # FIXME: add unit test for this! if ref = request.in["REFERER"] split_re = Regexp.new($srv_url) unless split_re xref = ref.split(split_re).last if N::StringUtils.valid?(xref) request.in["REFERER"] = xref end end return request end # Create session # def create_session(request) session = nil session_id = nil # gmosx: i have to fix the get_cookie method to return a # full cookie object. if session_id = request.get_cookie(N::Session::COOKIE_NAME) session = $sessions[session_id] $log.debug "Stale session cookie: #{session_id}" unless session # FIXME: remove cookie if stale! else session_id = N::Session.calculate_id() cookie = N::Cookie.new(N::Session::COOKIE_NAME, session_id) request.out_cookies[N::Session::COOKIE_NAME] = cookie end # session not found and must be created unless session session = N::Session.new(session_id) end return session end end end # module