vintage 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-01-01
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Jeremy McAnally
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,33 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/vintage
7
+ config/hoe.rb
8
+ config/requirements.rb
9
+ lib/vintage.rb
10
+ lib/vintage/version.rb
11
+ lib/vintage/errors.rb
12
+ lib/vintage/handler.rb
13
+ lib/vintage/helpers.rb
14
+ lib/vintage/log.rb
15
+ lib/vintage/renderer.rb
16
+ lib/vintage/request_context.rb
17
+ lib/vintage/server.rb
18
+ log/debug.log
19
+ script/destroy
20
+ script/generate
21
+ setup.rb
22
+ tasks/deployment.rake
23
+ tasks/environment.rake
24
+ tasks/website.rake
25
+ test/test_helper.rb
26
+ test/test_vintage.rb
27
+ app_generators/vintage_application/USAGE
28
+ app_generators/vintage_application/vintage_application_generator.rb
29
+ app_generators/vintage_application/templates/configuration.yml
30
+ app_generators/vintage_application/templates/index.erb
31
+ app_generators/vintage_application/templates/README
32
+ app_generators/vintage_application/templates/style.css
33
+ app_generators/vintage_application/templates/vintage.png
data/README.txt ADDED
@@ -0,0 +1,40 @@
1
+ = Vintage - The super slim, microwebframework of doom!
2
+
3
+ Vintage is a very small web framework based on the original idea of Merb: Mongrel serving up
4
+ ERb (Embedded Ruby) templates. The idea has been expanded and now Vintage helps you serve up
5
+ ERb, HAML, Textile, Markdown, and Markaby templates.
6
+
7
+ == Basic Usage
8
+
9
+ To use Vintage, you have two options. You can use it in standard mode or application mode. In
10
+ standard mode, there is no configuration and Vintage will serve up templates and static files
11
+ from the current folder. To get this mode, then simply type <tt>vintage start</tt> in any folder.
12
+
13
+ $ vintage start
14
+ - vintage version 0.0.1
15
+ starting server on port 5000
16
+
17
+ Now navigating to a URL will look in the current folder for the file or template. For example, going
18
+ to <tt>http://localhost:5000/my_template</tt> will look for <tt>my_template.erb</tt> (or whatever template
19
+ engine you are using) in the current folder and render it if available. If a static file is requested, then
20
+ it is served up. If you request <tt>http://localhost:5000/my_folder/my_template</tt>, then the application
21
+ will look in <tt>my_folder</tt> for the <tt>my_template</tt> template.
22
+
23
+ === Vintage as an application server
24
+
25
+ Vintage can also be configured to be used as an application server. To do so, you can either generate an
26
+ application or hand create a <tt>configuration.yml</tt> file (see one from a generated project for an example).
27
+ To generate an application, simple run +vintage+ with a project name as the argument.
28
+
29
+ vintage my_project
30
+
31
+ This command will generate a number of files. Chief among these is <tt>configuration.yml</tt> which tells
32
+ Vintage how you'd like to run it. Other files include a sample template and the proper folder structure
33
+ for the generated configuration to work properly. This setup allows you to more easily segment your code
34
+ for easier maintenance.
35
+
36
+ == Helpers
37
+
38
+ Vintage comes with a few helpers that live in Vintage::Helpers. You can add your own helpers by creating a
39
+ <tt>helpers</tt> folder and stashing modules in there. As of right now, helpers must live in the Vintage::Helpers
40
+ module, but this will hopefully be changing very soon.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
@@ -0,0 +1,5 @@
1
+ Description:
2
+
3
+
4
+ Usage:
5
+
@@ -0,0 +1,6 @@
1
+ Vintage - The super slim web framework for men and women
2
+ ========================================================
3
+
4
+ Vintage is a very small web framework based on the original idea of Merb: Mongrel serving up
5
+ ERb (Embedded Ruby) templates. The idea has been expanded and now Vintage helps you serve up
6
+ ERb, HAML, Textile, Markdown, and Markaby templates.
@@ -0,0 +1,17 @@
1
+ ---
2
+ # Path for static files
3
+ :static_path: static/
4
+ # Path for application templates
5
+ :path: app/
6
+ # Templating engine to use
7
+ :templates: erb
8
+ # Port to launch server on
9
+ :port: 5000
10
+ # Relative URL to mount application on
11
+ :mount: /
12
+ # Default template to render on root
13
+ :root: index
14
+ # You can also define error templates
15
+ # :errors:
16
+ # :not_found: not_found
17
+ # :internal_error: internal_error
@@ -0,0 +1,29 @@
1
+ <html>
2
+ <head>
3
+ <title>
4
+ Welcome to Vintage
5
+ </title>
6
+ <link rel="stylesheet" href="style.css" />
7
+ </head>
8
+ <body>
9
+ <img src="vintage.png" />
10
+ <h1>Welcome to Vintage</h1>
11
+ <p>
12
+ Come on in and relax. Actually, don't relax. Build something.
13
+ </p>
14
+ <div>
15
+ <h2>Request Information</h2>
16
+ <ul>
17
+ <li>Remote IP: <%= request.remote_ip %></li>
18
+ <li>Referer: <%= request.referer %></li>
19
+ <li>Requested URI: <%= request.uri %></li>
20
+ <li>Request method: <%= request.method %></li>
21
+ <li>User agent: <%= request.user_agent %></li>
22
+ <li>Query string: <%= request.query_string %></li>
23
+ <li>Parameters: <%= request.params == {} ? "None" : request.params.to_a.map{|k,v| "#{k} = #{v}"}.join(", ") %></li>
24
+ </ul>
25
+ </div>
26
+ <br />
27
+ <%= link_to "Vintage homepage", "http://vintage.rubyforge.org" %>
28
+ </body>
29
+ </html>
@@ -0,0 +1,8 @@
1
+ BODY { background: #3E2B09; text-align: center; font-family: sans-serif; }
2
+ h1 { color: white; }
3
+ p { color: #ccd69f; }
4
+ div { background: #ccd69f; color: black; width: 450px; padding: 10px; margin: auto; border: 2px solid #aab47d;}
5
+ div h2 { font-size: 14pt; color: #33400a; margin: 0px; }
6
+ div ul { list-style-type: none; }
7
+ div ul li { padding: 0px; margin: 8px 0px; text-align: left; }
8
+ A { color: white; }
@@ -0,0 +1,71 @@
1
+ class VintageApplicationGenerator < RubiGen::Base
2
+
3
+ DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
4
+ Config::CONFIG['ruby_install_name'])
5
+
6
+ default_options :author => nil
7
+
8
+ attr_reader :name
9
+
10
+ def initialize(runtime_args, runtime_options = {})
11
+ super
12
+ usage if args.empty?
13
+ @destination_root = File.expand_path(args.shift)
14
+ @name = base_name
15
+ extract_options
16
+ end
17
+
18
+ def manifest
19
+ record do |m|
20
+ # Ensure appropriate folder(s) exists
21
+ m.directory ''
22
+ BASEDIRS.each { |path| m.directory path }
23
+
24
+ m.file "configuration.yml", "configuration.yml"
25
+ m.file "README", "README"
26
+ m.file "index.erb", "app/index.erb"
27
+ m.file "vintage.png", "static/vintage.png"
28
+ m.file "style.css", "static/style.css"
29
+
30
+ # m.dependency "install_rubigen_scripts", [destination_root, 'vintage_application'],
31
+ # :shebang => options[:shebang], :collision => :force
32
+ end
33
+ end
34
+
35
+ protected
36
+ def banner
37
+ <<-EOS
38
+ Creates a ...
39
+
40
+ USAGE: #{spec.name} name"
41
+ EOS
42
+ end
43
+
44
+ def add_options!(opts)
45
+ opts.separator ''
46
+ opts.separator 'Options:'
47
+ # For each option below, place the default
48
+ # at the top of the file next to "default_options"
49
+ # opts.on("-a", "--author=\"Your Name\"", String,
50
+ # "Some comment about this option",
51
+ # "Default: none") { |options[:author]| }
52
+ opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
53
+ end
54
+
55
+ def extract_options
56
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
57
+ # Templates can access these value via the attr_reader-generated methods, but not the
58
+ # raw instance variable value.
59
+ # @author = options[:author]
60
+ end
61
+
62
+ # Installation skeleton. Intermediate directories are automatically
63
+ # created so don't sweat their absence here.
64
+ BASEDIRS = %w(
65
+ app
66
+ static
67
+ helpers
68
+ test
69
+ tmp
70
+ )
71
+ end
data/bin/vintage ADDED
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created by Jeremy McAnally on 2008-1-1.
4
+ # Copyright (c) 2008. All rights reserved.
5
+
6
+ $:.unshift File.dirname(__FILE__)
7
+ require File.dirname(__FILE__) + '/../lib/vintage'
8
+
9
+ require 'rubygems'
10
+ require 'optparse'
11
+ require 'rubigen'
12
+
13
+ # NOTE: the option -p/--path= is given as an example, and should probably be replaced in your application.
14
+
15
+ OPTIONS = {
16
+ :path => Dir.pwd,
17
+ :static_path => Dir.pwd,
18
+ :port => 5000,
19
+ :config => 'configuration.yml',
20
+ :templates => 'erb',
21
+ :mount => '/',
22
+ :root => 'index'
23
+ }
24
+ MANDATORY_OPTIONS = %w( )
25
+
26
+ parser = OptionParser.new do |opts|
27
+ opts.banner = <<BANNER
28
+
29
+ Vintage - v.#{Vintage::VERSION::STRING}
30
+ =================
31
+ The super-micro web framework. If a project name is provided,
32
+ a new project is generated. Otherwise, Vintage will start serving
33
+ given the defaults and/or any provided options.
34
+
35
+ Usage: #{File.basename($0)} [options]
36
+ #{File.basename($0)} [project name]
37
+
38
+ Options are:
39
+ BANNER
40
+ opts.separator ""
41
+ opts.on("-p", "--path=PATH", String,
42
+ "The root path for selecting files",
43
+ "Default: ~") { |OPTIONS[:path]| }
44
+ opts.on("-P", "--port=PORT", Integer,
45
+ "The port to serve up your Vintage application on",
46
+ "Default: 5000") { |OPTIONS[:port]| }
47
+ opts.on("-c", "--config=FILE", String,
48
+ "The configuration file to use when launching this Vintage application",
49
+ "Default: configuration.rb") { |OPTIONS[:config]| }
50
+ opts.on("-t", "--template=TYPE", String,
51
+ "The parser used for templates (can be erb, haml, mab, markdown, or textile)",
52
+ "Default: erb") { |OPTIONS[:templates]| }
53
+ opts.on("-m", "--mount-at=url", String,
54
+ "The relative URL to mount this application at (e.g., vintage -m myapp will mount at http://localhost/myapp)",
55
+ "Default: none (mounted at /)") { |OPTIONS[:mount]| }
56
+ opts.on("-r", "--root=template", String,
57
+ "The template to render at the root URL",
58
+ "Default: index") { |OPTIONS[:root]| }
59
+ opts.on("-h", "--help",
60
+ "Show this help message.") { puts opts; exit }
61
+ opts.parse!(ARGV)
62
+ end
63
+
64
+ if ARGV.empty?
65
+ puts parser
66
+ puts
67
+ elsif ARGV[0] == "start"
68
+ OPTIONS.merge!(YAML::load_file(OPTIONS[:config])) if File.exists?(OPTIONS[:config])
69
+ Vintage::Server.run(OPTIONS)
70
+ else
71
+ require 'rubigen/scripts/generate'
72
+ source = RubiGen::PathSource.new(:application, File.join(File.dirname(__FILE__), "../app_generators"))
73
+ RubiGen::Base.reset_sources
74
+ RubiGen::Base.append_sources source
75
+ RubiGen::Scripts::Generate.new.run(ARGV, :generator => 'vintage_application')
76
+ end
data/config/hoe.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'vintage/version'
2
+
3
+ AUTHOR = 'Jeremy McAnally' # can also be an array of Authors
4
+ EMAIL = "jeremymcanally@gmail.com"
5
+ DESCRIPTION = "A super simple web framework"
6
+ GEM_NAME = 'vintage' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'vintage' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "unknown"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ # UNCOMMENT IF REQUIRED:
33
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
+ VERS = Vintage::VERSION::STRING + (REV ? ".#{REV}" : "")
35
+ VERSION = VERS
36
+ RDOC_OPTS = ['--quiet', '--title', 'vintage documentation',
37
+ "--opname", "index.html",
38
+ "--line-numbers",
39
+ "--main", "README",
40
+ "--inline-source"]
41
+
42
+ class Hoe
43
+ def extra_deps
44
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
45
+ @extra_deps
46
+ end
47
+ end
48
+
49
+ # Generate all the Rake tasks
50
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
51
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
52
+ p.author = AUTHOR
53
+ p.description = DESCRIPTION
54
+ p.email = EMAIL
55
+ p.summary = DESCRIPTION
56
+ p.url = HOMEPATH
57
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
58
+ p.test_globs = ["test/**/test_*.rb"]
59
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
60
+
61
+ # == Optional
62
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
63
+ #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
64
+
65
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
66
+
67
+ end
68
+
69
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
70
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
71
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
72
+ hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'vintage'
@@ -0,0 +1,76 @@
1
+ module Vintage
2
+ # A class to render the default error pages. These will
3
+ # not render if error pages are specified in the configuration.
4
+ class ErrorReporter
5
+ # Standard template to render for a <tt>500 Internal Server Error</tt>
6
+ def self.internal_error(error, params)
7
+ """
8
+ <html>
9
+ <head>
10
+ <title>Vintage Error: 500 Internal Server Error</title>
11
+ <style>
12
+ body { margin: 0px; padding: 0px; font-family: sans-serif; }
13
+ h1 { background: #3E2B09; padding: 45px 10px 10px 10px; color: #6F5E3C; border: 0px; border-bottom: 2px solid #1C0907; margin: 0px; }
14
+ h1 span.error { text-shadow: 0.1em 0.1em #333; color: white; }
15
+ h2 { margin: 0px; padding: 5px 5px 10px 10px; font-size: 14pt !important; }
16
+ h2 span.where { color: #999; }
17
+ h3 { margin: 0px; padding: 10px 10px; color: #999;}
18
+ ul { margin: 0px; }
19
+ li { margin: 0px; padding: 0px 30px; }
20
+ pre { padding: 0 30px; margin: 0px; }
21
+ </style>
22
+ </head>
23
+
24
+ <body>
25
+ <h1><span class='error'>#{error.class}</span> 500 Internal Server Error</h1>
26
+ <h2>#{error.message} <span class='where'>at #{error.backtrace[0]}</span></h2>
27
+ <div>
28
+ <h3>Parameters</h3>
29
+ <ul>
30
+ #{params == {} ? "None" : params.to_a.map{|key, val| "<li><b>" + key.to_s + "<b> = " + val.to_s + "</li>"}.join("\n") }
31
+ </ul>
32
+ <br />
33
+ <h3>Backtrace</h3>
34
+ <pre>#{error.backtrace.join("\n")}</pre>
35
+ </div>
36
+ </body>
37
+ </html>
38
+
39
+ """
40
+ end
41
+
42
+ # Standard template to render for a <tt>404 Page Not Found</tt> error
43
+ def self.not_found(url, remote_ip, params)
44
+ """
45
+ <html>
46
+ <head>
47
+ <title>Vintage Error: 404 Page Not Found</title>
48
+ <style>
49
+ body { margin: 0px; padding: 0px; font-family: sans-serif; }
50
+ h1 { background: #3E2B09; padding: 45px 10px 10px 10px; color: #6F5E3C; border: 0px; border-bottom: 2px solid #1C0907; margin: 0px; }
51
+ h1 span.error { text-shadow: 0.1em 0.1em #333; color: white; }
52
+ h2 { margin: 0px; padding: 5px 5px 10px 10px; font-size: 14pt !important; }
53
+ h2 span.where { color: #999; }
54
+ h3 { margin: 0px; padding: 10px 10px; color: #999;}
55
+ ul { margin: 0px; }
56
+ li { margin: 0px; padding: 0px 30px; }
57
+ pre { padding: 0 30px; margin: 0px; }
58
+ </style>
59
+ </head>
60
+
61
+ <body>
62
+ <h1><span class='error'>Page Not Found</span> 404 Not Found</h1>
63
+ <h2>Request for #{url} <span class='where'>from #{remote_ip}</span></h2>
64
+ <div>
65
+ <h3>Parameters</h3>
66
+ <ul>
67
+ #{params == {} ? "None" : params.to_a.map{|key, val| "<li><b>" + key.to_s + "<b> = " + val.to_s + "</li>"}.join("\n") }
68
+ </ul>
69
+ </div>
70
+ </body>
71
+ </html>
72
+
73
+ """
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,121 @@
1
+ require 'rubygems'
2
+ require 'mongrel'
3
+ require 'erubis'
4
+ require 'erb'
5
+ require 'mime/types'
6
+
7
+ require 'vintage/renderer'
8
+ require 'vintage/request_context'
9
+ require 'vintage/errors'
10
+
11
+ module Vintage
12
+ # The Mongrel HTTP Handler. Handles all operations with requests.
13
+ class Handler < Mongrel::HttpHandler
14
+ def initialize(options)
15
+ # Make our configuration options avialable to the handler
16
+ @options = options
17
+
18
+ # Setup a DirHandler for sending static files securely
19
+ @static_handler = Mongrel::DirHandler.new(@options[:static_path], false, nil)
20
+
21
+ # Inject our helpers in the RequestContext class to make them
22
+ # available on each request.
23
+ include_helpers
24
+ end
25
+
26
+ # 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
+
31
+ # 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
+
37
+ # Initialize the buffered log entry
38
+ log_entry = ""
39
+ log_entry << "*** request for [#{request.params['REQUEST_URI']}] from [#{request.params['REMOTE_ADDR']}]\n"
40
+
41
+ # If it's a root request, we want to render the template we configured
42
+ @request_path = @options[:root] if @request_path == '/'
43
+
44
+ # If it's a static file we don't need to append a file extension
45
+ filename = (@request_path =~ /\.(.*)$/) ? "#{@options[:static_path]}/#{@request_path}" : "#{@options[:path]}/#{@request_path}.#{@options[:templates]}"
46
+
47
+ # Does the file exist...?
48
+ if File.exists?(filename)
49
+ # It's found! Let's add to our log entry...
50
+ log_entry << " response: [200]\n"
51
+ log_entry << " rendering [#{@request_path}]\n"
52
+
53
+ # Is it a static file?
54
+ if (@request_path =~ /\.(.*)$/)
55
+ # Yes? Let our static handler take it away!
56
+ @static_handler.process(request, response)
57
+ else
58
+ # No! Render a template...
59
+ content = Renderer.send(@options[:templates].to_sym, File.open("#{@options[:path]}#{@request_path}.#{@options[:templates]}", "r").read, context)
60
+ end
61
+
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
+
69
+ # 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
74
+ end
75
+ else
76
+ # 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
86
+ end
87
+ rescue StandardError => err
88
+ # 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
95
+ ensure
96
+ # After every request push the buffered log entry out to the logger
97
+ 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
112
+ end
113
+
114
+ # Inject the default helpers and helpers from the
115
+ # +helpers/+ directory (if available) into the
116
+ # RequestContext class.
117
+ def include_helpers
118
+ RequestContext.send(:include, Vintage::Helpers)
119
+ end
120
+ end
121
+ end