adamwiggins-sinatra 0.8.9 → 0.10.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/AUTHORS +8 -7
 - data/CHANGES +211 -1
 - data/LICENSE +1 -1
 - data/README.rdoc +183 -139
 - data/Rakefile +20 -81
 - data/lib/sinatra.rb +5 -1
 - data/lib/sinatra/base.rb +569 -278
 - data/lib/sinatra/main.rb +12 -25
 - data/lib/sinatra/showexceptions.rb +303 -0
 - data/sinatra.gemspec +20 -44
 - data/test/base_test.rb +140 -52
 - data/test/builder_test.rb +14 -17
 - data/test/contest.rb +64 -0
 - data/test/erb_test.rb +42 -16
 - data/test/extensions_test.rb +100 -0
 - data/test/filter_test.rb +85 -13
 - data/test/haml_test.rb +39 -21
 - data/test/helper.rb +76 -0
 - data/test/helpers_test.rb +219 -84
 - data/test/mapped_error_test.rb +168 -146
 - data/test/middleware_test.rb +22 -17
 - data/test/options_test.rb +323 -54
 - data/test/render_backtrace_test.rb +145 -0
 - data/test/request_test.rb +28 -6
 - data/test/response_test.rb +42 -0
 - data/test/result_test.rb +27 -21
 - data/test/route_added_hook_test.rb +59 -0
 - data/test/routing_test.rb +558 -77
 - data/test/sass_test.rb +52 -13
 - data/test/server_test.rb +47 -0
 - data/test/sinatra_test.rb +3 -5
 - data/test/static_test.rb +57 -30
 - data/test/templates_test.rb +74 -25
 - data/test/views/error.builder +3 -0
 - data/test/views/error.erb +3 -0
 - data/test/views/error.haml +3 -0
 - data/test/views/error.sass +2 -0
 - data/test/views/foo/hello.test +1 -0
 - metadata +50 -46
 - data/compat/app_test.rb +0 -300
 - data/compat/application_test.rb +0 -334
 - data/compat/builder_test.rb +0 -101
 - data/compat/custom_error_test.rb +0 -62
 - data/compat/erb_test.rb +0 -136
 - data/compat/events_test.rb +0 -75
 - data/compat/filter_test.rb +0 -30
 - data/compat/haml_test.rb +0 -233
 - data/compat/helper.rb +0 -21
 - data/compat/mapped_error_test.rb +0 -72
 - data/compat/pipeline_test.rb +0 -71
 - data/compat/public/foo.xml +0 -1
 - data/compat/sass_test.rb +0 -57
 - data/compat/sessions_test.rb +0 -39
 - data/compat/streaming_test.rb +0 -121
 - data/compat/sym_params_test.rb +0 -19
 - data/compat/template_test.rb +0 -30
 - data/compat/use_in_file_templates_test.rb +0 -47
 - data/compat/views/foo.builder +0 -1
 - data/compat/views/foo.erb +0 -1
 - data/compat/views/foo.haml +0 -1
 - data/compat/views/foo.sass +0 -2
 - data/compat/views/foo_layout.erb +0 -2
 - data/compat/views/foo_layout.haml +0 -2
 - data/compat/views/layout_test/foo.builder +0 -1
 - data/compat/views/layout_test/foo.erb +0 -1
 - data/compat/views/layout_test/foo.haml +0 -1
 - data/compat/views/layout_test/foo.sass +0 -2
 - data/compat/views/layout_test/layout.builder +0 -3
 - data/compat/views/layout_test/layout.erb +0 -1
 - data/compat/views/layout_test/layout.haml +0 -1
 - data/compat/views/layout_test/layout.sass +0 -2
 - data/compat/views/no_layout/no_layout.builder +0 -1
 - data/compat/views/no_layout/no_layout.haml +0 -1
 - data/lib/sinatra/compat.rb +0 -239
 - data/lib/sinatra/test.rb +0 -112
 - data/lib/sinatra/test/rspec.rb +0 -2
 - data/lib/sinatra/test/spec.rb +0 -2
 - data/lib/sinatra/test/unit.rb +0 -11
 - data/test/reload_test.rb +0 -65
 
    
        data/Rakefile
    CHANGED
    
    | 
         @@ -1,26 +1,15 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'rubygems'
         
     | 
| 
       2 
1 
     | 
    
         
             
            require 'rake/clean'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rake/testtask'
         
     | 
| 
       3 
3 
     | 
    
         
             
            require 'fileutils'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            task :default => :test
         
     | 
| 
      
 6 
     | 
    
         
            +
            task :spec => :test
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
8 
     | 
    
         
             
            # SPECS ===============================================================
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
               
     | 
| 
       12 
     | 
    
         
            -
              sh "specrb --testcase '#{pattern}' --specdox -Ilib:test test/*_test.rb"
         
     | 
| 
       13 
     | 
    
         
            -
            end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
            desc 'Run specs with unit test style output'
         
     | 
| 
       16 
     | 
    
         
            -
            task :test do |t|
         
     | 
| 
       17 
     | 
    
         
            -
              sh "specrb -Ilib:test test/*_test.rb"
         
     | 
| 
       18 
     | 
    
         
            -
            end
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
            desc 'Run compatibility specs'
         
     | 
| 
       21 
     | 
    
         
            -
            task :compat do |t|
         
     | 
| 
       22 
     | 
    
         
            -
              pattern = ENV['TEST'] || '.*'
         
     | 
| 
       23 
     | 
    
         
            -
              sh "specrb --testcase '#{pattern}' -Ilib:test compat/*_test.rb"
         
     | 
| 
      
 10 
     | 
    
         
            +
            Rake::TestTask.new(:test) do |t|
         
     | 
| 
      
 11 
     | 
    
         
            +
              t.test_files = FileList['test/*_test.rb']
         
     | 
| 
      
 12 
     | 
    
         
            +
              t.ruby_opts = ['-rubygems'] if defined? Gem
         
     | 
| 
       24 
13 
     | 
    
         
             
            end
         
     | 
| 
       25 
14 
     | 
    
         | 
| 
       26 
15 
     | 
    
         
             
            # PACKAGING ============================================================
         
     | 
| 
         @@ -38,7 +27,7 @@ def spec 
     | 
|
| 
       38 
27 
     | 
    
         
             
            end
         
     | 
| 
       39 
28 
     | 
    
         | 
| 
       40 
29 
     | 
    
         
             
            def package(ext='')
         
     | 
| 
       41 
     | 
    
         
            -
              " 
     | 
| 
      
 30 
     | 
    
         
            +
              "pkg/sinatra-#{spec.version}" + ext
         
     | 
| 
       42 
31 
     | 
    
         
             
            end
         
     | 
| 
       43 
32 
     | 
    
         | 
| 
       44 
33 
     | 
    
         
             
            desc 'Build packages'
         
     | 
| 
         @@ -49,25 +38,27 @@ task :install => package('.gem') do 
     | 
|
| 
       49 
38 
     | 
    
         
             
              sh "gem install #{package('.gem')}"
         
     | 
| 
       50 
39 
     | 
    
         
             
            end
         
     | 
| 
       51 
40 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
            directory ' 
     | 
| 
      
 41 
     | 
    
         
            +
            directory 'pkg/'
         
     | 
| 
      
 42 
     | 
    
         
            +
            CLOBBER.include('pkg')
         
     | 
| 
       53 
43 
     | 
    
         | 
