Changeset 2

Show
Ignore:
Timestamp:
01/05/08 13:34:30 (7 months ago)
Author:
jeremymcanal..@gmail.com
Message:

Ported to Rack. Hoorah!

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • bin/vintage

    r1 r2  
    2020  :templates    => 'erb', 
    2121  :mount        => '/', 
    22   :root         => 'index' 
     22  :root         => 'index', 
     23  :server       => 'mongrel' 
    2324} 
    2425MANDATORY_OPTIONS = %w(  ) 
     
    5758          "The template to render at the root URL", 
    5859          "Default: index") { |OPTIONS[:root]| } 
     60  opts.on("-s", "--server=server", String, 
     61          "The server daemon to use (can be mongrel, webrick, cgi, or fastcgi)", 
     62          "Default: mongrel") { |OPTIONS[:server]| } 
    5963  opts.on("-h", "--help", 
    6064          "Show this help message.") { puts opts; exit } 
  • lib/vintage/handler.rb

    r1 r2  
    33require 'erubis' 
    44require 'erb' 
     5 
    56require 'mime/types' 
    67 
     
    1112module Vintage 
    1213  # The Mongrel HTTP Handler.  Handles all operations with requests. 
    13   class Handler < Mongrel::HttpHandler     
     14  class Handler    
    1415    def initialize(options) 
    1516      # Make our configuration options avialable to the handler 
     
    1718       
    1819      # Setup a DirHandler for sending static files securely 
    19       @static_handler = Mongrel::DirHandler.new(@options[:static_path], false, nil
     20      @static_handler = Rack::File.new(@options[:static_path]
    2021       
    2122      # Inject our helpers in the RequestContext class to make them 
     
    2526   
    2627    # Main request handler for Mongrel. 
    27     def process(request, response) 
    28       # Parse params into a nice Hash 
    29       handle_params(request.params["QUERY_STRING"]) 
    30        
     28    def call(env) 
     29      # Setup up the request's context (response and request information) 
     30      request = Rack::Request.new(env) 
     31      context = RequestContext.new(request) 
     32 
    3133      # Setup our request's path 
    32       @request_path = request.params["PATH_INFO"] 
    33        
    34       # Setup up the request's context (response and request information) 
    35       context = RequestContext.new(request, @params, {}) 
    36        
     34      @request_path = request.path_info 
     35     
    3736      # Initialize the buffered log entry 
    3837      log_entry = "" 
    39       log_entry << "*** request for [#{request.params['REQUEST_URI']}] from [#{request.params['REMOTE_ADDR']}]\n" 
     38      log_entry << "*** request for [#{request.url}] from [#{env['REMOTE_ADDR']}]\n" 
    4039 
    4140      # If it's a root request, we want to render the template we configured 
     
    5453        if (@request_path =~ /\.(.*)$/) 
    5554          # Yes?  Let our static handler take it away! 
    56           @static_handler.process(request, response
     55          @static_handler.call(env
    5756        else 
    5857          # No!  Render a template... 
    5958          content = Renderer.send(@options[:templates].to_sym, File.open("#{@options[:path]}#{@request_path}.#{@options[:templates]}", "r").read, context) 
    60         end 
    6159         
    62         # Render (if response is 200) or redirect 
    63         response.start(context.response.code) do |head, out| 
    64           # Add any custom headers (e.g., from redirect_to) 
    65           context.response.headers.each do |k,v| 
    66             head[k] = v 
    67           end 
    68            
     60          # Render (if response is 200) or redirect           
    6961          # Set the content type if we're responding with a render 
    70           head["Content-Type"] = "text/html" if context.response.code == 200 
    71            
    72           # Write out to the response 
    73           out.write content 
     62          context.response.headers["Content-Type"] = "text/html" if context.response.code == 200 
     63          [context.response.code, {}.merge!(context.response.headers), content] 
    7464        end 
    7565      else 
    7666        # Page not found 
    77         response.start(404) do |head, out| 
    78           # Log the 404 
    79           log_entry << "    response: [404]\n" 
    80           log_entry << "    rendering 'page not found'\n" 
    81            
    82           # Send back the default or a custom template 
    83           head["Content-Type"] = "text/html" 
    84           out.write @options[:errors] && @options[:errors][:not_found] ? Renderer.send(@options[:templates].to_sym, File.open("#{@options[:path]}#{@options[:errors][:not_found]}.#{@options[:templates]}", "r").read, context) : ErrorReporter.not_found(@request_path, request.params['REMOTE_ADDR'], @params) 
    85         end 
     67        # Log the 404 
     68        log_entry << "    response: [404]\n" 
     69        log_entry << "    rendering 'page not found'\n" 
     70         
     71        # Send back the default or a custom template 
     72        content = @options[:errors] && @options[:errors][:not_found] ? Renderer.send(@options[:templates].to_sym, File.open("#{@options[:path]}#{@options[:errors][:not_found]}.#{@options[:templates]}", "r").read, context) : ErrorReporter.not_found(@request_path, request.params['REMOTE_ADDR'], @params) 
     73        [context.response.code, {}.merge!(context.response.headers), content] 
    8674      end 
    8775    rescue StandardError => err 
    8876      # OOPS!  Something broke. 
    89       response.start(500) do |head, out| 
    90         # Log it and send an error page... 
    91         log_entry << "\t!!! [500] #{err}\n" 
    92         head["Content-Type"] = "text/html
    93         out.write @options[:errors] && @options[:errors][:internal_error] ? Renderer.send(@options[:templates].to_sym, File.open("#{@options[:path]}#{@options[:errors][:internal_error]}.#{@options[:templates]}", "r").read, context) : ErrorReporter.internal_error(err, @params) 
    94       end 
     77      context.response.code = 500 
     78 
     79      # Log it and send an error page... 
     80      log_entry << "\t!!! [500] #{err}\n
     81      content = @options[:errors] && @options[:errors][:internal_error] ? Renderer.send(@options[:templates].to_sym, File.open("#{@options[:path]}#{@options[:errors][:internal_error]}.#{@options[:templates]}", "r").read, context) : ErrorReporter.internal_error(err, @params) 
     82      [context.response.code, {}.merge!(context.response.headers), content] 
    9583    ensure 
    9684      # After every request push the buffered log entry out to the logger 
    9785      Log.enter log_entry.to_s + "\n" 
    98     end 
    99      
    100     # Parse HTTP params into a +Hash+. 
    101     def handle_params(params) 
    102       @params = {} 
    103        
    104       unless params == nil || params == '' 
    105         # Split the query string and hack it up 
    106         params.split('&').each do |param| 
    107           key, val = param.split('=') 
    108  
    109           @params[key.to_sym] = val 
    110         end 
    111       end 
    11286    end 
    11387     
  • lib/vintage/request_context.rb

    r1 r2  
    1 # Class that encapsulates information about the request. 
    2 class Request 
    3   attr_accessor :remote_ip, :method, :params, :query_string, :uri, :referer, :user_agent 
     1require 'rack' 
     2require 'rack/file' 
     3 
     4module Vintage 
     5  # Class that encapsulates the response's headers and 
     6  # response code. 
     7  class Response 
     8    attr_accessor :headers, :code 
    49   
    5   def initialize(request, param_hash) 
    6     self.remote_ip = request.params['REMOTE_ADDR'] 
    7     self.referer = request.params['HTTP_REFERER'] 
    8     self.uri = request.params['REQUEST_URI'] 
    9     self.method = request.params['REQUEST_METHOD'] 
    10     self.user_agent = request.params['HTTP_USER_AGENT'] 
    11     self.query_string = request.params['QUERY_STRING'] 
    12     self.params = param_hash 
     10    def initialize 
     11      self.headers = {} 
     12      self.code = 200 
     13    end 
     14  end 
     15 
     16  # A class that creates a context for template 
     17  # rendering.  Helpers are mixed in here to give 
     18  # templates access to them. 
     19  class RequestContext 
     20    attr_accessor :request, :response 
     21   
     22    def initialize(incoming_request) 
     23      self.request = incoming_request 
     24      self.response = Vintage::Response.new 
     25    end 
    1326  end 
    1427end 
    1528 
    16 # Class that encapsulates the response's headers and 
    17 # response code. 
    18 class Response 
    19   attr_accessor :headers, :code 
    20    
    21   def initialize(headers) 
    22     self.headers = headers 
    23     self.code = 200 
     29module Rack 
     30  class Request 
     31    def remote_ip 
     32      @env['REMOTE_ADDR'] 
     33    end 
     34     
     35    def user_agent 
     36      @env['HTTP_USER_AGENT'] 
     37    end 
    2438  end 
    2539end 
    26  
    27 # A class that creates a context for template 
    28 # rendering.  Helpers are mixed in here to give 
    29 # templates access to them. 
    30 class RequestContext 
    31   attr_accessor :request, :response 
    32    
    33   def initialize(incoming_request, params, headers) 
    34     self.request = Request.new(incoming_request, params) 
    35     self.response = Response.new(headers) 
    36   end 
    37 end 
  • lib/vintage/server.rb

    r1 r2  
    77require 'vintage/log' 
    88require 'vintage/helpers' 
     9 
     10require 'rack' 
     11require 'rack/file' 
    912 
    1013begin 
     
    2326      Log.enter "\t starting server on port #{options[:port]}" 
    2427      Log.enter 
     28 
     29      application = Handler.new(options) 
     30 
     31      server = Rack::Handler::Mongrel 
    2532       
    26       h = Mongrel::HttpServer.new("0.0.0.0", options[:port]) 
    27       h.register(options[:mount], Handler.new(options)) 
    28       h.run.join 
     33      case options[:server] 
     34      when "mongrel" 
     35        server = Rack::Handler::Mongrel 
     36      when "webrick" 
     37        server = Rack::Handler::WEBrick 
     38      when "cgi" 
     39        server = Rack::Handler::CGI 
     40      when "fastcgi" 
     41        server = Rack::Handler::FastCGI 
     42      end 
     43 
     44      server.run application, {:Port => options[:port], :Host => "0.0.0.0", :AccessLog => []} 
    2945    rescue Interrupt 
    3046      Log.enter 
  • requests.log

    r1 r2  
    77        shutting server down 
    88 
     9- vintage version 0.0.1 
     10         starting server on port 5000 
     11 
     12 
     13- interrupt signal caught 
     14        shutting server down 
     15