root/lib/vintage/handler.rb

Revision 4, 4.1 kB (checked in by jeremymcanal..@gmail.com, 9 months ago)

Added support for Thin, evented Mongrel, and Swiftiply.
Added cookies.

Line 
1 require 'rubygems'
2 require 'mongrel'
3 require 'erubis'
4 require 'erb'
5
6 require 'mime/types'
7
8 require 'vintage/renderer'
9 require 'vintage/request_context'
10 require 'vintage/errors'
11
12 module Vintage
13   # The Mongrel HTTP Handler.  Handles all operations with requests.
14   class Handler   
15     def initialize(options)
16       # Make our configuration options avialable to the handler
17       @options = options
18      
19       # Setup a DirHandler for sending static files securely
20       @static_handler = Rack::File.new(@options[:static_path])
21      
22       # Inject our helpers in the RequestContext class to make them
23       # available on each request.
24       include_helpers
25     end
26  
27     # Main request handler for Mongrel.
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
33       # Setup our request's path
34       @request_path = request.path_info
35    
36       # Initialize the buffered log entry
37       log_entry = ""
38       log_entry << "*** request for [#{request.url}] from [#{env['REMOTE_ADDR']}]\n"
39
40       # If it's a root request, we want to render the template we configured
41       @request_path = @options[:root] if @request_path == '/'
42      
43       # If it's a static file we don't need to append a file extension
44       filename = (@request_path =~ /\.(.*)$/) ? "#{@options[:static_path]}/#{@request_path}" : "#{@options[:path]}/#{@request_path}.#{@options[:templates]}"
45      
46       # Does the file exist...?
47       if File.exists?(filename)
48         # It's found!  Let's add to our log entry...
49         log_entry << "    response: [200]\n"
50         log_entry << "    rendering [#{@request_path}]\n"
51
52         # Is it a static file?
53         if (@request_path =~ /\.(.*)$/)
54           # Yes?  Let our static handler take it away!
55           @static_handler.call(env)
56         else
57           # No!  Render a template...
58           content = Renderer.send(@options[:templates].to_sym, File.open("#{@options[:path]}#{@request_path}.#{@options[:templates]}", "r").read, context)
59        
60           # Set the content type if we're responding with a render
61           context.response.headers["Content-Type"] = "text/html" if context.response.code == 200
62           response = Rack::Response.new(content, context.response.code, {}.merge!(context.response.headers))
63        
64           # Render (if response is 200) or redirect
65           # Set cookies       
66           if context.response.cookies != {}
67             context.response.cookies.each do |key, value|
68               response.set_cookie(key, value)
69             end
70           end
71          
72           response.finish
73         end
74       else
75         # Page not found
76         # Log the 404
77         log_entry << "    response: [404]\n"
78         log_entry << "    rendering 'page not found'\n"
79        
80         # Send back the default or a custom template
81         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)
82         [context.response.code, {}.merge!(context.response.headers), content]
83       end
84     rescue StandardError => err
85       # OOPS!  Something broke.
86       context.response.code = 500
87
88       # Log it and send an error page...
89       log_entry << "\t!!! [500] #{err}\n"
90       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)
91       [context.response.code, {}.merge!(context.response.headers), content]
92     ensure
93       # After every request push the buffered log entry out to the logger
94       Log.enter log_entry.to_s + "\n"
95     end
96    
97     # Inject the default helpers and helpers from the
98     # +helpers/+ directory (if available) into the
99     # RequestContext class.
100     def include_helpers
101       RequestContext.send(:include, Vintage::Helpers)
102     end
103   end
104 end
Note: See TracBrowser for help on using the browser.