| 
       54 
     | 
    
         
            -
            file package('.gem') => %w[ 
     | 
| 
      
 44 
     | 
    
         
            +
            file package('.gem') => %w[pkg/ sinatra.gemspec] + spec.files do |f|
         
     | 
| 
       55 
45 
     | 
    
         
             
              sh "gem build sinatra.gemspec"
         
     | 
| 
       56 
46 
     | 
    
         
             
              mv File.basename(f.name), f.name
         
     | 
| 
       57 
47 
     | 
    
         
             
            end
         
     | 
| 
       58 
48 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
            file package('.tar.gz') => %w[ 
     | 
| 
       60 
     | 
    
         
            -
              sh  
     | 
| 
      
 49 
     | 
    
         
            +
            file package('.tar.gz') => %w[pkg/] + spec.files do |f|
         
     | 
| 
      
 50 
     | 
    
         
            +
              sh <<-SH
         
     | 
| 
      
 51 
     | 
    
         
            +
                git archive \
         
     | 
| 
      
 52 
     | 
    
         
            +
                  --prefix=sinatra-#{source_version}/ \
         
     | 
| 
      
 53 
     | 
    
         
            +
                  --format=tar \
         
     | 
| 
      
 54 
     | 
    
         
            +
                  HEAD | gzip > #{f.name}
         
     | 
| 
      
 55 
     | 
    
         
            +
              SH
         
     | 
| 
       61 
56 
     | 
    
         
             
            end
         
     | 
| 
       62 
57 
     | 
    
         | 
| 
       63 
58 
     | 
    
         
             
            # Rubyforge Release / Publish Tasks ==================================
         
     | 
| 
       64 
59 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
            desc 'Publish  
     | 
| 
       66 
     | 
    
         
            -
            task ' 
     | 
| 
       67 
     | 
    
         
            -
              sh 'scp -rp doc/* rubyforge.org:/var/www/gforge-projects/sinatra/'
         
     | 
| 
       68 
     | 
    
         
            -
            end
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
            task 'publish:gem' => [package('.gem'), package('.tar.gz')] do |t|
         
     | 
| 
      
 60 
     | 
    
         
            +
            desc 'Publish gem and tarball to rubyforge'
         
     | 
| 
      
 61 
     | 
    
         
            +
            task 'release' => [package('.gem'), package('.tar.gz')] do |t|
         
     | 
| 
       71 
62 
     | 
    
         
             
              sh <<-end
         
     | 
| 
       72 
63 
     | 
    
         
             
                rubyforge add_release sinatra sinatra #{spec.version} #{package('.gem')} &&
         
     | 
| 
       73 
64 
     | 
    
         
             
                rubyforge add_file    sinatra sinatra #{spec.version} #{package('.tar.gz')}
         
     | 
| 
         @@ -78,7 +69,7 @@ end 
     | 
|
| 
       78 
69 
     | 
    
         
             
            # Building docs requires HAML and the hanna gem:
         
     | 
| 
       79 
70 
     | 
    
         
             
            #   gem install mislav-hanna --source=http://gems.github.com
         
     | 
| 
       80 
71 
     | 
    
         | 
| 
       81 
     | 
    
         
            -
            task 'doc'     => ['doc:api' 
     | 
| 
      
 72 
     | 
    
         
            +
            task 'doc'     => ['doc:api']
         
     | 
| 
       82 
73 
     | 
    
         | 
| 
       83 
74 
     | 
    
         
             
            desc 'Generate Hanna RDoc under doc/api'
         
     | 
| 
       84 
75 
     | 
    
         
             
            task 'doc:api' => ['doc/api/index.html']
         
     | 
| 
         @@ -98,53 +89,6 @@ file 'doc/api/index.html' => FileList['lib/**/*.rb','README.rdoc'] do |f| 
     | 
|
| 
       98 
89 
     | 
    
         
             
            end
         
     | 
| 
       99 
90 
     | 
    
         
             
            CLEAN.include 'doc/api'
         
     | 
| 
       100 
91 
     | 
    
         | 
| 
       101 
     | 
    
         
            -
            def rdoc_to_html(file_name)
         
     | 
| 
       102 
     | 
    
         
            -
              require 'rdoc/markup/to_html'
         
     | 
| 
       103 
     | 
    
         
            -
              rdoc = RDoc::Markup::ToHtml.new
         
     | 
| 
       104 
     | 
    
         
            -
              rdoc.convert(File.read(file_name))
         
     | 
| 
       105 
     | 
    
         
            -
            end
         
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
            def haml(locals={})
         
     | 
| 
       108 
     | 
    
         
            -
              require 'haml'
         
     | 
| 
       109 
     | 
    
         
            -
              template = File.read('doc/template.haml')
         
     | 
| 
       110 
     | 
    
         
            -
              haml = Haml::Engine.new(template, :format => :html4, :attr_wrapper => '"')
         
     | 
| 
       111 
     | 
    
         
            -
              haml.render(Object.new, locals)
         
     | 
| 
       112 
     | 
    
         
            -
            end
         
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
            desc 'Build website HTML and stuff'
         
     | 
| 
       115 
     | 
    
         
            -
            task 'doc:site' => ['doc/index.html', 'doc/book.html']
         
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
            file 'doc/index.html' => %w[README.rdoc doc/template.haml] do |file|
         
     | 
| 
       118 
     | 
    
         
            -
              File.open(file.name, 'w') do |file|
         
     | 
| 
       119 
     | 
    
         
            -
                file << haml(:title => 'Sinatra', :content => rdoc_to_html('README.rdoc'))
         
     | 
| 
       120 
     | 
    
         
            -
              end
         
     | 
| 
       121 
     | 
    
         
            -
            end
         
     | 
| 
       122 
     | 
    
         
            -
            CLEAN.include 'doc/index.html'
         
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
            file 'doc/book.html' => ['book/output/sinatra-book.html'] do |file|
         
     | 
| 
       125 
     | 
    
         
            -
              File.open(file.name, 'w') do |file|
         
     | 
| 
       126 
     | 
    
         
            -
                book_content = File.read('book/output/sinatra-book.html')
         
     | 
| 
       127 
     | 
    
         
            -
                file << haml(:title => 'Sinatra Book', :content => book_content)
         
     | 
| 
       128 
     | 
    
         
            -
              end
         
     | 
| 
       129 
     | 
    
         
            -
            end
         
     | 
| 
       130 
     | 
    
         
            -
            CLEAN.include 'doc/book.html'
         
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
       132 
     | 
    
         
            -
            file 'book/output/sinatra-book.html' => FileList['book/**'] do |f|
         
     | 
| 
       133 
     | 
    
         
            -
              unless File.directory?('book')
         
     | 
| 
       134 
     | 
    
         
            -
                sh 'git clone git://github.com/cschneid/sinatra-book.git book'
         
     | 
| 
       135 
     | 
    
         
            -
              end
         
     | 
| 
       136 
     | 
    
         
            -
              sh((<<-SH).strip.gsub(/\s+/, ' '))
         
     | 
| 
       137 
     | 
    
         
            -
                cd book &&
         
     | 
| 
       138 
     | 
    
         
            -
                git fetch origin &&
         
     | 
| 
       139 
     | 
    
         
            -
                git rebase origin/master &&
         
     | 
| 
       140 
     | 
    
         
            -
                thor book:build
         
     | 
| 
       141 
     | 
    
         
            -
              SH
         
     | 
| 
       142 
     | 
    
         
            -
            end
         
     | 
| 
       143 
     | 
    
         
            -
            CLEAN.include 'book/output/sinatra-book.html'
         
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
            desc 'Build the Sinatra book'
         
     | 
| 
       146 
     | 
    
         
            -
            task 'doc:book' => ['book/output/sinatra-book.html']
         
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
92 
     | 
    
         
             
            # Gemspec Helpers ====================================================
         
     | 
| 
       149 
93 
     | 
    
         | 
| 
       150 
94 
     | 
    
         
             
            def source_version
         
     | 
| 
         @@ -152,12 +96,7 @@ def source_version 
     | 
|
| 
       152 
96 
     | 
    
         
             
              line.match(/.*VERSION = '(.*)'/)[1]
         
     | 
| 
       153 
97 
     | 
    
         
             
            end
         
     | 
| 
       154 
98 
     | 
    
         | 
| 
       155 
     | 
    
         
            -
             
     | 
| 
       156 
     | 
    
         
            -
              FileList[
         
     | 
| 
       157 
     | 
    
         
            -
                '{lib,test,compat,images}/**',
         
     | 
| 
       158 
     | 
    
         
            -
                'Rakefile', 'CHANGES', 'README.rdoc'
         
     | 
| 
       159 
     | 
    
         
            -
              ]
         
     | 
| 
       160 
     | 
    
         
            -
            file 'sinatra.gemspec' => project_files do |f|
         
     | 
| 
      
 99 
     | 
    
         
            +
            task 'sinatra.gemspec' => FileList['{lib,test,compat}/**','Rakefile','CHANGES','*.rdoc'] do |f|
         
     | 
| 
       161 
100 
     | 
    
         
             
              # read spec file and split out manifest section
         
     | 
| 
       162 
101 
     | 
    
         
             
              spec = File.read(f.name)
         
     | 
| 
       163 
102 
     | 
    
         
             
              head, manifest, tail = spec.split("  # = MANIFEST =\n")
         
     | 
    
        data/lib/sinatra.rb
    CHANGED
    
    
    
        data/lib/sinatra/base.rb
    CHANGED
    
    | 
         @@ -1,32 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'thread'
         
     | 
| 
       1 
2 
     | 
    
         
             
            require 'time'
         
     | 
| 
       2 
3 
     | 
    
         
             
            require 'uri'
         
     | 
| 
       3 
4 
     | 
    
         
             
            require 'rack'
         
     | 
| 
       4 
5 
     | 
    
         
             
            require 'rack/builder'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'sinatra/showexceptions'
         
     | 
| 
       5 
7 
     | 
    
         | 
| 
       6 
8 
     | 
    
         
             
            module Sinatra
         
     | 
| 
       7 
     | 
    
         
            -
              VERSION = '0. 
     | 
| 
      
 9 
     | 
    
         
            +
              VERSION = '0.10.1'
         
     | 
| 
       8 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
              # The request object. See Rack::Request for more info:
         
     | 
| 
      
 12 
     | 
    
         
            +
              # http://rack.rubyforge.org/doc/classes/Rack/Request.html
         
     | 
| 
       9 
13 
     | 
    
         
             
              class Request < Rack::Request
         
     | 
| 
       10 
14 
     | 
    
         
             
                def user_agent
         
     | 
| 
       11 
15 
     | 
    
         
             
                  @env['HTTP_USER_AGENT']
         
     | 
| 
       12 
16 
     | 
    
         
             
                end
         
     | 
| 
       13 
17 
     | 
    
         | 
| 
      
 18 
     | 
    
         
            +
                # Returns an array of acceptable media types for the response
         
     | 
| 
       14 
19 
     | 
    
         
             
                def accept
         
     | 
| 
       15 
     | 
    
         
            -
                  @env['HTTP_ACCEPT'].split(',').map { |a| a.strip }
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @env['HTTP_ACCEPT'].to_s.split(',').map { |a| a.strip }
         
     | 
| 
       16 
21 
     | 
    
         
             
                end
         
     | 
| 
       17 
     | 
    
         
            -
              end
         
     | 
| 
       18 
22 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                def  
     | 
| 
       21 
     | 
    
         
            -
                   
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 23 
     | 
    
         
            +
                # Override Rack 0.9.x's #params implementation (see #72 in lighthouse)
         
     | 
| 
      
 24 
     | 
    
         
            +
                def params
         
     | 
| 
      
 25 
     | 
    
         
            +
                  self.GET.update(self.POST)
         
     | 
| 
      
 26 
     | 
    
         
            +
                rescue EOFError, Errno::ESPIPE
         
     | 
| 
      
 27 
     | 
    
         
            +
                  self.GET
         
     | 
| 
       23 
28 
     | 
    
         
             
                end
         
     | 
| 
       24 
29 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                def  
     | 
| 
       26 
     | 
    
         
            -
                  @ 
     | 
| 
       27 
     | 
    
         
            -
                  str
         
     | 
| 
      
 30 
     | 
    
         
            +
                def secure?
         
     | 
| 
      
 31 
     | 
    
         
            +
                  (@env['HTTP_X_FORWARDED_PROTO'] || @env['rack.url_scheme']) == 'https'
         
     | 
| 
       28 
32 
     | 
    
         
             
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
       29 
34 
     | 
    
         | 
| 
      
 35 
     | 
    
         
            +
              # The response object. See Rack::Response and Rack::ResponseHelpers for
         
     | 
| 
      
 36 
     | 
    
         
            +
              # more info:
         
     | 
| 
      
 37 
     | 
    
         
            +
              # http://rack.rubyforge.org/doc/classes/Rack/Response.html
         
     | 
| 
      
 38 
     | 
    
         
            +
              # http://rack.rubyforge.org/doc/classes/Rack/Response/Helpers.html
         
     | 
| 
      
 39 
     | 
    
         
            +
              class Response < Rack::Response
         
     | 
| 
       30 
40 
     | 
    
         
             
                def finish
         
     | 
| 
       31 
41 
     | 
    
         
             
                  @body = block if block_given?
         
     | 
| 
       32 
42 
     | 
    
         
             
                  if [204, 304].include?(status.to_i)
         
     | 
| 
         @@ -35,19 +45,20 @@ module Sinatra 
     | 
|
| 
       35 
45 
     | 
    
         
             
                  else
         
     | 
| 
       36 
46 
     | 
    
         
             
                    body = @body || []
         
     | 
| 
       37 
47 
     | 
    
         
             
                    body = [body] if body.respond_to? :to_str
         
     | 
| 
       38 
     | 
    
         
            -
                    if  
     | 
| 
      
 48 
     | 
    
         
            +
                    if body.respond_to?(:to_ary)
         
     | 
| 
       39 
49 
     | 
    
         
             
                      header["Content-Length"] = body.to_ary.
         
     | 
| 
       40 
     | 
    
         
            -
                        inject(0) { |len, part| len + part 
     | 
| 
      
 50 
     | 
    
         
            +
                        inject(0) { |len, part| len + Rack::Utils.bytesize(part) }.to_s
         
     | 
| 
       41 
51 
     | 
    
         
             
                    end
         
     | 
| 
       42 
52 
     | 
    
         
             
                    [status.to_i, header.to_hash, body]
         
     | 
| 
       43 
53 
     | 
    
         
             
                  end
         
     | 
| 
       44 
54 
     | 
    
         
             
                end
         
     | 
| 
       45 
55 
     | 
    
         
             
              end
         
     | 
| 
       46 
56 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
              class NotFound < NameError  
     | 
| 
      
 57 
     | 
    
         
            +
              class NotFound < NameError #:nodoc:
         
     | 
| 
       48 
58 
     | 
    
         
             
                def code ; 404 ; end
         
     | 
| 
       49 
59 
     | 
    
         
             
              end
         
     | 
| 
       50 
60 
     | 
    
         | 
| 
      
 61 
     | 
    
         
            +
              # Methods available to routes, before filters, and views.
         
     | 
| 
       51 
62 
     | 
    
         
             
              module Helpers
         
     | 
| 
       52 
63 
     | 
    
         
             
                # Set or retrieve the response status code.
         
     | 
| 
       53 
64 
     | 
    
         
             
                def status(value=nil)
         
     | 
| 
         @@ -75,7 +86,7 @@ module Sinatra 
     | 
|
| 
       75 
86 
     | 
    
         | 
| 
       76 
87 
     | 
    
         
             
                # Halt processing and return the error status provided.
         
     | 
| 
       77 
88 
     | 
    
         
             
                def error(code, body=nil)
         
     | 
| 
       78 
     | 
    
         
            -
                  code, body 
     | 
| 
      
 89 
     | 
    
         
            +
                  code, body    = 500, code.to_str if code.respond_to? :to_str
         
     | 
| 
       79 
90 
     | 
    
         
             
                  response.body = body unless body.nil?
         
     | 
| 
       80 
91 
     | 
    
         
             
                  halt code
         
     | 
| 
       81 
92 
     | 
    
         
             
                end
         
     | 
| 
         @@ -85,6 +96,12 @@ module Sinatra 
     | 
|
| 
       85 
96 
     | 
    
         
             
                  error 404, body
         
     | 
| 
       86 
97 
     | 
    
         
             
                end
         
     | 
| 
       87 
98 
     | 
    
         | 
| 
      
 99 
     | 
    
         
            +
                # Set multiple response headers with Hash.
         
     | 
| 
      
 100 
     | 
    
         
            +
                def headers(hash=nil)
         
     | 
| 
      
 101 
     | 
    
         
            +
                  response.headers.merge! hash if hash
         
     | 
| 
      
 102 
     | 
    
         
            +
                  response.headers
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
       88 
105 
     | 
    
         
             
                # Access the underlying Rack session.
         
     | 
| 
       89 
106 
     | 
    
         
             
                def session
         
     | 
| 
       90 
107 
     | 
    
         
             
                  env['rack.session'] ||= {}
         
     | 
| 
         @@ -118,23 +135,35 @@ module Sinatra 
     | 
|
| 
       118 
135 
     | 
    
         
             
                  end
         
     | 
| 
       119 
136 
     | 
    
         
             
                end
         
     | 
| 
       120 
137 
     | 
    
         | 
| 
       121 
     | 
    
         
            -
                # Use the contents of the file as the response body 
     | 
| 
      
 138 
     | 
    
         
            +
                # Use the contents of the file at +path+ as the response body.
         
     | 
| 
       122 
139 
     | 
    
         
             
                def send_file(path, opts={})
         
     | 
| 
       123 
140 
     | 
    
         
             
                  stat = File.stat(path)
         
     | 
| 
       124 
141 
     | 
    
         
             
                  last_modified stat.mtime
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
       125 
143 
     | 
    
         
             
                  content_type media_type(opts[:type]) ||
         
     | 
| 
       126 
144 
     | 
    
         
             
                    media_type(File.extname(path)) ||
         
     | 
| 
       127 
145 
     | 
    
         
             
                    response['Content-Type'] ||
         
     | 
| 
       128 
146 
     | 
    
         
             
                    'application/octet-stream'
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
       129 
148 
     | 
    
         
             
                  response['Content-Length'] ||= (opts[:length] || stat.size).to_s
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  if opts[:disposition] == 'attachment' || opts[:filename]
         
     | 
| 
      
 151 
     | 
    
         
            +
                    attachment opts[:filename] || path
         
     | 
| 
      
 152 
     | 
    
         
            +
                  elsif opts[:disposition] == 'inline'
         
     | 
| 
      
 153 
     | 
    
         
            +
                    response['Content-Disposition'] = 'inline'
         
     | 
| 
      
 154 
     | 
    
         
            +
                  end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
       130 
156 
     | 
    
         
             
                  halt StaticFile.open(path, 'rb')
         
     | 
| 
       131 
157 
     | 
    
         
             
                rescue Errno::ENOENT
         
     | 
| 
       132 
158 
     | 
    
         
             
                  not_found
         
     | 
| 
       133 
159 
     | 
    
         
             
                end
         
     | 
| 
       134 
160 
     | 
    
         | 
| 
      
 161 
     | 
    
         
            +
                # Rack response body used to deliver static files. The file contents are
         
     | 
| 
      
 162 
     | 
    
         
            +
                # generated iteratively in 8K chunks.
         
     | 
| 
       135 
163 
     | 
    
         
             
                class StaticFile < ::File #:nodoc:
         
     | 
| 
       136 
164 
     | 
    
         
             
                  alias_method :to_path, :path
         
     | 
| 
       137 
165 
     | 
    
         
             
                  def each
         
     | 
| 
      
 166 
     | 
    
         
            +
                    rewind
         
     | 
| 
       138 
167 
     | 
    
         
             
                    while buf = read(8192)
         
     | 
| 
       139 
168 
     | 
    
         
             
                      yield buf
         
     | 
| 
       140 
169 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -177,109 +206,148 @@ module Sinatra 
     | 
|
| 
       177 
206 
     | 
    
         
             
                    halt 304 if etags.include?(value) || etags.include?('*')
         
     | 
| 
       178 
207 
     | 
    
         
             
                  end
         
     | 
| 
       179 
208 
     | 
    
         
             
                end
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                ## Sugar for redirect (example:  redirect back)
         
     | 
| 
      
 211 
     | 
    
         
            +
                def back ; request.referer ; end
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
       180 
213 
     | 
    
         
             
              end
         
     | 
| 
       181 
214 
     | 
    
         | 
| 
      
 215 
     | 
    
         
            +
              # Template rendering methods. Each method takes the name of a template
         
     | 
| 
      
 216 
     | 
    
         
            +
              # to render as a Symbol and returns a String with the rendered output,
         
     | 
| 
      
 217 
     | 
    
         
            +
              # as well as an optional hash with additional options.
         
     | 
| 
      
 218 
     | 
    
         
            +
              #
         
     | 
| 
      
 219 
     | 
    
         
            +
              # `template` is either the name or path of the template as symbol
         
     | 
| 
      
 220 
     | 
    
         
            +
              # (Use `:'subdir/myview'` for views in subdirectories), or a string
         
     | 
| 
      
 221 
     | 
    
         
            +
              # that will be rendered.
         
     | 
| 
      
 222 
     | 
    
         
            +
              #
         
     | 
| 
      
 223 
     | 
    
         
            +
              # Possible options are:
         
     | 
| 
      
 224 
     | 
    
         
            +
              #   :layout       If set to false, no layout is rendered, otherwise
         
     | 
| 
      
 225 
     | 
    
         
            +
              #                 the specified layout is used (Ignored for `sass`)
         
     | 
| 
      
 226 
     | 
    
         
            +
              #   :locals       A hash with local variables that should be available
         
     | 
| 
      
 227 
     | 
    
         
            +
              #                 in the template
         
     | 
| 
       182 
228 
     | 
    
         
             
              module Templates
         
     | 
| 
       183 
     | 
    
         
            -
                def  
     | 
| 
       184 
     | 
    
         
            -
                   
     | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
       186 
     | 
    
         
            -
             
     | 
| 
      
 229 
     | 
    
         
            +
                def erb(template, options={}, locals={})
         
     | 
| 
      
 230 
     | 
    
         
            +
                  render :erb, template, options, locals
         
     | 
| 
      
 231 
     | 
    
         
            +
                end
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
                def haml(template, options={}, locals={})
         
     | 
| 
      
 234 
     | 
    
         
            +
                  render :haml, template, options, locals
         
     | 
| 
      
 235 
     | 
    
         
            +
                end
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
                def sass(template, options={}, locals={})
         
     | 
| 
      
 238 
     | 
    
         
            +
                  options[:layout] = false
         
     | 
| 
      
 239 
     | 
    
         
            +
                  render :sass, template, options, locals
         
     | 
| 
      
 240 
     | 
    
         
            +
                end
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                def builder(template=nil, options={}, locals={}, &block)
         
     | 
| 
      
 243 
     | 
    
         
            +
                  options, template = template, nil if template.is_a?(Hash)
         
     | 
| 
      
 244 
     | 
    
         
            +
                  template = lambda { block } if template.nil?
         
     | 
| 
      
 245 
     | 
    
         
            +
                  render :builder, template, options, locals
         
     | 
| 
      
 246 
     | 
    
         
            +
                end
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
              private
         
     | 
| 
      
 249 
     | 
    
         
            +
                def render(engine, template, options={}, locals={})
         
     | 
| 
      
 250 
     | 
    
         
            +
                  # merge app-level options
         
     | 
| 
      
 251 
     | 
    
         
            +
                  options = self.class.send(engine).merge(options) if self.class.respond_to?(engine)
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                  # extract generic options
         
     | 
| 
      
 254 
     | 
    
         
            +
                  layout = options.delete(:layout)
         
     | 
| 
      
 255 
     | 
    
         
            +
                  layout = :layout if layout.nil? || layout == true
         
     | 
| 
      
 256 
     | 
    
         
            +
                  views = options.delete(:views) || self.class.views || "./views"
         
     | 
| 
      
 257 
     | 
    
         
            +
                  locals = options.delete(:locals) || locals || {}
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
                  # render template
         
     | 
| 
      
 260 
     | 
    
         
            +
                  data, options[:filename], options[:line] = lookup_template(engine, template, views)
         
     | 
| 
      
 261 
     | 
    
         
            +
                  output = __send__("render_#{engine}", data, options, locals)
         
     | 
| 
      
 262 
     | 
    
         
            +
             
     | 
| 
      
 263 
     | 
    
         
            +
                  # render layout
         
     | 
| 
       187 
264 
     | 
    
         
             
                  if layout
         
     | 
| 
       188 
     | 
    
         
            -
                     
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
             
     | 
| 
      
 265 
     | 
    
         
            +
                    data, options[:filename], options[:line] = lookup_layout(engine, layout, views)
         
     | 
| 
      
 266 
     | 
    
         
            +
                    if data
         
     | 
| 
      
 267 
     | 
    
         
            +
                      output = __send__("render_#{engine}", data, options, locals) { output }
         
     | 
| 
      
 268 
     | 
    
         
            +
                    end
         
     | 
| 
       191 
269 
     | 
    
         
             
                  end
         
     | 
| 
      
 270 
     | 
    
         
            +
             
     | 
| 
      
 271 
     | 
    
         
            +
                  output
         
     | 
| 
       192 
272 
     | 
    
         
             
                end
         
     | 
| 
       193 
273 
     | 
    
         | 
| 
       194 
     | 
    
         
            -
                def lookup_template(engine, template,  
     | 
| 
      
 274 
     | 
    
         
            +
                def lookup_template(engine, template, views_dir, filename = nil, line = nil)
         
     | 
| 
       195 
275 
     | 
    
         
             
                  case template
         
     | 
| 
       196 
276 
     | 
    
         
             
                  when Symbol
         
     | 
| 
       197 
     | 
    
         
            -
                     
     | 
| 
       198 
     | 
    
         
            -
                      lookup_template(engine, cached, options)
         
     | 
| 
       199 
     | 
    
         
            -
                    else
         
     | 
| 
       200 
     | 
    
         
            -
                      ::File.read(template_path(engine, template, options))
         
     | 
| 
       201 
     | 
    
         
            -
                    end
         
     | 
| 
      
 277 
     | 
    
         
            +
                    load_template(engine, template, views_dir, options)
         
     | 
| 
       202 
278 
     | 
    
         
             
                  when Proc
         
     | 
| 
       203 
     | 
    
         
            -
                     
     | 
| 
      
 279 
     | 
    
         
            +
                    filename, line = self.class.caller_locations.first if filename.nil?
         
     | 
| 
      
 280 
     | 
    
         
            +
                    [template.call, filename, line.to_i]
         
     | 
| 
       204 
281 
     | 
    
         
             
                  when String
         
     | 
| 
       205 
     | 
    
         
            -
                     
     | 
| 
      
 282 
     | 
    
         
            +
                    filename, line = self.class.caller_locations.first if filename.nil?
         
     | 
| 
      
 283 
     | 
    
         
            +
                    [template, filename, line.to_i]
         
     | 
| 
       206 
284 
     | 
    
         
             
                  else
         
     | 
| 
       207 
285 
     | 
    
         
             
                    raise ArgumentError
         
     | 
| 
       208 
286 
     | 
    
         
             
                  end
         
     | 
| 
       209 
287 
     | 
    
         
             
                end
         
     | 
| 
       210 
288 
     | 
    
         | 
| 
       211 
     | 
    
         
            -
                def  
     | 
| 
       212 
     | 
    
         
            -
                   
     | 
| 
       213 
     | 
    
         
            -
                   
     | 
| 
       214 
     | 
    
         
            -
             
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
       217 
     | 
    
         
            -
             
     | 
| 
       218 
     | 
    
         
            -
             
     | 
| 
       219 
     | 
    
         
            -
             
     | 
| 
      
 289 
     | 
    
         
            +
                def load_template(engine, template, views_dir, options={})
         
     | 
| 
      
 290 
     | 
    
         
            +
                  base = self.class
         
     | 
| 
      
 291 
     | 
    
         
            +
                  while base.respond_to?(:templates)
         
     | 
| 
      
 292 
     | 
    
         
            +
                    if cached = base.templates[template]
         
     | 
| 
      
 293 
     | 
    
         
            +
                      return lookup_template(engine, cached[:template], views_dir, cached[:filename], cached[:line])
         
     | 
| 
      
 294 
     | 
    
         
            +
                    else
         
     | 
| 
      
 295 
     | 
    
         
            +
                      base = base.superclass
         
     | 
| 
      
 296 
     | 
    
         
            +
                    end
         
     | 
| 
      
 297 
     | 
    
         
            +
                  end
         
     | 
| 
       220 
298 
     | 
    
         | 
| 
       221 
     | 
    
         
            -
             
     | 
| 
       222 
     | 
    
         
            -
                  views_dir  
     | 
| 
       223 
     | 
    
         
            -
             
     | 
| 
       224 
     | 
    
         
            -
                  "#{views_dir}/#{template}.#{engine}"
         
     | 
| 
      
 299 
     | 
    
         
            +
                  # If no template exists in the cache, try loading from disk.
         
     | 
| 
      
 300 
     | 
    
         
            +
                  path = ::File.join(views_dir, "#{template}.#{engine}")
         
     | 
| 
      
 301 
     | 
    
         
            +
                  [ ::File.read(path), path, 1 ]
         
     | 
| 
       225 
302 
     | 
    
         
             
                end
         
     | 
| 
       226 
303 
     | 
    
         | 
| 
       227 
     | 
    
         
            -
                def  
     | 
| 
       228 
     | 
    
         
            -
                   
     | 
| 
       229 
     | 
    
         
            -
             
     | 
| 
      
 304 
     | 
    
         
            +
                def lookup_layout(engine, template, views_dir)
         
     | 
| 
      
 305 
     | 
    
         
            +
                  lookup_template(engine, template, views_dir)
         
     | 
| 
      
 306 
     | 
    
         
            +
                rescue Errno::ENOENT
         
     | 
| 
      
 307 
     | 
    
         
            +
                  nil
         
     | 
| 
       230 
308 
     | 
    
         
             
                end
         
     | 
| 
       231 
309 
     | 
    
         | 
| 
       232 
     | 
    
         
            -
                def render_erb( 
     | 
| 
      
 310 
     | 
    
         
            +
                def render_erb(data, options, locals, &block)
         
     | 
| 
      
 311 
     | 
    
         
            +
                  original_out_buf = defined?(@_out_buf) && @_out_buf
         
     | 
| 
       233 
312 
     | 
    
         
             
                  data = data.call if data.kind_of? Proc
         
     | 
| 
       234 
     | 
    
         
            -
                  instance = ::ERB.new(data)
         
     | 
| 
       235 
     | 
    
         
            -
                  locals = options[:locals] || {}
         
     | 
| 
       236 
     | 
    
         
            -
                  locals_assigns = locals.to_a.collect { |k,v| "#{k} = locals[:#{k}]" }
         
     | 
| 
       237 
     | 
    
         
            -
                  src = "#{locals_assigns.join("\n")}\n#{instance.src}"
         
     | 
| 
       238 
     | 
    
         
            -
                  eval src, binding, '(__ERB__)', locals_assigns.length + 1
         
     | 
| 
       239 
     | 
    
         
            -
                  instance.result(binding)
         
     | 
| 
       240 
     | 
    
         
            -
                end
         
     | 
| 
       241 
313 
     | 
    
         | 
| 
       242 
     | 
    
         
            -
             
     | 
| 
       243 
     | 
    
         
            -
                   
     | 
| 
       244 
     | 
    
         
            -
                  options[:options] ||= self.class.haml if self.class.respond_to? :haml
         
     | 
| 
       245 
     | 
    
         
            -
                  render :haml, template, options
         
     | 
| 
       246 
     | 
    
         
            -
                end
         
     | 
| 
      
 314 
     | 
    
         
            +
                  instance = ::ERB.new(data, nil, nil, '@_out_buf')
         
     | 
| 
      
 315 
     | 
    
         
            +
                  locals_assigns = locals.to_a.collect { |k,v| "#{k} = locals[:#{k}]" }
         
     | 
| 
       247 
316 
     | 
    
         | 
| 
       248 
     | 
    
         
            -
             
     | 
| 
       249 
     | 
    
         
            -
                   
     | 
| 
       250 
     | 
    
         
            -
                   
     | 
| 
       251 
     | 
    
         
            -
                end
         
     | 
| 
      
 317 
     | 
    
         
            +
                  filename = options.delete(:filename) || '(__ERB__)'
         
     | 
| 
      
 318 
     | 
    
         
            +
                  line = options.delete(:line) || 1
         
     | 
| 
      
 319 
     | 
    
         
            +
                  line -= 1 if instance.src =~ /^#coding:/
         
     | 
| 
       252 
320 
     | 
    
         | 
| 
       253 
     | 
    
         
            -
             
     | 
| 
       254 
     | 
    
         
            -
                   
     | 
| 
       255 
     | 
    
         
            -
                   
     | 
| 
       256 
     | 
    
         
            -
                   
     | 
| 
      
 321 
     | 
    
         
            +
                  render_binding = binding
         
     | 
| 
      
 322 
     | 
    
         
            +
                  eval locals_assigns.join("\n"), render_binding
         
     | 
| 
      
 323 
     | 
    
         
            +
                  eval instance.src, render_binding, filename, line
         
     | 
| 
      
 324 
     | 
    
         
            +
                  @_out_buf, result = original_out_buf, @_out_buf
         
     | 
| 
      
 325 
     | 
    
         
            +
                  result
         
     | 
| 
       257 
326 
     | 
    
         
             
                end
         
     | 
| 
       258 
327 
     | 
    
         | 
| 
       259 
     | 
    
         
            -
                def  
     | 
| 
       260 
     | 
    
         
            -
                   
     | 
| 
       261 
     | 
    
         
            -
                  engine.render
         
     | 
| 
      
 328 
     | 
    
         
            +
                def render_haml(data, options, locals, &block)
         
     | 
| 
      
 329 
     | 
    
         
            +
                  ::Haml::Engine.new(data, options).render(self, locals, &block)
         
     | 
| 
       262 
330 
     | 
    
         
             
                end
         
     | 
| 
       263 
331 
     | 
    
         | 
| 
       264 
     | 
    
         
            -
                def  
     | 
| 
       265 
     | 
    
         
            -
                   
     | 
| 
       266 
     | 
    
         
            -
                  options, template = template, nil if template.is_a?(Hash)
         
     | 
| 
       267 
     | 
    
         
            -
                  template = lambda { block } if template.nil?
         
     | 
| 
       268 
     | 
    
         
            -
                  render :builder, template, options
         
     | 
| 
      
 332 
     | 
    
         
            +
                def render_sass(data, options, locals, &block)
         
     | 
| 
      
 333 
     | 
    
         
            +
                  ::Sass::Engine.new(data, options).render
         
     | 
| 
       269 
334 
     | 
    
         
             
                end
         
     | 
| 
       270 
335 
     | 
    
         | 
| 
       271 
     | 
    
         
            -
                def render_builder( 
     | 
| 
       272 
     | 
    
         
            -
                   
     | 
| 
      
 336 
     | 
    
         
            +
                def render_builder(data, options, locals, &block)
         
     | 
| 
      
 337 
     | 
    
         
            +
                  options = { :indent => 2 }.merge(options)
         
     | 
| 
      
 338 
     | 
    
         
            +
                  filename = options.delete(:filename) || '<BUILDER>'
         
     | 
| 
      
 339 
     | 
    
         
            +
                  line = options.delete(:line) || 1
         
     | 
| 
      
 340 
     | 
    
         
            +
                  xml = ::Builder::XmlMarkup.new(options)
         
     | 
| 
       273 
341 
     | 
    
         
             
                  if data.respond_to?(:to_str)
         
     | 
| 
       274 
     | 
    
         
            -
                    eval data.to_str, binding,  
     | 
| 
      
 342 
     | 
    
         
            +
                    eval data.to_str, binding, filename, line
         
     | 
| 
       275 
343 
     | 
    
         
             
                  elsif data.kind_of?(Proc)
         
     | 
| 
       276 
344 
     | 
    
         
             
                    data.call(xml)
         
     | 
| 
       277 
345 
     | 
    
         
             
                  end
         
     | 
| 
       278 
346 
     | 
    
         
             
                  xml.target!
         
     | 
| 
       279 
347 
     | 
    
         
             
                end
         
     | 
| 
       280 
     | 
    
         
            -
             
     | 
| 
       281 
348 
     | 
    
         
             
              end
         
     | 
| 
       282 
349 
     | 
    
         | 
| 
      
 350 
     | 
    
         
            +
              # Base class for all Sinatra applications and middleware.
         
     | 
| 
       283 
351 
     | 
    
         
             
              class Base
         
     | 
| 
       284 
352 
     | 
    
         
             
                include Rack::Utils
         
     | 
| 
       285 
353 
     | 
    
         
             
                include Helpers
         
     | 
| 
         @@ -292,6 +360,7 @@ module Sinatra 
     | 
|
| 
       292 
360 
     | 
    
         
             
                  yield self if block_given?
         
     | 
| 
       293 
361 
     | 
    
         
             
                end
         
     | 
| 
       294 
362 
     | 
    
         | 
| 
      
 363 
     | 
    
         
            +
                # Rack call interface.
         
     | 
| 
       295 
364 
     | 
    
         
             
                def call(env)
         
     | 
| 
       296 
365 
     | 
    
         
             
                  dup.call!(env)
         
     | 
| 
       297 
366 
     | 
    
         
             
                end
         
     | 
| 
         @@ -302,34 +371,69 @@ module Sinatra 
     | 
|
| 
       302 
371 
     | 
    
         
             
                  @env      = env
         
     | 
| 
       303 
372 
     | 
    
         
             
                  @request  = Request.new(env)
         
     | 
| 
       304 
373 
     | 
    
         
             
                  @response = Response.new
         
     | 
| 
       305 
     | 
    
         
            -
                  @params   =  
     | 
| 
       306 
     | 
    
         
            -
             
     | 
| 
       307 
     | 
    
         
            -
                   
     | 
| 
      
 374 
     | 
    
         
            +
                  @params   = indifferent_params(@request.params)
         
     | 
| 
      
 375 
     | 
    
         
            +
             
     | 
| 
      
 376 
     | 
    
         
            +
                  invoke { dispatch! }
         
     | 
| 
      
 377 
     | 
    
         
            +
                  invoke { error_block!(response.status) }
         
     | 
| 
      
 378 
     | 
    
         
            +
             
     | 
| 
      
 379 
     | 
    
         
            +
                  status, header, body = @response.finish
         
     | 
| 
      
 380 
     | 
    
         
            +
             
     | 
| 
      
 381 
     | 
    
         
            +
                  # Never produce a body on HEAD requests. Do retain the Content-Length
         
     | 
| 
      
 382 
     | 
    
         
            +
                  # unless it's "0", in which case we assume it was calculated erroneously
         
     | 
| 
      
 383 
     | 
    
         
            +
                  # for a manual HEAD response and remove it entirely.
         
     | 
| 
      
 384 
     | 
    
         
            +
                  if @env['REQUEST_METHOD'] == 'HEAD'
         
     | 
| 
      
 385 
     | 
    
         
            +
                    body = []
         
     | 
| 
      
 386 
     | 
    
         
            +
                    header.delete('Content-Length') if header['Content-Length'] == '0'
         
     | 
| 
      
 387 
     | 
    
         
            +
                  end
         
     | 
| 
      
 388 
     | 
    
         
            +
             
     | 
| 
      
 389 
     | 
    
         
            +
                  [status, header, body]
         
     | 
| 
       308 
390 
     | 
    
         
             
                end
         
     | 
| 
       309 
391 
     | 
    
         | 
| 
      
 392 
     | 
    
         
            +
                # Access options defined with Base.set.
         
     | 
| 
       310 
393 
     | 
    
         
             
                def options
         
     | 
| 
       311 
394 
     | 
    
         
             
                  self.class
         
     | 
| 
       312 
395 
     | 
    
         
             
                end
         
     | 
| 
       313 
396 
     | 
    
         | 
| 
      
 397 
     | 
    
         
            +
                # Exit the current block, halts any further processing
         
     | 
| 
      
 398 
     | 
    
         
            +
                # of the request, and returns the specified response.
         
     | 
| 
       314 
399 
     | 
    
         
             
                def halt(*response)
         
     | 
| 
       315 
     | 
    
         
            -
                   
     | 
| 
      
 400 
     | 
    
         
            +
                  response = response.first if response.length == 1
         
     | 
| 
      
 401 
     | 
    
         
            +
                  throw :halt, response
         
     | 
| 
       316 
402 
     | 
    
         
             
                end
         
     | 
| 
       317 
403 
     | 
    
         | 
| 
      
 404 
     | 
    
         
            +
                # Pass control to the next matching route.
         
     | 
| 
      
 405 
     | 
    
         
            +
                # If there are no more matching routes, Sinatra will
         
     | 
| 
      
 406 
     | 
    
         
            +
                # return a 404 response.
         
     | 
| 
       318 
407 
     | 
    
         
             
                def pass
         
     | 
| 
       319 
408 
     | 
    
         
             
                  throw :pass
         
     | 
| 
       320 
409 
     | 
    
         
             
                end
         
     | 
| 
       321 
410 
     | 
    
         | 
| 
      
 411 
     | 
    
         
            +
                # Forward the request to the downstream app -- middleware only.
         
     | 
| 
      
 412 
     | 
    
         
            +
                def forward
         
     | 
| 
      
 413 
     | 
    
         
            +
                  fail "downstream app not set" unless @app.respond_to? :call
         
     | 
| 
      
 414 
     | 
    
         
            +
                  status, headers, body = @app.call(@request.env)
         
     | 
| 
      
 415 
     | 
    
         
            +
                  @response.status = status
         
     | 
| 
      
 416 
     | 
    
         
            +
                  @response.body = body
         
     | 
| 
      
 417 
     | 
    
         
            +
                  @response.headers.merge! headers
         
     | 
| 
      
 418 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 419 
     | 
    
         
            +
                end
         
     | 
| 
      
 420 
     | 
    
         
            +
             
     | 
| 
       322 
421 
     | 
    
         
             
              private
         
     | 
| 
       323 
     | 
    
         
            -
                 
     | 
| 
       324 
     | 
    
         
            -
             
     | 
| 
       325 
     | 
    
         
            -
                  if  
     | 
| 
       326 
     | 
    
         
            -
             
     | 
| 
       327 
     | 
    
         
            -
             
     | 
| 
       328 
     | 
    
         
            -
             
     | 
| 
       329 
     | 
    
         
            -
             
     | 
| 
       330 
     | 
    
         
            -
             
     | 
| 
       331 
     | 
    
         
            -
             
     | 
| 
       332 
     | 
    
         
            -
             
     | 
| 
      
 422 
     | 
    
         
            +
                # Run before filters defined on the class and all superclasses.
         
     | 
| 
      
 423 
     | 
    
         
            +
                def filter!(base=self.class)
         
     | 
| 
      
 424 
     | 
    
         
            +
                  filter!(base.superclass) if base.superclass.respond_to?(:filters)
         
     | 
| 
      
 425 
     | 
    
         
            +
                  base.filters.each { |block| instance_eval(&block) }
         
     | 
| 
      
 426 
     | 
    
         
            +
                end
         
     | 
| 
      
 427 
     | 
    
         
            +
             
     | 
| 
      
 428 
     | 
    
         
            +
                # Run routes defined on the class and all superclasses.
         
     | 
| 
      
 429 
     | 
    
         
            +
                def route!(base=self.class)
         
     | 
| 
      
 430 
     | 
    
         
            +
                  if routes = base.routes[@request.request_method]
         
     | 
| 
      
 431 
     | 
    
         
            +
                    original_params = @params
         
     | 
| 
      
 432 
     | 
    
         
            +
                    path            = unescape(@request.path_info)
         
     | 
| 
      
 433 
     | 
    
         
            +
             
     | 
| 
      
 434 
     | 
    
         
            +
                    routes.each do |pattern, keys, conditions, block|
         
     | 
| 
      
 435 
     | 
    
         
            +
                      if match = pattern.match(path)
         
     | 
| 
      
 436 
     | 
    
         
            +
                        values = match.captures.to_a
         
     | 
| 
       333 
437 
     | 
    
         
             
                        params =
         
     | 
| 
       334 
438 
     | 
    
         
             
                          if keys.any?
         
     | 
| 
       335 
439 
     | 
    
         
             
                            keys.zip(values).inject({}) do |hash,(k,v)|
         
     | 
| 
         @@ -345,28 +449,78 @@ module Sinatra 
     | 
|
| 
       345 
449 
     | 
    
         
             
                          else
         
     | 
| 
       346 
450 
     | 
    
         
             
                            {}
         
     | 
| 
       347 
451 
     | 
    
         
             
                          end
         
     | 
| 
       348 
     | 
    
         
            -
                        @params = original_params. 
     | 
| 
       349 
     | 
    
         
            -
                        @ 
     | 
| 
      
 452 
     | 
    
         
            +
                        @params = original_params.merge(params)
         
     | 
| 
      
 453 
     | 
    
         
            +
                        @block_params = values
         
     | 
| 
       350 
454 
     | 
    
         | 
| 
       351 
     | 
    
         
            -
                        catch(:pass)  
     | 
| 
      
 455 
     | 
    
         
            +
                        catch(:pass) do
         
     | 
| 
       352 
456 
     | 
    
         
             
                          conditions.each { |cond|
         
     | 
| 
       353 
457 
     | 
    
         
             
                            throw :pass if instance_eval(&cond) == false }
         
     | 
| 
       354 
     | 
    
         
            -
                           
     | 
| 
       355 
     | 
    
         
            -
                         
     | 
| 
      
 458 
     | 
    
         
            +
                          route_eval(&block)
         
     | 
| 
      
 459 
     | 
    
         
            +
                        end
         
     | 
| 
       356 
460 
     | 
    
         
             
                      end
         
     | 
| 
       357 
461 
     | 
    
         
             
                    end
         
     | 
| 
      
 462 
     | 
    
         
            +
             
     | 
| 
      
 463 
     | 
    
         
            +
                    @params = original_params
         
     | 
| 
      
 464 
     | 
    
         
            +
                  end
         
     | 
| 
      
 465 
     | 
    
         
            +
             
     | 
| 
      
 466 
     | 
    
         
            +
                  # Run routes defined in superclass.
         
     | 
| 
      
 467 
     | 
    
         
            +
                  if base.superclass.respond_to?(:routes)
         
     | 
| 
      
 468 
     | 
    
         
            +
                    route! base.superclass
         
     | 
| 
      
 469 
     | 
    
         
            +
                    return
         
     | 
| 
       358 
470 
     | 
    
         
             
                  end
         
     | 
| 
       359 
     | 
    
         
            -
             
     | 
| 
      
 471 
     | 
    
         
            +
             
     | 
| 
      
 472 
     | 
    
         
            +
                  route_missing
         
     | 
| 
       360 
473 
     | 
    
         
             
                end
         
     | 
| 
       361 
474 
     | 
    
         | 
| 
       362 
     | 
    
         
            -
                 
     | 
| 
       363 
     | 
    
         
            -
             
     | 
| 
       364 
     | 
    
         
            -
             
     | 
| 
       365 
     | 
    
         
            -
             
     | 
| 
       366 
     | 
    
         
            -
             
     | 
| 
       367 
     | 
    
         
            -
             
     | 
| 
       368 
     | 
    
         
            -
             
     | 
| 
       369 
     | 
    
         
            -
             
     | 
| 
      
 475 
     | 
    
         
            +
                # Run a route block and throw :halt with the result.
         
     | 
| 
      
 476 
     | 
    
         
            +
                def route_eval(&block)
         
     | 
| 
      
 477 
     | 
    
         
            +
                  throw :halt, instance_eval(&block)
         
     | 
| 
      
 478 
     | 
    
         
            +
                end
         
     | 
| 
      
 479 
     | 
    
         
            +
             
     | 
| 
      
 480 
     | 
    
         
            +
                # No matching route was found or all routes passed. The default
         
     | 
| 
      
 481 
     | 
    
         
            +
                # implementation is to forward the request downstream when running
         
     | 
| 
      
 482 
     | 
    
         
            +
                # as middleware (@app is non-nil); when no downstream app is set, raise
         
     | 
| 
      
 483 
     | 
    
         
            +
                # a NotFound exception. Subclasses can override this method to perform
         
     | 
| 
      
 484 
     | 
    
         
            +
                # custom route miss logic.
         
     | 
| 
      
 485 
     | 
    
         
            +
                def route_missing
         
     | 
| 
      
 486 
     | 
    
         
            +
                  if @app
         
     | 
| 
      
 487 
     | 
    
         
            +
                    forward
         
     | 
| 
      
 488 
     | 
    
         
            +
                  else
         
     | 
| 
      
 489 
     | 
    
         
            +
                    raise NotFound
         
     | 
| 
      
 490 
     | 
    
         
            +
                  end
         
     | 
| 
      
 491 
     | 
    
         
            +
                end
         
     | 
| 
      
 492 
     | 
    
         
            +
             
     | 
| 
      
 493 
     | 
    
         
            +
                # Attempt to serve static files from public directory. Throws :halt when
         
     | 
| 
      
 494 
     | 
    
         
            +
                # a matching file is found, returns nil otherwise.
         
     | 
| 
      
 495 
     | 
    
         
            +
                def static!
         
     | 
| 
      
 496 
     | 
    
         
            +
                  return if (public_dir = options.public).nil?
         
     | 
| 
      
 497 
     | 
    
         
            +
                  public_dir = File.expand_path(public_dir)
         
     | 
| 
      
 498 
     | 
    
         
            +
             
     | 
| 
      
 499 
     | 
    
         
            +
                  path = File.expand_path(public_dir + unescape(request.path_info))
         
     | 
| 
      
 500 
     | 
    
         
            +
                  return if path[0, public_dir.length] != public_dir
         
     | 
| 
      
 501 
     | 
    
         
            +
                  return unless File.file?(path)
         
     | 
| 
      
 502 
     | 
    
         
            +
             
     | 
| 
      
 503 
     | 
    
         
            +
                  send_file path, :disposition => nil
         
     | 
| 
      
 504 
     | 
    
         
            +
                end
         
     | 
| 
      
 505 
     | 
    
         
            +
             
     | 
| 
      
 506 
     | 
    
         
            +
                # Enable string or symbol key access to the nested params hash.
         
     | 
| 
      
 507 
     | 
    
         
            +
                def indifferent_params(params)
         
     | 
| 
      
 508 
     | 
    
         
            +
                  params = indifferent_hash.merge(params)
         
     | 
| 
      
 509 
     | 
    
         
            +
                  params.each do |key, value|
         
     | 
| 
      
 510 
     | 
    
         
            +
                    next unless value.is_a?(Hash)
         
     | 
| 
      
 511 
     | 
    
         
            +
                    params[key] = indifferent_params(value)
         
     | 
| 
      
 512 
     | 
    
         
            +
                  end
         
     | 
| 
      
 513 
     | 
    
         
            +
                end
         
     | 
| 
      
 514 
     | 
    
         
            +
             
     | 
| 
      
 515 
     | 
    
         
            +
                def indifferent_hash
         
     | 
| 
      
 516 
     | 
    
         
            +
                  Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
         
     | 
| 
      
 517 
     | 
    
         
            +
                end
         
     | 
| 
      
 518 
     | 
    
         
            +
             
     | 
| 
      
 519 
     | 
    
         
            +
                # Run the block with 'throw :halt' support and apply result to the response.
         
     | 
| 
      
 520 
     | 
    
         
            +
                def invoke(&block)
         
     | 
| 
      
 521 
     | 
    
         
            +
                  res = catch(:halt) { instance_eval(&block) }
         
     | 
| 
      
 522 
     | 
    
         
            +
                  return if res.nil?
         
     | 
| 
      
 523 
     | 
    
         
            +
             
     | 
| 
       370 
524 
     | 
    
         
             
                  case
         
     | 
| 
       371 
525 
     | 
    
         
             
                  when res.respond_to?(:to_str)
         
     | 
| 
       372 
526 
     | 
    
         
             
                    @response.body = [res]
         
     | 
| 
         @@ -379,7 +533,7 @@ module Sinatra 
     | 
|
| 
       379 
533 
     | 
    
         
             
                        headers.each { |k, v| @response.headers[k] = v } if headers
         
     | 
| 
       380 
534 
     | 
    
         
             
                      elsif res.length == 2
         
     | 
| 
       381 
535 
     | 
    
         
             
                        @response.status = res.first
         
     | 
| 
       382 
     | 
    
         
            -
                        @response.body 
     | 
| 
      
 536 
     | 
    
         
            +
                        @response.body   = res.last
         
     | 
| 
       383 
537 
     | 
    
         
             
                      else
         
     | 
| 
       384 
538 
     | 
    
         
             
                        raise TypeError, "#{res.inspect} not supported"
         
     | 
| 
       385 
539 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -390,57 +544,113 @@ module Sinatra 
     | 
|
| 
       390 
544 
     | 
    
         
             
                    @response.body = res
         
     | 
| 
       391 
545 
     | 
    
         
             
                  when (100...599) === res
         
     | 
| 
       392 
546 
     | 
    
         
             
                    @response.status = res
         
     | 
| 
       393 
     | 
    
         
            -
                  when res.nil?
         
     | 
| 
       394 
     | 
    
         
            -
                    @response.body = []
         
     | 
| 
       395 
547 
     | 
    
         
             
                  end
         
     | 
| 
      
 548 
     | 
    
         
            +
             
     | 
| 
       396 
549 
     | 
    
         
             
                  res
         
     | 
| 
       397 
550 
     | 
    
         
             
                end
         
     | 
| 
       398 
551 
     | 
    
         | 
| 
       399 
     | 
    
         
            -
                 
     | 
| 
       400 
     | 
    
         
            -
             
     | 
| 
       401 
     | 
    
         
            -
                   
     | 
| 
      
 552 
     | 
    
         
            +
                # Dispatch a request with error handling.
         
     | 
| 
      
 553 
     | 
    
         
            +
                def dispatch!
         
     | 
| 
      
 554 
     | 
    
         
            +
                  filter!
         
     | 
| 
      
 555 
     | 
    
         
            +
                  static! if options.static? && (request.get? || request.head?)
         
     | 
| 
      
 556 
     | 
    
         
            +
                  route!
         
     | 
| 
       402 
557 
     | 
    
         
             
                rescue NotFound => boom
         
     | 
| 
       403 
     | 
    
         
            -
                   
     | 
| 
       404 
     | 
    
         
            -
                  @response.status = 404
         
     | 
| 
       405 
     | 
    
         
            -
                  @response.body = ['<h1>Not Found</h1>']
         
     | 
| 
       406 
     | 
    
         
            -
                  handler = errmap[boom.class] || errmap[NotFound]
         
     | 
| 
       407 
     | 
    
         
            -
                  invoke handler unless handler.nil?
         
     | 
| 
      
 558 
     | 
    
         
            +
                  handle_not_found!(boom)
         
     | 
| 
       408 
559 
     | 
    
         
             
                rescue ::Exception => boom
         
     | 
| 
      
 560 
     | 
    
         
            +
                  handle_exception!(boom)
         
     | 
| 
      
 561 
     | 
    
         
            +
                end
         
     | 
| 
      
 562 
     | 
    
         
            +
             
     | 
| 
      
 563 
     | 
    
         
            +
                def handle_not_found!(boom)
         
     | 
| 
       409 
564 
     | 
    
         
             
                  @env['sinatra.error'] = boom
         
     | 
| 
      
 565 
     | 
    
         
            +
                  @response.status      = 404
         
     | 
| 
      
 566 
     | 
    
         
            +
                  @response.body        = ['<h1>Not Found</h1>']
         
     | 
| 
      
 567 
     | 
    
         
            +
                  error_block! boom.class, NotFound
         
     | 
| 
      
 568 
     | 
    
         
            +
                end
         
     | 
| 
       410 
569 
     | 
    
         | 
| 
       411 
     | 
    
         
            -
             
     | 
| 
       412 
     | 
    
         
            -
             
     | 
| 
       413 
     | 
    
         
            -
             
     | 
| 
       414 
     | 
    
         
            -
                   
     | 
| 
      
 570 
     | 
    
         
            +
                def handle_exception!(boom)
         
     | 
| 
      
 571 
     | 
    
         
            +
                  @env['sinatra.error'] = boom
         
     | 
| 
      
 572 
     | 
    
         
            +
             
     | 
| 
      
 573 
     | 
    
         
            +
                  dump_errors!(boom) if options.dump_errors?
         
     | 
| 
      
 574 
     | 
    
         
            +
                  raise boom         if options.raise_errors? || options.show_exceptions?
         
     | 
| 
       415 
575 
     | 
    
         | 
| 
       416 
     | 
    
         
            -
                  raise boom if options.raise_errors?
         
     | 
| 
       417 
576 
     | 
    
         
             
                  @response.status = 500
         
     | 
| 
       418 
     | 
    
         
            -
                   
     | 
| 
       419 
     | 
    
         
            -
                 
     | 
| 
       420 
     | 
    
         
            -
             
     | 
| 
       421 
     | 
    
         
            -
             
     | 
| 
      
 577 
     | 
    
         
            +
                  error_block! boom.class, Exception
         
     | 
| 
      
 578 
     | 
    
         
            +
                end
         
     | 
| 
      
 579 
     | 
    
         
            +
             
     | 
| 
      
 580 
     | 
    
         
            +
                # Find an custom error block for the key(s) specified.
         
     | 
| 
      
 581 
     | 
    
         
            +
                def error_block!(*keys)
         
     | 
| 
      
 582 
     | 
    
         
            +
                  keys.each do |key|
         
     | 
| 
      
 583 
     | 
    
         
            +
                    base = self.class
         
     | 
| 
      
 584 
     | 
    
         
            +
                    while base.respond_to?(:errors)
         
     | 
| 
      
 585 
     | 
    
         
            +
                      if block = base.errors[key]
         
     | 
| 
      
 586 
     | 
    
         
            +
                        # found a handler, eval and return result
         
     | 
| 
      
 587 
     | 
    
         
            +
                        res = instance_eval(&block)
         
     | 
| 
      
 588 
     | 
    
         
            +
                        return res
         
     | 
| 
      
 589 
     | 
    
         
            +
                      else
         
     | 
| 
      
 590 
     | 
    
         
            +
                        base = base.superclass
         
     | 
| 
      
 591 
     | 
    
         
            +
                      end
         
     | 
| 
      
 592 
     | 
    
         
            +
                    end
         
     | 
| 
       422 
593 
     | 
    
         
             
                  end
         
     | 
| 
      
 594 
     | 
    
         
            +
                  nil
         
     | 
| 
       423 
595 
     | 
    
         
             
                end
         
     | 
| 
       424 
596 
     | 
    
         | 
| 
       425 
     | 
    
         
            -
                 
     | 
| 
       426 
     | 
    
         
            -
             
     | 
| 
       427 
     | 
    
         
            -
             
     | 
| 
       428 
     | 
    
         
            -
             
     | 
| 
       429 
     | 
    
         
            -
             
     | 
| 
       430 
     | 
    
         
            -
                 
     | 
| 
       431 
     | 
    
         
            -
             
     | 
| 
      
 597 
     | 
    
         
            +
                def dump_errors!(boom)
         
     | 
| 
      
 598 
     | 
    
         
            +
                  backtrace = clean_backtrace(boom.backtrace)
         
     | 
| 
      
 599 
     | 
    
         
            +
                  msg = ["#{boom.class} - #{boom.message}:",
         
     | 
| 
      
 600 
     | 
    
         
            +
                    *backtrace].join("\n ")
         
     | 
| 
      
 601 
     | 
    
         
            +
                  @env['rack.errors'].write(msg)
         
     | 
| 
      
 602 
     | 
    
         
            +
                end
         
     | 
| 
      
 603 
     | 
    
         
            +
             
     | 
| 
      
 604 
     | 
    
         
            +
                def clean_backtrace(trace)
         
     | 
| 
      
 605 
     | 
    
         
            +
                  return trace unless options.clean_trace?
         
     | 
| 
      
 606 
     | 
    
         
            +
             
     | 
| 
      
 607 
     | 
    
         
            +
                  trace.reject { |line|
         
     | 
| 
      
 608 
     | 
    
         
            +
                    line =~ /lib\/sinatra.*\.rb/ ||
         
     | 
| 
      
 609 
     | 
    
         
            +
                      (defined?(Gem) && line.include?(Gem.dir))
         
     | 
| 
      
 610 
     | 
    
         
            +
                  }.map! { |line| line.gsub(/^\.\//, '') }
         
     | 
| 
      
 611 
     | 
    
         
            +
                end
         
     | 
| 
       432 
612 
     | 
    
         | 
| 
       433 
613 
     | 
    
         
             
                class << self
         
     | 
| 
       434 
     | 
    
         
            -
                   
     | 
| 
       435 
     | 
    
         
            -
             
     | 
| 
      
 614 
     | 
    
         
            +
                  attr_reader :routes, :filters, :templates, :errors
         
     | 
| 
      
 615 
     | 
    
         
            +
             
     | 
| 
      
 616 
     | 
    
         
            +
                  def reset!
         
     | 
| 
      
 617 
     | 
    
         
            +
                    @conditions = []
         
     | 
| 
      
 618 
     | 
    
         
            +
                    @routes     = {}
         
     | 
| 
      
 619 
     | 
    
         
            +
                    @filters    = []
         
     | 
| 
      
 620 
     | 
    
         
            +
                    @templates  = {}
         
     | 
| 
      
 621 
     | 
    
         
            +
                    @errors     = {}
         
     | 
| 
      
 622 
     | 
    
         
            +
                    @middleware = []
         
     | 
| 
      
 623 
     | 
    
         
            +
                    @prototype  = nil
         
     | 
| 
      
 624 
     | 
    
         
            +
                    @extensions = []
         
     | 
| 
      
 625 
     | 
    
         
            +
                  end
         
     | 
| 
       436 
626 
     | 
    
         | 
| 
      
 627 
     | 
    
         
            +
                  # Extension modules registered on this class and all superclasses.
         
     | 
| 
      
 628 
     | 
    
         
            +
                  def extensions
         
     | 
| 
      
 629 
     | 
    
         
            +
                    if superclass.respond_to?(:extensions)
         
     | 
| 
      
 630 
     | 
    
         
            +
                      (@extensions + superclass.extensions).uniq
         
     | 
| 
      
 631 
     | 
    
         
            +
                    else
         
     | 
| 
      
 632 
     | 
    
         
            +
                      @extensions
         
     | 
| 
      
 633 
     | 
    
         
            +
                    end
         
     | 
| 
      
 634 
     | 
    
         
            +
                  end
         
     | 
| 
      
 635 
     | 
    
         
            +
             
     | 
| 
      
 636 
     | 
    
         
            +
                  # Middleware used in this class and all superclasses.
         
     | 
| 
      
 637 
     | 
    
         
            +
                  def middleware
         
     | 
| 
      
 638 
     | 
    
         
            +
                    if superclass.respond_to?(:middleware)
         
     | 
| 
      
 639 
     | 
    
         
            +
                      superclass.middleware + @middleware
         
     | 
| 
      
 640 
     | 
    
         
            +
                    else
         
     | 
| 
      
 641 
     | 
    
         
            +
                      @middleware
         
     | 
| 
      
 642 
     | 
    
         
            +
                    end
         
     | 
| 
      
 643 
     | 
    
         
            +
                  end
         
     | 
| 
      
 644 
     | 
    
         
            +
             
     | 
| 
      
 645 
     | 
    
         
            +
                  # Sets an option to the given value.  If the value is a proc,
         
     | 
| 
      
 646 
     | 
    
         
            +
                  # the proc will be called every time the option is accessed.
         
     | 
| 
       437 
647 
     | 
    
         
             
                  def set(option, value=self)
         
     | 
| 
       438 
648 
     | 
    
         
             
                    if value.kind_of?(Proc)
         
     | 
| 
       439 
649 
     | 
    
         
             
                      metadef(option, &value)
         
     | 
| 
       440 
650 
     | 
    
         
             
                      metadef("#{option}?") { !!__send__(option) }
         
     | 
| 
       441 
651 
     | 
    
         
             
                      metadef("#{option}=") { |val| set(option, Proc.new{val}) }
         
     | 
| 
       442 
652 
     | 
    
         
             
                    elsif value == self && option.respond_to?(:to_hash)
         
     | 
| 
       443 
     | 
    
         
            -
                      option.to_hash.each( 
     | 
| 
      
 653 
     | 
    
         
            +
                      option.to_hash.each { |k,v| set(k, v) }
         
     | 
| 
       444 
654 
     | 
    
         
             
                    elsif respond_to?("#{option}=")
         
     | 
| 
       445 
655 
     | 
    
         
             
                      __send__ "#{option}=", value
         
     | 
| 
       446 
656 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -449,14 +659,19 @@ module Sinatra 
     | 
|
| 
       449 
659 
     | 
    
         
             
                    self
         
     | 
| 
       450 
660 
     | 
    
         
             
                  end
         
     | 
| 
       451 
661 
     | 
    
         | 
| 
      
 662 
     | 
    
         
            +
                  # Same as calling `set :option, true` for each of the given options.
         
     | 
| 
       452 
663 
     | 
    
         
             
                  def enable(*opts)
         
     | 
| 
       453 
664 
     | 
    
         
             
                    opts.each { |key| set(key, true) }
         
     | 
| 
       454 
665 
     | 
    
         
             
                  end
         
     | 
| 
       455 
666 
     | 
    
         | 
| 
      
 667 
     | 
    
         
            +
                  # Same as calling `set :option, false` for each of the given options.
         
     | 
| 
       456 
668 
     | 
    
         
             
                  def disable(*opts)
         
     | 
| 
       457 
669 
     | 
    
         
             
                    opts.each { |key| set(key, false) }
         
     | 
| 
       458 
670 
     | 
    
         
             
                  end
         
     | 
| 
       459 
671 
     | 
    
         | 
| 
      
 672 
     | 
    
         
            +
                  # Define a custom error handler. Optionally takes either an Exception
         
     | 
| 
      
 673 
     | 
    
         
            +
                  # class, or an HTTP status code to specify which errors should be
         
     | 
| 
      
 674 
     | 
    
         
            +
                  # handled.
         
     | 
| 
       460 
675 
     | 
    
         
             
                  def error(codes=Exception, &block)
         
     | 
| 
       461 
676 
     | 
    
         
             
                    if codes.respond_to? :each
         
     | 
| 
       462 
677 
     | 
    
         
             
                      codes.each { |err| error(err, &block) }
         
     | 
| 
         @@ -465,28 +680,43 @@ module Sinatra 
     | 
|
| 
       465 
680 
     | 
    
         
             
                    end
         
     | 
| 
       466 
681 
     | 
    
         
             
                  end
         
     | 
| 
       467 
682 
     | 
    
         | 
| 
      
 683 
     | 
    
         
            +
                  # Sugar for `error(404) { ... }`
         
     | 
| 
       468 
684 
     | 
    
         
             
                  def not_found(&block)
         
     | 
| 
       469 
685 
     | 
    
         
             
                    error 404, &block
         
     | 
| 
       470 
686 
     | 
    
         
             
                  end
         
     | 
| 
       471 
687 
     | 
    
         | 
| 
      
 688 
     | 
    
         
            +
                  # Define a named template. The block must return the template source.
         
     | 
| 
       472 
689 
     | 
    
         
             
                  def template(name, &block)
         
     | 
| 
       473 
     | 
    
         
            -
                     
     | 
| 
      
 690 
     | 
    
         
            +
                    filename, line = caller_locations.first
         
     | 
| 
      
 691 
     | 
    
         
            +
                    templates[name] = { :filename => filename, :line => line, :template => block }
         
     | 
| 
       474 
692 
     | 
    
         
             
                  end
         
     | 
| 
       475 
693 
     | 
    
         | 
| 
      
 694 
     | 
    
         
            +
                  # Define the layout template. The block must return the template source.
         
     | 
| 
       476 
695 
     | 
    
         
             
                  def layout(name=:layout, &block)
         
     | 
| 
       477 
696 
     | 
    
         
             
                    template name, &block
         
     | 
| 
       478 
697 
     | 
    
         
             
                  end
         
     | 
| 
       479 
698 
     | 
    
         | 
| 
       480 
     | 
    
         
            -
                   
     | 
| 
       481 
     | 
    
         
            -
             
     | 
| 
       482 
     | 
    
         
            -
             
     | 
| 
       483 
     | 
    
         
            -
                    file  
     | 
| 
       484 
     | 
    
         
            -
             
     | 
| 
      
 699 
     | 
    
         
            +
                  # Load embeded templates from the file; uses the caller's __FILE__
         
     | 
| 
      
 700 
     | 
    
         
            +
                  # when no file is specified.
         
     | 
| 
      
 701 
     | 
    
         
            +
                  def use_in_file_templates!(file=nil)
         
     | 
| 
      
 702 
     | 
    
         
            +
                    file ||= caller_files.first
         
     | 
| 
      
 703 
     | 
    
         
            +
             
     | 
| 
      
 704 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 705 
     | 
    
         
            +
                      app, data =
         
     | 
| 
      
 706 
     | 
    
         
            +
                        ::IO.read(file).split(/^__END__$/, 2)
         
     | 
| 
      
 707 
     | 
    
         
            +
                    rescue Errno::ENOENT
         
     | 
| 
      
 708 
     | 
    
         
            +
                      app, data = nil
         
     | 
| 
      
 709 
     | 
    
         
            +
                    end
         
     | 
| 
      
 710 
     | 
    
         
            +
             
     | 
| 
      
 711 
     | 
    
         
            +
                    if data
         
     | 
| 
       485 
712 
     | 
    
         
             
                      data.gsub!(/\r\n/, "\n")
         
     | 
| 
      
 713 
     | 
    
         
            +
                      lines = app.count("\n") + 1
         
     | 
| 
       486 
714 
     | 
    
         
             
                      template = nil
         
     | 
| 
       487 
715 
     | 
    
         
             
                      data.each_line do |line|
         
     | 
| 
      
 716 
     | 
    
         
            +
                        lines += 1
         
     | 
| 
       488 
717 
     | 
    
         
             
                        if line =~ /^@@\s*(.*)/
         
     | 
| 
       489 
     | 
    
         
            -
                          template =  
     | 
| 
      
 718 
     | 
    
         
            +
                          template = ''
         
     | 
| 
      
 719 
     | 
    
         
            +
                          templates[$1.to_sym] = { :filename => file, :line => lines, :template => template }
         
     | 
| 
       490 
720 
     | 
    
         
             
                        elsif template
         
     | 
| 
       491 
721 
     | 
    
         
             
                          template << line
         
     | 
| 
       492 
722 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -501,14 +731,20 @@ module Sinatra 
     | 
|
| 
       501 
731 
     | 
    
         
             
                    Rack::Mime.mime_type(type, nil)
         
     | 
| 
       502 
732 
     | 
    
         
             
                  end
         
     | 
| 
       503 
733 
     | 
    
         | 
| 
      
 734 
     | 
    
         
            +
                  # Define a before filter. Filters are run before all requests
         
     | 
| 
      
 735 
     | 
    
         
            +
                  # within the same context as route handlers and may access/modify the
         
     | 
| 
      
 736 
     | 
    
         
            +
                  # request and response.
         
     | 
| 
       504 
737 
     | 
    
         
             
                  def before(&block)
         
     | 
| 
       505 
738 
     | 
    
         
             
                    @filters << block
         
     | 
| 
       506 
739 
     | 
    
         
             
                  end
         
     | 
| 
       507 
740 
     | 
    
         | 
| 
      
 741 
     | 
    
         
            +
                  # Add a route condition. The route is considered non-matching when the
         
     | 
| 
      
 742 
     | 
    
         
            +
                  # block returns false.
         
     | 
| 
       508 
743 
     | 
    
         
             
                  def condition(&block)
         
     | 
| 
       509 
744 
     | 
    
         
             
                    @conditions << block
         
     | 
| 
       510 
745 
     | 
    
         
             
                  end
         
     | 
| 
       511 
746 
     | 
    
         | 
| 
      
 747 
     | 
    
         
            +
               private
         
     | 
| 
       512 
748 
     | 
    
         
             
                  def host_name(pattern)
         
     | 
| 
       513 
749 
     | 
    
         
             
                    condition { pattern === request.host }
         
     | 
| 
       514 
750 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -523,8 +759,9 @@ module Sinatra 
     | 
|
| 
       523 
759 
     | 
    
         
             
                      end
         
     | 
| 
       524 
760 
     | 
    
         
             
                    }
         
     | 
| 
       525 
761 
     | 
    
         
             
                  end
         
     | 
| 
      
 762 
     | 
    
         
            +
                  alias_method :agent, :user_agent
         
     | 
| 
       526 
763 
     | 
    
         | 
| 
       527 
     | 
    
         
            -
                  def  
     | 
| 
      
 764 
     | 
    
         
            +
                  def provides(*types)
         
     | 
| 
       528 
765 
     | 
    
         
             
                    types = [types] unless types.kind_of? Array
         
     | 
| 
       529 
766 
     | 
    
         
             
                    types.map!{|t| media_type(t)}
         
     | 
| 
       530 
767 
     | 
    
         | 
| 
         @@ -539,52 +776,72 @@ module Sinatra 
     | 
|
| 
       539 
776 
     | 
    
         
             
                    }
         
     | 
| 
       540 
777 
     | 
    
         
             
                  end
         
     | 
| 
       541 
778 
     | 
    
         | 
| 
      
 779 
     | 
    
         
            +
                public
         
     | 
| 
      
 780 
     | 
    
         
            +
                  # Defining a `GET` handler also automatically defines
         
     | 
| 
      
 781 
     | 
    
         
            +
                  # a `HEAD` handler.
         
     | 
| 
       542 
782 
     | 
    
         
             
                  def get(path, opts={}, &block)
         
     | 
| 
       543 
783 
     | 
    
         
             
                    conditions = @conditions.dup
         
     | 
| 
       544 
     | 
    
         
            -
                     
     | 
| 
      
 784 
     | 
    
         
            +
                    route('GET', path, opts, &block)
         
     | 
| 
       545 
785 
     | 
    
         | 
| 
       546 
786 
     | 
    
         
             
                    @conditions = conditions
         
     | 
| 
       547 
     | 
    
         
            -
                     
     | 
| 
      
 787 
     | 
    
         
            +
                    route('HEAD', path, opts, &block)
         
     | 
| 
       548 
788 
     | 
    
         
             
                  end
         
     | 
| 
       549 
789 
     | 
    
         | 
| 
       550 
     | 
    
         
            -
                  def put(path, opts={}, &bk); 
     | 
| 
       551 
     | 
    
         
            -
                  def post(path, opts={}, &bk); 
     | 
| 
       552 
     | 
    
         
            -
                  def delete(path, opts={}, &bk); route 'DELETE', path, opts, &bk 
     | 
| 
       553 
     | 
    
         
            -
                  def head(path, opts={}, &bk); 
     | 
| 
      
 790 
     | 
    
         
            +
                  def put(path, opts={}, &bk);    route 'PUT',    path, opts, &bk end
         
     | 
| 
      
 791 
     | 
    
         
            +
                  def post(path, opts={}, &bk);   route 'POST',   path, opts, &bk end
         
     | 
| 
      
 792 
     | 
    
         
            +
                  def delete(path, opts={}, &bk); route 'DELETE', path, opts, &bk end
         
     | 
| 
      
 793 
     | 
    
         
            +
                  def head(path, opts={}, &bk);   route 'HEAD',   path, opts, &bk end
         
     | 
| 
       554 
794 
     | 
    
         | 
| 
       555 
795 
     | 
    
         
             
                private
         
     | 
| 
       556 
     | 
    
         
            -
                  def route( 
     | 
| 
       557 
     | 
    
         
            -
                     
     | 
| 
       558 
     | 
    
         
            -
                     
     | 
| 
       559 
     | 
    
         
            -
             
     | 
| 
      
 796 
     | 
    
         
            +
                  def route(verb, path, options={}, &block)
         
     | 
| 
      
 797 
     | 
    
         
            +
                    # Because of self.options.host
         
     | 
| 
      
 798 
     | 
    
         
            +
                    host_name(options.delete(:host)) if options.key?(:host)
         
     | 
| 
      
 799 
     | 
    
         
            +
             
     | 
| 
      
 800 
     | 
    
         
            +
                    options.each {|option, args| send(option, *args)}
         
     | 
| 
       560 
801 
     | 
    
         | 
| 
       561 
802 
     | 
    
         
             
                    pattern, keys = compile(path)
         
     | 
| 
       562 
803 
     | 
    
         
             
                    conditions, @conditions = @conditions, []
         
     | 
| 
       563 
     | 
    
         
            -
                    method_name = "route { #{method} #{path} }"
         
     | 
| 
       564 
     | 
    
         
            -
                    nmethods = instance_methods.grep(rx = /#{Regexp.escape(method_name)}/).size
         
     | 
| 
       565 
     | 
    
         
            -
                    method_name += " [#{nmethods}]"
         
     | 
| 
       566 
804 
     | 
    
         | 
| 
       567 
     | 
    
         
            -
                    define_method 
     | 
| 
      
 805 
     | 
    
         
            +
                    define_method "#{verb} #{path}", &block
         
     | 
| 
      
 806 
     | 
    
         
            +
                    unbound_method = instance_method("#{verb} #{path}")
         
     | 
| 
      
 807 
     | 
    
         
            +
                    block =
         
     | 
| 
      
 808 
     | 
    
         
            +
                      if block.arity != 0
         
     | 
| 
      
 809 
     | 
    
         
            +
                        lambda { unbound_method.bind(self).call(*@block_params) }
         
     | 
| 
      
 810 
     | 
    
         
            +
                      else
         
     | 
| 
      
 811 
     | 
    
         
            +
                        lambda { unbound_method.bind(self).call }
         
     | 
| 
      
 812 
     | 
    
         
            +
                      end
         
     | 
| 
      
 813 
     | 
    
         
            +
             
     | 
| 
      
 814 
     | 
    
         
            +
                    invoke_hook(:route_added, verb, path, block)
         
     | 
| 
      
 815 
     | 
    
         
            +
             
     | 
| 
      
 816 
     | 
    
         
            +
                    (@routes[verb] ||= []).
         
     | 
| 
      
 817 
     | 
    
         
            +
                      push([pattern, keys, conditions, block]).last
         
     | 
| 
      
 818 
     | 
    
         
            +
                  end
         
     | 
| 
       568 
819 
     | 
    
         | 
| 
       569 
     | 
    
         
            -
             
     | 
| 
       570 
     | 
    
         
            -
             
     | 
| 
      
 820 
     | 
    
         
            +
                  def invoke_hook(name, *args)
         
     | 
| 
      
 821 
     | 
    
         
            +
                    extensions.each { |e| e.send(name, *args) if e.respond_to?(name) }
         
     | 
| 
       571 
822 
     | 
    
         
             
                  end
         
     | 
| 
       572 
823 
     | 
    
         | 
| 
       573 
824 
     | 
    
         
             
                  def compile(path)
         
     | 
| 
       574 
825 
     | 
    
         
             
                    keys = []
         
     | 
| 
       575 
826 
     | 
    
         
             
                    if path.respond_to? :to_str
         
     | 
| 
      
 827 
     | 
    
         
            +
                      special_chars = %w{. + ( )}
         
     | 
| 
       576 
828 
     | 
    
         
             
                      pattern =
         
     | 
| 
       577 
     | 
    
         
            -
                         
     | 
| 
       578 
     | 
    
         
            -
                           
     | 
| 
      
 829 
     | 
    
         
            +
                        path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
         
     | 
| 
      
 830 
     | 
    
         
            +
                          case match
         
     | 
| 
      
 831 
     | 
    
         
            +
                          when "*"
         
     | 
| 
       579 
832 
     | 
    
         
             
                            keys << 'splat'
         
     | 
| 
       580 
833 
     | 
    
         
             
                            "(.*?)"
         
     | 
| 
      
 834 
     | 
    
         
            +
                          when *special_chars
         
     | 
| 
      
 835 
     | 
    
         
            +
                            Regexp.escape(match)
         
     | 
| 
       581 
836 
     | 
    
         
             
                          else
         
     | 
| 
       582 
837 
     | 
    
         
             
                            keys << $2[1..-1]
         
     | 
| 
       583 
     | 
    
         
            -
                            "([ 
     | 
| 
      
 838 
     | 
    
         
            +
                            "([^/?&#]+)"
         
     | 
| 
       584 
839 
     | 
    
         
             
                          end
         
     | 
| 
       585 
840 
     | 
    
         
             
                        end
         
     | 
| 
       586 
841 
     | 
    
         
             
                      [/^#{pattern}$/, keys]
         
     | 
| 
       587 
     | 
    
         
            -
                    elsif path.respond_to?  
     | 
| 
      
 842 
     | 
    
         
            +
                    elsif path.respond_to?(:keys) && path.respond_to?(:match)
         
     | 
| 
      
 843 
     | 
    
         
            +
                      [path, path.keys]
         
     | 
| 
      
 844 
     | 
    
         
            +
                    elsif path.respond_to? :match
         
     | 
| 
       588 
845 
     | 
    
         
             
                      [path, keys]
         
     | 
| 
       589 
846 
     | 
    
         
             
                    else
         
     | 
| 
       590 
847 
     | 
    
         
             
                      raise TypeError, path
         
     | 
| 
         @@ -592,70 +849,106 @@ module Sinatra 
     | 
|
| 
       592 
849 
     | 
    
         
             
                  end
         
     | 
| 
       593 
850 
     | 
    
         | 
| 
       594 
851 
     | 
    
         
             
                public
         
     | 
| 
       595 
     | 
    
         
            -
                   
     | 
| 
       596 
     | 
    
         
            -
                   
     | 
| 
       597 
     | 
    
         
            -
                  def  
     | 
| 
      
 852 
     | 
    
         
            +
                  # Makes the methods defined in the block and in the Modules given
         
     | 
| 
      
 853 
     | 
    
         
            +
                  # in `extensions` available to the handlers and templates
         
     | 
| 
      
 854 
     | 
    
         
            +
                  def helpers(*extensions, &block)
         
     | 
| 
      
 855 
     | 
    
         
            +
                    class_eval(&block)  if block_given?
         
     | 
| 
      
 856 
     | 
    
         
            +
                    include(*extensions) if extensions.any?
         
     | 
| 
      
 857 
     | 
    
         
            +
                  end
         
     | 
| 
      
 858 
     | 
    
         
            +
             
     | 
| 
      
 859 
     | 
    
         
            +
                  def register(*extensions, &block)
         
     | 
| 
      
 860 
     | 
    
         
            +
                    extensions << Module.new(&block) if block_given?
         
     | 
| 
      
 861 
     | 
    
         
            +
                    @extensions += extensions
         
     | 
| 
      
 862 
     | 
    
         
            +
                    extensions.each do |extension|
         
     | 
| 
      
 863 
     | 
    
         
            +
                      extend extension
         
     | 
| 
      
 864 
     | 
    
         
            +
                      extension.registered(self) if extension.respond_to?(:registered)
         
     | 
| 
      
 865 
     | 
    
         
            +
                    end
         
     | 
| 
      
 866 
     | 
    
         
            +
                  end
         
     | 
| 
      
 867 
     | 
    
         
            +
             
     | 
| 
      
 868 
     | 
    
         
            +
                  def development?; environment == :development end
         
     | 
| 
      
 869 
     | 
    
         
            +
                  def production?;  environment == :production  end
         
     | 
| 
      
 870 
     | 
    
         
            +
                  def test?;        environment == :test        end
         
     | 
| 
       598 
871 
     | 
    
         | 
| 
      
 872 
     | 
    
         
            +
                  # Set configuration options for Sinatra and/or the app.
         
     | 
| 
      
 873 
     | 
    
         
            +
                  # Allows scoping of settings for certain environments.
         
     | 
| 
       599 
874 
     | 
    
         
             
                  def configure(*envs, &block)
         
     | 
| 
       600 
     | 
    
         
            -
                    yield if envs.empty? || envs.include?(environment.to_sym)
         
     | 
| 
      
 875 
     | 
    
         
            +
                    yield self if envs.empty? || envs.include?(environment.to_sym)
         
     | 
| 
       601 
876 
     | 
    
         
             
                  end
         
     | 
| 
       602 
877 
     | 
    
         | 
| 
      
 878 
     | 
    
         
            +
                  # Use the specified Rack middleware
         
     | 
| 
       603 
879 
     | 
    
         
             
                  def use(middleware, *args, &block)
         
     | 
| 
       604 
     | 
    
         
            -
                     
     | 
| 
      
 880 
     | 
    
         
            +
                    @prototype = nil
         
     | 
| 
       605 
881 
     | 
    
         
             
                    @middleware << [middleware, args, block]
         
     | 
| 
       606 
882 
     | 
    
         
             
                  end
         
     | 
| 
       607 
883 
     | 
    
         | 
| 
      
 884 
     | 
    
         
            +
                  # Run the Sinatra app as a self-hosted server using
         
     | 
| 
      
 885 
     | 
    
         
            +
                  # Thin, Mongrel or WEBrick (in that order)
         
     | 
| 
       608 
886 
     | 
    
         
             
                  def run!(options={})
         
     | 
| 
       609 
     | 
    
         
            -
                    set 
     | 
| 
       610 
     | 
    
         
            -
                    handler 
     | 
| 
      
 887 
     | 
    
         
            +
                    set options
         
     | 
| 
      
 888 
     | 
    
         
            +
                    handler      = detect_rack_handler
         
     | 
| 
       611 
889 
     | 
    
         
             
                    handler_name = handler.name.gsub(/.*::/, '')
         
     | 
| 
       612 
890 
     | 
    
         
             
                    puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
         
     | 
| 
       613 
     | 
    
         
            -
                      "on #{port} for #{environment} with backup from #{handler_name}"
         
     | 
| 
      
 891 
     | 
    
         
            +
                      "on #{port} for #{environment} with backup from #{handler_name}" unless handler_name =~/cgi/i
         
     | 
| 
       614 
892 
     | 
    
         
             
                    handler.run self, :Host => host, :Port => port do |server|
         
     | 
| 
       615 
893 
     | 
    
         
             
                      trap(:INT) do
         
     | 
| 
       616 
894 
     | 
    
         
             
                        ## Use thins' hard #stop! if available, otherwise just #stop
         
     | 
| 
       617 
895 
     | 
    
         
             
                        server.respond_to?(:stop!) ? server.stop! : server.stop
         
     | 
| 
       618 
     | 
    
         
            -
                        puts "\n== Sinatra has ended his set (crowd applauds)"
         
     | 
| 
      
 896 
     | 
    
         
            +
                        puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i
         
     | 
| 
       619 
897 
     | 
    
         
             
                      end
         
     | 
| 
      
 898 
     | 
    
         
            +
                      set :running, true
         
     | 
| 
       620 
899 
     | 
    
         
             
                    end
         
     | 
| 
       621 
900 
     | 
    
         
             
                  rescue Errno::EADDRINUSE => e
         
     | 
| 
       622 
901 
     | 
    
         
             
                    puts "== Someone is already performing on port #{port}!"
         
     | 
| 
       623 
902 
     | 
    
         
             
                  end
         
     | 
| 
       624 
903 
     | 
    
         | 
| 
       625 
     | 
    
         
            -
                   
     | 
| 
       626 
     | 
    
         
            -
             
     | 
| 
       627 
     | 
    
         
            -
                    @ 
     | 
| 
      
 904 
     | 
    
         
            +
                  # The prototype instance used to process requests.
         
     | 
| 
      
 905 
     | 
    
         
            +
                  def prototype
         
     | 
| 
      
 906 
     | 
    
         
            +
                    @prototype ||= new
         
     | 
| 
       628 
907 
     | 
    
         
             
                  end
         
     | 
| 
       629 
908 
     | 
    
         | 
| 
       630 
     | 
    
         
            -
             
     | 
| 
       631 
     | 
    
         
            -
                   
     | 
| 
       632 
     | 
    
         
            -
             
     | 
| 
       633 
     | 
    
         
            -
             
     | 
| 
       634 
     | 
    
         
            -
                    builder 
     | 
| 
       635 
     | 
    
         
            -
                     
     | 
| 
       636 
     | 
    
         
            -
                    builder. 
     | 
| 
       637 
     | 
    
         
            -
                     
     | 
| 
      
 909 
     | 
    
         
            +
                  # Create a new instance of the class fronted by its middleware
         
     | 
| 
      
 910 
     | 
    
         
            +
                  # pipeline. The object is guaranteed to respond to #call but may not be
         
     | 
| 
      
 911 
     | 
    
         
            +
                  # an instance of the class new was called on.
         
     | 
| 
      
 912 
     | 
    
         
            +
                  def new(*args, &bk)
         
     | 
| 
      
 913 
     | 
    
         
            +
                    builder = Rack::Builder.new
         
     | 
| 
      
 914 
     | 
    
         
            +
                    builder.use Rack::Session::Cookie if sessions? && !test?
         
     | 
| 
      
 915 
     | 
    
         
            +
                    builder.use Rack::CommonLogger    if logging?
         
     | 
| 
      
 916 
     | 
    
         
            +
                    builder.use Rack::MethodOverride  if methodoverride?
         
     | 
| 
      
 917 
     | 
    
         
            +
                    builder.use ShowExceptions        if show_exceptions?
         
     | 
| 
      
 918 
     | 
    
         
            +
                    middleware.each { |c,a,b| builder.use(c, *a, &b) }
         
     | 
| 
      
 919 
     | 
    
         
            +
             
     | 
| 
      
 920 
     | 
    
         
            +
                    builder.run super
         
     | 
| 
      
 921 
     | 
    
         
            +
                    builder.to_app
         
     | 
| 
       638 
922 
     | 
    
         
             
                  end
         
     | 
| 
       639 
923 
     | 
    
         | 
| 
       640 
     | 
    
         
            -
                  def  
     | 
| 
       641 
     | 
    
         
            -
                     
     | 
| 
      
 924 
     | 
    
         
            +
                  def call(env)
         
     | 
| 
      
 925 
     | 
    
         
            +
                    synchronize { prototype.call(env) }
         
     | 
| 
      
 926 
     | 
    
         
            +
                  end
         
     | 
| 
      
 927 
     | 
    
         
            +
             
     | 
| 
      
 928 
     | 
    
         
            +
                private
         
     | 
| 
      
 929 
     | 
    
         
            +
                  def detect_rack_handler
         
     | 
| 
      
 930 
     | 
    
         
            +
                    servers = Array(self.server)
         
     | 
| 
      
 931 
     | 
    
         
            +
                    servers.each do |server_name|
         
     | 
| 
      
 932 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 933 
     | 
    
         
            +
                        return Rack::Handler.get(server_name.downcase)
         
     | 
| 
      
 934 
     | 
    
         
            +
                      rescue LoadError
         
     | 
| 
      
 935 
     | 
    
         
            +
                      rescue NameError
         
     | 
| 
      
 936 
     | 
    
         
            +
                      end
         
     | 
| 
      
 937 
     | 
    
         
            +
                    end
         
     | 
| 
      
 938 
     | 
    
         
            +
                    fail "Server handler (#{servers.join(',')}) not found."
         
     | 
| 
       642 
939 
     | 
    
         
             
                  end
         
     | 
| 
       643 
940 
     | 
    
         | 
| 
       644 
941 
     | 
    
         
             
                  def inherited(subclass)
         
     | 
| 
       645 
     | 
    
         
            -
                    subclass. 
     | 
| 
       646 
     | 
    
         
            -
                    subclass.templates = templates.dup
         
     | 
| 
       647 
     | 
    
         
            -
                    subclass.conditions = []
         
     | 
| 
       648 
     | 
    
         
            -
                    subclass.filters = filters.dup
         
     | 
| 
       649 
     | 
    
         
            -
                    subclass.errors = errors.dup
         
     | 
| 
       650 
     | 
    
         
            -
                    subclass.middleware = middleware.dup
         
     | 
| 
       651 
     | 
    
         
            -
                    subclass.send :reset_middleware
         
     | 
| 
      
 942 
     | 
    
         
            +
                    subclass.reset!
         
     | 
| 
       652 
943 
     | 
    
         
             
                    super
         
     | 
| 
       653 
944 
     | 
    
         
             
                  end
         
     | 
| 
       654 
945 
     | 
    
         | 
| 
       655 
     | 
    
         
            -
                   
     | 
| 
       656 
     | 
    
         
            -
             
     | 
| 
       657 
     | 
    
         
            -
             
     | 
| 
       658 
     | 
    
         
            -
                       
     | 
| 
      
 946 
     | 
    
         
            +
                  @@mutex = Mutex.new
         
     | 
| 
      
 947 
     | 
    
         
            +
                  def synchronize(&block)
         
     | 
| 
      
 948 
     | 
    
         
            +
                    if lock?
         
     | 
| 
      
 949 
     | 
    
         
            +
                      @@mutex.synchronize(&block)
         
     | 
| 
      
 950 
     | 
    
         
            +
                    else
         
     | 
| 
      
 951 
     | 
    
         
            +
                      yield
         
     | 
| 
       659 
952 
     | 
    
         
             
                    end
         
     | 
| 
       660 
953 
     | 
    
         
             
                  end
         
     | 
| 
       661 
954 
     | 
    
         | 
| 
         @@ -663,18 +956,47 @@ module Sinatra 
     | 
|
| 
       663 
956 
     | 
    
         
             
                    (class << self; self; end).
         
     | 
| 
       664 
957 
     | 
    
         
             
                      send :define_method, message, &block
         
     | 
| 
       665 
958 
     | 
    
         
             
                  end
         
     | 
| 
      
 959 
     | 
    
         
            +
             
     | 
| 
      
 960 
     | 
    
         
            +
                public
         
     | 
| 
      
 961 
     | 
    
         
            +
                  CALLERS_TO_IGNORE = [
         
     | 
| 
      
 962 
     | 
    
         
            +
                    /\/sinatra(\/(base|main|showexceptions))?\.rb$/, # all sinatra code
         
     | 
| 
      
 963 
     | 
    
         
            +
                    /\(.*\)/,              # generated code
         
     | 
| 
      
 964 
     | 
    
         
            +
                    /custom_require\.rb$/, # rubygems require hacks
         
     | 
| 
      
 965 
     | 
    
         
            +
                    /active_support/,      # active_support require hacks
         
     | 
| 
      
 966 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 967 
     | 
    
         
            +
             
     | 
| 
      
 968 
     | 
    
         
            +
                  # add rubinius (and hopefully other VM impls) ignore patterns ...
         
     | 
| 
      
 969 
     | 
    
         
            +
                  CALLERS_TO_IGNORE.concat(RUBY_IGNORE_CALLERS) if defined?(RUBY_IGNORE_CALLERS)
         
     | 
| 
      
 970 
     | 
    
         
            +
             
     | 
| 
      
 971 
     | 
    
         
            +
                  # Like Kernel#caller but excluding certain magic entries and without
         
     | 
| 
      
 972 
     | 
    
         
            +
                  # line / method information; the resulting array contains filenames only.
         
     | 
| 
      
 973 
     | 
    
         
            +
                  def caller_files
         
     | 
| 
      
 974 
     | 
    
         
            +
                    caller_locations.
         
     | 
| 
      
 975 
     | 
    
         
            +
                      map { |file,line| file }
         
     | 
| 
      
 976 
     | 
    
         
            +
                  end
         
     | 
| 
      
 977 
     | 
    
         
            +
             
     | 
| 
      
 978 
     | 
    
         
            +
                  def caller_locations
         
     | 
| 
      
 979 
     | 
    
         
            +
                    caller(1).
         
     | 
| 
      
 980 
     | 
    
         
            +
                      map    { |line| line.split(/:(?=\d|in )/)[0,2] }.
         
     | 
| 
      
 981 
     | 
    
         
            +
                      reject { |file,line| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
         
     | 
| 
      
 982 
     | 
    
         
            +
                  end
         
     | 
| 
       666 
983 
     | 
    
         
             
                end
         
     | 
| 
       667 
984 
     | 
    
         | 
| 
      
 985 
     | 
    
         
            +
                reset!
         
     | 
| 
      
 986 
     | 
    
         
            +
             
     | 
| 
       668 
987 
     | 
    
         
             
                set :raise_errors, true
         
     | 
| 
       669 
988 
     | 
    
         
             
                set :dump_errors, false
         
     | 
| 
      
 989 
     | 
    
         
            +
                set :clean_trace, true
         
     | 
| 
      
 990 
     | 
    
         
            +
                set :show_exceptions, false
         
     | 
| 
       670 
991 
     | 
    
         
             
                set :sessions, false
         
     | 
| 
       671 
992 
     | 
    
         
             
                set :logging, false
         
     | 
| 
       672 
993 
     | 
    
         
             
                set :methodoverride, false
         
     | 
| 
       673 
994 
     | 
    
         
             
                set :static, false
         
     | 
| 
       674 
995 
     | 
    
         
             
                set :environment, (ENV['RACK_ENV'] || :development).to_sym
         
     | 
| 
       675 
996 
     | 
    
         | 
| 
       676 
     | 
    
         
            -
                set :run, false
         
     | 
| 
       677 
     | 
    
         
            -
                set : 
     | 
| 
      
 997 
     | 
    
         
            +
                set :run, false                       # start server via at-exit hook?
         
     | 
| 
      
 998 
     | 
    
         
            +
                set :running, false                   # is the built-in server running now?
         
     | 
| 
      
 999 
     | 
    
         
            +
                set :server, %w[thin mongrel webrick]
         
     | 
| 
       678 
1000 
     | 
    
         
             
                set :host, '0.0.0.0'
         
     | 
| 
       679 
1001 
     | 
    
         
             
                set :port, 4567
         
     | 
| 
       680 
1002 
     | 
    
         | 
| 
         @@ -682,14 +1004,7 @@ module Sinatra 
     | 
|
| 
       682 
1004 
     | 
    
         
             
                set :root, Proc.new { app_file && File.expand_path(File.dirname(app_file)) }
         
     | 
| 
       683 
1005 
     | 
    
         
             
                set :views, Proc.new { root && File.join(root, 'views') }
         
     | 
| 
       684 
1006 
     | 
    
         
             
                set :public, Proc.new { root && File.join(root, 'public') }
         
     | 
| 
       685 
     | 
    
         
            -
             
     | 
| 
       686 
     | 
    
         
            -
                # static files route
         
     | 
| 
       687 
     | 
    
         
            -
                get(/.*[^\/]$/) do
         
     | 
| 
       688 
     | 
    
         
            -
                  pass unless options.static? && options.public?
         
     | 
| 
       689 
     | 
    
         
            -
                  path = options.public + unescape(request.path_info)
         
     | 
| 
       690 
     | 
    
         
            -
                  pass unless File.file?(path)
         
     | 
| 
       691 
     | 
    
         
            -
                  send_file path, :disposition => nil
         
     | 
| 
       692 
     | 
    
         
            -
                end
         
     | 
| 
      
 1007 
     | 
    
         
            +
                set :lock, false
         
     | 
| 
       693 
1008 
     | 
    
         | 
| 
       694 
1009 
     | 
    
         
             
                error ::Exception do
         
     | 
| 
       695 
1010 
     | 
    
         
             
                  response.status = 500
         
     | 
| 
         @@ -705,6 +1020,8 @@ module Sinatra 
     | 
|
| 
       705 
1020 
     | 
    
         
             
                  end
         
     | 
| 
       706 
1021 
     | 
    
         | 
| 
       707 
1022 
     | 
    
         
             
                  error NotFound do
         
     | 
| 
      
 1023 
     | 
    
         
            +
                    content_type 'text/html'
         
     | 
| 
      
 1024 
     | 
    
         
            +
             
     | 
| 
       708 
1025 
     | 
    
         
             
                    (<<-HTML).gsub(/^ {8}/, '')
         
     | 
| 
       709 
1026 
     | 
    
         
             
                    <!DOCTYPE html>
         
     | 
| 
       710 
1027 
     | 
    
         
             
                    <html>
         
     | 
| 
         @@ -726,93 +1043,67 @@ module Sinatra 
     | 
|
| 
       726 
1043 
     | 
    
         
             
                    </html>
         
     | 
| 
       727 
1044 
     | 
    
         
             
                    HTML
         
     | 
| 
       728 
1045 
     | 
    
         
             
                  end
         
     | 
| 
       729 
     | 
    
         
            -
             
     | 
| 
       730 
     | 
    
         
            -
                  error do
         
     | 
| 
       731 
     | 
    
         
            -
                    next unless err = request.env['sinatra.error']
         
     | 
| 
       732 
     | 
    
         
            -
                    heading = err.class.name + ' - ' + err.message.to_s
         
     | 
| 
       733 
     | 
    
         
            -
                    (<<-HTML).gsub(/^ {8}/, '')
         
     | 
| 
       734 
     | 
    
         
            -
                    <!DOCTYPE html>
         
     | 
| 
       735 
     | 
    
         
            -
                    <html>
         
     | 
| 
       736 
     | 
    
         
            -
                    <head>
         
     | 
| 
       737 
     | 
    
         
            -
                      <style type="text/css">
         
     | 
| 
       738 
     | 
    
         
            -
                        body {font-family:verdana;color:#333}
         
     | 
| 
       739 
     | 
    
         
            -
                        #c {margin-left:20px}
         
     | 
| 
       740 
     | 
    
         
            -
                        h1 {color:#1D6B8D;margin:0;margin-top:-30px}
         
     | 
| 
       741 
     | 
    
         
            -
                        h2 {color:#1D6B8D;font-size:18px}
         
     | 
| 
       742 
     | 
    
         
            -
                        pre {border-left:2px solid #ddd;padding-left:10px;color:#000}
         
     | 
| 
       743 
     | 
    
         
            -
                        img {margin-top:10px}
         
     | 
| 
       744 
     | 
    
         
            -
                      </style>
         
     | 
| 
       745 
     | 
    
         
            -
                    </head>
         
     | 
| 
       746 
     | 
    
         
            -
                    <body>
         
     | 
| 
       747 
     | 
    
         
            -
                      <div id="c">
         
     | 
| 
       748 
     | 
    
         
            -
                        <img src="/__sinatra__/500.png">
         
     | 
| 
       749 
     | 
    
         
            -
                        <h1>#{escape_html(heading)}</h1>
         
     | 
| 
       750 
     | 
    
         
            -
                        <pre class='trace'>#{escape_html(err.backtrace.join("\n"))}</pre>
         
     | 
| 
       751 
     | 
    
         
            -
                        <h2>Params</h2>
         
     | 
| 
       752 
     | 
    
         
            -
                        <pre>#{escape_html(params.inspect)}</pre>
         
     | 
| 
       753 
     | 
    
         
            -
                      </div>
         
     | 
| 
       754 
     | 
    
         
            -
                    </body>
         
     | 
| 
       755 
     | 
    
         
            -
                    </html>
         
     | 
| 
       756 
     | 
    
         
            -
                    HTML
         
     | 
| 
       757 
     | 
    
         
            -
                  end
         
     | 
| 
       758 
1046 
     | 
    
         
             
                end
         
     | 
| 
       759 
1047 
     | 
    
         
             
              end
         
     | 
| 
       760 
1048 
     | 
    
         | 
| 
       761 
     | 
    
         
            -
               
     | 
| 
       762 
     | 
    
         
            -
             
     | 
| 
      
 1049 
     | 
    
         
            +
              # The top-level Application. All DSL methods executed on main are delegated
         
     | 
| 
      
 1050 
     | 
    
         
            +
              # to this class.
         
     | 
| 
      
 1051 
     | 
    
         
            +
              class Application < Base
         
     | 
| 
      
 1052 
     | 
    
         
            +
                set :raise_errors, Proc.new { test? }
         
     | 
| 
      
 1053 
     | 
    
         
            +
                set :show_exceptions, Proc.new { development? }
         
     | 
| 
       763 
1054 
     | 
    
         
             
                set :dump_errors, true
         
     | 
| 
       764 
1055 
     | 
    
         
             
                set :sessions, false
         
     | 
| 
       765 
     | 
    
         
            -
                set :logging,  
     | 
| 
      
 1056 
     | 
    
         
            +
                set :logging, Proc.new { ! test? }
         
     | 
| 
       766 
1057 
     | 
    
         
             
                set :methodoverride, true
         
     | 
| 
       767 
1058 
     | 
    
         
             
                set :static, true
         
     | 
| 
       768 
     | 
    
         
            -
                set :run,  
     | 
| 
       769 
     | 
    
         
            -
                set :reload, Proc.new { app_file? && development? }
         
     | 
| 
       770 
     | 
    
         
            -
             
     | 
| 
       771 
     | 
    
         
            -
                def self.reloading?
         
     | 
| 
       772 
     | 
    
         
            -
                  @reloading ||= false
         
     | 
| 
       773 
     | 
    
         
            -
                end
         
     | 
| 
       774 
     | 
    
         
            -
             
     | 
| 
       775 
     | 
    
         
            -
                def self.configure(*envs)
         
     | 
| 
       776 
     | 
    
         
            -
                  super unless reloading?
         
     | 
| 
       777 
     | 
    
         
            -
                end
         
     | 
| 
       778 
     | 
    
         
            -
             
     | 
| 
       779 
     | 
    
         
            -
                def self.call(env)
         
     | 
| 
       780 
     | 
    
         
            -
                  reload! if reload?
         
     | 
| 
       781 
     | 
    
         
            -
                  super
         
     | 
| 
       782 
     | 
    
         
            -
                end
         
     | 
| 
      
 1059 
     | 
    
         
            +
                set :run, Proc.new { ! test? }
         
     | 
| 
       783 
1060 
     | 
    
         | 
| 
       784 
     | 
    
         
            -
                def self. 
     | 
| 
       785 
     | 
    
         
            -
                   
     | 
| 
       786 
     | 
    
         
            -
                   
     | 
| 
       787 
     | 
    
         
            -
                   
     | 
| 
       788 
     | 
    
         
            -
                  @reloading = false
         
     | 
| 
      
 1061 
     | 
    
         
            +
                def self.register(*extensions, &block) #:nodoc:
         
     | 
| 
      
 1062 
     | 
    
         
            +
                  added_methods = extensions.map {|m| m.public_instance_methods }.flatten
         
     | 
| 
      
 1063 
     | 
    
         
            +
                  Delegator.delegate(*added_methods)
         
     | 
| 
      
 1064 
     | 
    
         
            +
                  super(*extensions, &block)
         
     | 
| 
       789 
1065 
     | 
    
         
             
                end
         
     | 
| 
       790 
     | 
    
         
            -
             
     | 
| 
       791 
     | 
    
         
            -
              end
         
     | 
| 
       792 
     | 
    
         
            -
             
     | 
| 
       793 
     | 
    
         
            -
              class Application < Default
         
     | 
| 
       794 
1066 
     | 
    
         
             
              end
         
     | 
| 
       795 
1067 
     | 
    
         | 
| 
       796 
     | 
    
         
            -
               
     | 
| 
       797 
     | 
    
         
            -
             
     | 
| 
       798 
     | 
    
         
            -
             
     | 
| 
       799 
     | 
    
         
            -
             
     | 
| 
       800 
     | 
    
         
            -
             
     | 
| 
       801 
     | 
    
         
            -
             
     | 
| 
       802 
     | 
    
         
            -
             
     | 
| 
       803 
     | 
    
         
            -
                 
     | 
| 
       804 
     | 
    
         
            -
                   
     | 
| 
       805 
     | 
    
         
            -
                     
     | 
| 
       806 
     | 
    
         
            -
                       
     | 
| 
       807 
     | 
    
         
            -
             
     | 
| 
       808 
     | 
    
         
            -
             
     | 
| 
       809 
     | 
    
         
            -
             
     | 
| 
      
 1068 
     | 
    
         
            +
              # Deprecated.
         
     | 
| 
      
 1069 
     | 
    
         
            +
              Default = Application
         
     | 
| 
      
 1070 
     | 
    
         
            +
             
     | 
| 
      
 1071 
     | 
    
         
            +
              # Sinatra delegation mixin. Mixing this module into an object causes all
         
     | 
| 
      
 1072 
     | 
    
         
            +
              # methods to be delegated to the Sinatra::Application class. Used primarily
         
     | 
| 
      
 1073 
     | 
    
         
            +
              # at the top-level.
         
     | 
| 
      
 1074 
     | 
    
         
            +
              module Delegator #:nodoc:
         
     | 
| 
      
 1075 
     | 
    
         
            +
                def self.delegate(*methods)
         
     | 
| 
      
 1076 
     | 
    
         
            +
                  methods.each do |method_name|
         
     | 
| 
      
 1077 
     | 
    
         
            +
                    eval <<-RUBY, binding, '(__DELEGATE__)', 1
         
     | 
| 
      
 1078 
     | 
    
         
            +
                      def #{method_name}(*args, &b)
         
     | 
| 
      
 1079 
     | 
    
         
            +
                        ::Sinatra::Application.send(#{method_name.inspect}, *args, &b)
         
     | 
| 
      
 1080 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1081 
     | 
    
         
            +
                      private #{method_name.inspect}
         
     | 
| 
      
 1082 
     | 
    
         
            +
                    RUBY
         
     | 
| 
      
 1083 
     | 
    
         
            +
                  end
         
     | 
| 
       810 
1084 
     | 
    
         
             
                end
         
     | 
| 
      
 1085 
     | 
    
         
            +
             
     | 
| 
      
 1086 
     | 
    
         
            +
                delegate :get, :put, :post, :delete, :head, :template, :layout, :before,
         
     | 
| 
      
 1087 
     | 
    
         
            +
                         :error, :not_found, :configure, :set,
         
     | 
| 
      
 1088 
     | 
    
         
            +
                         :enable, :disable, :use, :development?, :test?,
         
     | 
| 
      
 1089 
     | 
    
         
            +
                         :production?, :use_in_file_templates!, :helpers
         
     | 
| 
       811 
1090 
     | 
    
         
             
              end
         
     | 
| 
       812 
1091 
     | 
    
         | 
| 
      
 1092 
     | 
    
         
            +
              # Create a new Sinatra application. The block is evaluated in the new app's
         
     | 
| 
      
 1093 
     | 
    
         
            +
              # class scope.
         
     | 
| 
       813 
1094 
     | 
    
         
             
              def self.new(base=Base, options={}, &block)
         
     | 
| 
       814 
1095 
     | 
    
         
             
                base = Class.new(base)
         
     | 
| 
       815 
1096 
     | 
    
         
             
                base.send :class_eval, &block if block_given?
         
     | 
| 
       816 
1097 
     | 
    
         
             
                base
         
     | 
| 
       817 
1098 
     | 
    
         
             
              end
         
     | 
| 
      
 1099 
     | 
    
         
            +
             
     | 
| 
      
 1100 
     | 
    
         
            +
              # Extend the top-level DSL with the modules provided.
         
     | 
| 
      
 1101 
     | 
    
         
            +
              def self.register(*extensions, &block)
         
     | 
| 
      
 1102 
     | 
    
         
            +
                Application.register(*extensions, &block)
         
     | 
| 
      
 1103 
     | 
    
         
            +
              end
         
     | 
| 
      
 1104 
     | 
    
         
            +
             
     | 
| 
      
 1105 
     | 
    
         
            +
              # Include the helper modules provided in Sinatra's request context.
         
     | 
| 
      
 1106 
     | 
    
         
            +
              def self.helpers(*extensions, &block)
         
     | 
| 
      
 1107 
     | 
    
         
            +
                Application.helpers(*extensions, &block)
         
     | 
| 
      
 1108 
     | 
    
         
            +
              end
         
     | 
| 
       818 
1109 
     | 
    
         
             
            end
         
     |