sinatra 1.4.8 → 2.0.8.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

Files changed (129) hide show
  1. checksums.yaml +5 -5
  2. data/AUTHORS.md +1 -0
  3. data/CHANGELOG.md +238 -54
  4. data/CONTRIBUTING.md +8 -8
  5. data/Gemfile +47 -47
  6. data/LICENSE +4 -1
  7. data/MAINTENANCE.md +42 -0
  8. data/README.de.md +650 -442
  9. data/README.es.md +738 -357
  10. data/README.fr.md +15 -15
  11. data/README.hu.md +37 -3
  12. data/README.ja.md +124 -66
  13. data/README.ko.md +14 -14
  14. data/README.malayalam.md +3141 -0
  15. data/README.md +530 -403
  16. data/README.pt-br.md +2361 -334
  17. data/README.pt-pt.md +2 -2
  18. data/README.ru.md +856 -607
  19. data/README.zh.md +90 -28
  20. data/Rakefile +77 -51
  21. data/SECURITY.md +35 -0
  22. data/VERSION +1 -0
  23. data/lib/sinatra/base.rb +177 -239
  24. data/lib/sinatra/indifferent_hash.rb +200 -0
  25. data/lib/sinatra/main.rb +30 -10
  26. data/lib/sinatra/show_exceptions.rb +102 -62
  27. data/lib/sinatra/version.rb +1 -1
  28. data/sinatra.gemspec +44 -8
  29. metadata +41 -166
  30. data/lib/sinatra/ext.rb +0 -17
  31. data/test/asciidoctor_test.rb +0 -72
  32. data/test/base_test.rb +0 -167
  33. data/test/builder_test.rb +0 -91
  34. data/test/coffee_test.rb +0 -96
  35. data/test/compile_test.rb +0 -183
  36. data/test/contest.rb +0 -91
  37. data/test/creole_test.rb +0 -65
  38. data/test/delegator_test.rb +0 -160
  39. data/test/encoding_test.rb +0 -20
  40. data/test/erb_test.rb +0 -116
  41. data/test/extensions_test.rb +0 -98
  42. data/test/filter_test.rb +0 -487
  43. data/test/haml_test.rb +0 -109
  44. data/test/helper.rb +0 -132
  45. data/test/helpers_test.rb +0 -1917
  46. data/test/integration/app.rb +0 -79
  47. data/test/integration_helper.rb +0 -236
  48. data/test/integration_test.rb +0 -104
  49. data/test/less_test.rb +0 -69
  50. data/test/liquid_test.rb +0 -77
  51. data/test/mapped_error_test.rb +0 -285
  52. data/test/markaby_test.rb +0 -80
  53. data/test/markdown_test.rb +0 -85
  54. data/test/mediawiki_test.rb +0 -68
  55. data/test/middleware_test.rb +0 -68
  56. data/test/nokogiri_test.rb +0 -67
  57. data/test/public/favicon.ico +0 -0
  58. data/test/public/hello+world.txt +0 -1
  59. data/test/rabl_test.rb +0 -89
  60. data/test/rack_test.rb +0 -45
  61. data/test/radius_test.rb +0 -59
  62. data/test/rdoc_test.rb +0 -66
  63. data/test/readme_test.rb +0 -130
  64. data/test/request_test.rb +0 -100
  65. data/test/response_test.rb +0 -63
  66. data/test/result_test.rb +0 -76
  67. data/test/route_added_hook_test.rb +0 -59
  68. data/test/routing_test.rb +0 -1456
  69. data/test/sass_test.rb +0 -115
  70. data/test/scss_test.rb +0 -88
  71. data/test/server_test.rb +0 -56
  72. data/test/settings_test.rb +0 -582
  73. data/test/sinatra_test.rb +0 -12
  74. data/test/slim_test.rb +0 -102
  75. data/test/static_test.rb +0 -266
  76. data/test/streaming_test.rb +0 -149
  77. data/test/stylus_test.rb +0 -90
  78. data/test/templates_test.rb +0 -382
  79. data/test/textile_test.rb +0 -65
  80. data/test/views/a/in_a.str +0 -1
  81. data/test/views/ascii.erb +0 -2
  82. data/test/views/b/in_b.str +0 -1
  83. data/test/views/calc.html.erb +0 -1
  84. data/test/views/error.builder +0 -3
  85. data/test/views/error.erb +0 -3
  86. data/test/views/error.haml +0 -3
  87. data/test/views/error.sass +0 -2
  88. data/test/views/explicitly_nested.str +0 -1
  89. data/test/views/foo/hello.test +0 -1
  90. data/test/views/hello.asciidoc +0 -1
  91. data/test/views/hello.builder +0 -1
  92. data/test/views/hello.coffee +0 -1
  93. data/test/views/hello.creole +0 -1
  94. data/test/views/hello.erb +0 -1
  95. data/test/views/hello.haml +0 -1
  96. data/test/views/hello.less +0 -5
  97. data/test/views/hello.liquid +0 -1
  98. data/test/views/hello.mab +0 -1
  99. data/test/views/hello.md +0 -1
  100. data/test/views/hello.mediawiki +0 -1
  101. data/test/views/hello.nokogiri +0 -1
  102. data/test/views/hello.rabl +0 -2
  103. data/test/views/hello.radius +0 -1
  104. data/test/views/hello.rdoc +0 -1
  105. data/test/views/hello.sass +0 -2
  106. data/test/views/hello.scss +0 -3
  107. data/test/views/hello.slim +0 -1
  108. data/test/views/hello.str +0 -1
  109. data/test/views/hello.styl +0 -2
  110. data/test/views/hello.test +0 -1
  111. data/test/views/hello.textile +0 -1
  112. data/test/views/hello.wlang +0 -1
  113. data/test/views/hello.yajl +0 -1
  114. data/test/views/layout2.builder +0 -3
  115. data/test/views/layout2.erb +0 -2
  116. data/test/views/layout2.haml +0 -2
  117. data/test/views/layout2.liquid +0 -2
  118. data/test/views/layout2.mab +0 -2
  119. data/test/views/layout2.nokogiri +0 -3
  120. data/test/views/layout2.rabl +0 -3
  121. data/test/views/layout2.radius +0 -2
  122. data/test/views/layout2.slim +0 -3
  123. data/test/views/layout2.str +0 -2
  124. data/test/views/layout2.test +0 -1
  125. data/test/views/layout2.wlang +0 -2
  126. data/test/views/nested.str +0 -1
  127. data/test/views/utf8.erb +0 -2
  128. data/test/wlang_test.rb +0 -87
  129. data/test/yajl_test.rb +0 -86
@@ -1,79 +0,0 @@
1
- $stderr.puts "loading"
2
- require 'sinatra'
3
-
4
- configure do
5
- set :foo, :bar
6
- end
7
-
8
- get '/app_file' do
9
- content_type :txt
10
- settings.app_file
11
- end
12
-
13
- get '/ping' do
14
- 'pong'
15
- end
16
-
17
- get '/stream' do
18
- stream do |out|
19
- sleep 0.1
20
- out << "a"
21
- sleep 1.2
22
- out << "b"
23
- end
24
- end
25
-
26
- get '/mainonly' do
27
- object = Object.new
28
- begin
29
- object.send(:get, '/foo') { }
30
- 'false'
31
- rescue NameError
32
- 'true'
33
- end
34
- end
35
-
36
- set :out, nil
37
- get '/async' do
38
- stream(:keep_open) { |o| (settings.out = o) << "hi!" }
39
- end
40
-
41
- get '/send' do
42
- settings.out << params[:msg] if params[:msg]
43
- settings.out.close if params[:close]
44
- "ok"
45
- end
46
-
47
- get '/send_file' do
48
- file = File.expand_path '../../views/a/in_a.str', __FILE__
49
- send_file file
50
- end
51
-
52
- get '/streaming' do
53
- headers['Content-Length'] = '46'
54
- stream do |out|
55
- out << "It's gonna be legen -\n"
56
- sleep 0.5
57
- out << " (wait for it) \n"
58
- puts headers
59
- sleep 1
60
- out << "- dary!\n"
61
- end
62
- end
63
-
64
- class Subclass < Sinatra::Base
65
- set :out, nil
66
- get '/subclass/async' do
67
- stream(:keep_open) { |o| (settings.out = o) << "hi!" }
68
- end
69
-
70
- get '/subclass/send' do
71
- settings.out << params[:msg] if params[:msg]
72
- settings.out.close if params[:close]
73
- "ok"
74
- end
75
- end
76
-
77
- use Subclass
78
-
79
- $stderr.puts "starting"
@@ -1,236 +0,0 @@
1
- require 'sinatra/base'
2
- require 'rbconfig'
3
- require 'open-uri'
4
- require 'net/http'
5
- require 'timeout'
6
-
7
- module IntegrationHelper
8
- class BaseServer
9
- extend Enumerable
10
- attr_accessor :server, :port, :pipe
11
- alias name server
12
-
13
- def self.all
14
- @all ||= []
15
- end
16
-
17
- def self.each(&block)
18
- all.each(&block)
19
- end
20
-
21
- def self.run(server, port)
22
- new(server, port).run
23
- end
24
-
25
- def app_file
26
- File.expand_path('../integration/app.rb', __FILE__)
27
- end
28
-
29
- def environment
30
- "development"
31
- end
32
-
33
- def initialize(server, port)
34
- @installed, @pipe, @server, @port = nil, nil, server, port
35
- Server.all << self
36
- end
37
-
38
- def run
39
- return unless installed?
40
- kill
41
- @log = ""
42
- @pipe = IO.popen(command)
43
- @started = Time.now
44
- warn "#{server} up and running on port #{port}" if ping
45
- at_exit { kill }
46
- end
47
-
48
- def ping(timeout = 30)
49
- loop do
50
- return if alive?
51
- if Time.now - @started > timeout
52
- $stderr.puts command, log
53
- fail "timeout"
54
- else
55
- sleep 0.1
56
- end
57
- end
58
- end
59
-
60
- def alive?
61
- 3.times { get('/ping') }
62
- true
63
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET, EOFError, SystemCallError, OpenURI::HTTPError, Timeout::Error
64
- false
65
- end
66
-
67
- def get_stream(url = "/stream", &block)
68
- Net::HTTP.start '127.0.0.1', port do |http|
69
- request = Net::HTTP::Get.new url
70
- http.request request do |response|
71
- response.read_body(&block)
72
- end
73
- end
74
- end
75
-
76
- def get_response(url)
77
- Net::HTTP.start '127.0.0.1', port do |http|
78
- request = Net::HTTP::Get.new url
79
- http.request request do |response|
80
- response
81
- end
82
- end
83
- end
84
-
85
- def get(url)
86
- Timeout.timeout(1) { open("http://127.0.0.1:#{port}#{url}").read }
87
- end
88
-
89
- def log
90
- @log ||= ""
91
- loop { @log << @pipe.read_nonblock(1) }
92
- rescue Exception
93
- @log
94
- end
95
-
96
- def installed?
97
- return @installed unless @installed.nil?
98
- s = server == 'HTTP' ? 'net/http/server' : server
99
- require s
100
- @installed = true
101
- rescue LoadError
102
- warn "#{server} is not installed, skipping integration tests"
103
- @installed = false
104
- end
105
-
106
- def command
107
- @command ||= begin
108
- cmd = ["RACK_ENV=#{environment}", "exec"]
109
- if RbConfig.respond_to? :ruby
110
- cmd << RbConfig.ruby.inspect
111
- else
112
- file, dir = RbConfig::CONFIG.values_at('ruby_install_name', 'bindir')
113
- cmd << File.expand_path(file, dir).inspect
114
- end
115
- cmd << "-w" unless thin? || net_http_server?
116
- cmd << "-I" << File.expand_path('../../lib', __FILE__).inspect
117
- cmd << app_file.inspect << '-s' << server << '-o' << '127.0.0.1' << '-p' << port
118
- cmd << "-e" << environment.to_s << '2>&1'
119
- cmd.join " "
120
- end
121
- end
122
-
123
- def kill
124
- return unless pipe
125
- Process.kill("KILL", pipe.pid)
126
- rescue NotImplementedError
127
- system "kill -9 #{pipe.pid}"
128
- rescue Errno::ESRCH
129
- end
130
-
131
- def webrick?
132
- name.to_s == "webrick"
133
- end
134
-
135
- def thin?
136
- name.to_s == "thin"
137
- end
138
-
139
- def puma?
140
- name.to_s == "puma"
141
- end
142
-
143
- def trinidad?
144
- name.to_s == "trinidad"
145
- end
146
-
147
- def net_http_server?
148
- name.to_s == 'HTTP'
149
- end
150
-
151
- def warnings
152
- log.scan(%r[(?:\(eval|lib/sinatra).*warning:.*$])
153
- end
154
-
155
- def run_test(target, &block)
156
- retries ||= 3
157
- target.server = self
158
- run unless alive?
159
- target.instance_eval(&block)
160
- rescue Exception => error
161
- retries -= 1
162
- kill
163
- retries < 0 ? retry : raise(error)
164
- end
165
- end
166
-
167
- if RUBY_ENGINE == "jruby"
168
- class JRubyServer < BaseServer
169
- def start_vm
170
- require 'java'
171
- # Create a new container, set load paths and env
172
- # SINGLETHREAD means create a new runtime
173
- vm = org.jruby.embed.ScriptingContainer.new(org.jruby.embed.LocalContextScope::SINGLETHREAD)
174
- vm.load_paths = [File.expand_path('../../lib', __FILE__)]
175
- vm.environment = ENV.merge('RACK_ENV' => environment.to_s)
176
-
177
- # This ensures processing of RUBYOPT which activates Bundler
178
- vm.provider.ruby_instance_config.process_arguments []
179
- vm.argv = ['-s', server.to_s, '-o', '127.0.0.1', '-p', port.to_s, '-e', environment.to_s]
180
-
181
- # Set stdout/stderr so we can retrieve log
182
- @pipe = java.io.ByteArrayOutputStream.new
183
- vm.output = java.io.PrintStream.new(@pipe)
184
- vm.error = java.io.PrintStream.new(@pipe)
185
-
186
- Thread.new do
187
- # Hack to ensure that Kernel#caller has the same info as
188
- # when run from command-line, for Sinatra::Application.app_file.
189
- # Also, line numbers are zero-based in JRuby's parser
190
- vm.provider.runtime.current_context.set_file_and_line(app_file, 0)
191
- # Run the app
192
- vm.run_scriptlet org.jruby.embed.PathType::ABSOLUTE, app_file
193
- # terminate launches at_exit hooks which start server
194
- vm.terminate
195
- end
196
- end
197
-
198
- def run
199
- return unless installed?
200
- kill
201
- @thread = start_vm
202
- @started = Time.now
203
- warn "#{server} up and running on port #{port}" if ping
204
- at_exit { kill }
205
- end
206
-
207
- def log
208
- String.from_java_bytes @pipe.to_byte_array
209
- end
210
-
211
- def kill
212
- @thread.kill if @thread
213
- @thread = nil
214
- end
215
- end
216
- Server = JRubyServer
217
- else
218
- Server = BaseServer
219
- end
220
-
221
- def it(message, &block)
222
- Server.each do |server|
223
- next unless server.installed?
224
- super("with #{server.name}: #{message}") { server.run_test(self, &block) }
225
- end
226
- end
227
-
228
- def self.extend_object(obj)
229
- super
230
-
231
- base_port = 5000 + Process.pid % 100
232
- Sinatra::Base.server.each_with_index do |server, index|
233
- Server.run(server, base_port+index)
234
- end
235
- end
236
- end
@@ -1,104 +0,0 @@
1
- require File.expand_path('../helper', __FILE__)
2
- require File.expand_path('../integration_helper', __FILE__)
3
-
4
- # These tests start a real server and talk to it over TCP.
5
- # Every test runs with every detected server.
6
- #
7
- # See test/integration/app.rb for the code of the app we test against.
8
- class IntegrationTest < Minitest::Test
9
- extend IntegrationHelper
10
- attr_accessor :server
11
-
12
- it('sets the app_file') { assert_equal server.app_file, server.get("/app_file") }
13
- it('only extends main') { assert_equal "true", server.get("/mainonly") }
14
-
15
- it 'logs once in development mode' do
16
- next if server.puma? or RUBY_ENGINE == 'jruby'
17
- random = "%064x" % Kernel.rand(2**256-1)
18
- server.get "/ping?x=#{random}"
19
- count = server.log.scan("GET /ping?x=#{random}").count
20
- if server.net_http_server?
21
- assert_equal 0, count
22
- elsif server.webrick?
23
- assert(count > 0)
24
- else
25
- assert_equal(1, count)
26
- end
27
- end
28
-
29
- it 'streams' do
30
- next if server.webrick? or server.trinidad?
31
- times, chunks = [Time.now], []
32
- server.get_stream do |chunk|
33
- next if chunk.empty?
34
- chunks << chunk
35
- times << Time.now
36
- end
37
- assert_equal ["a", "b"], chunks
38
- assert times[1] - times[0] < 1
39
- assert times[2] - times[1] > 1
40
- end
41
-
42
- it 'streams async' do
43
- next unless server.thin?
44
-
45
- Timeout.timeout(3) do
46
- chunks = []
47
- server.get_stream '/async' do |chunk|
48
- next if chunk.empty?
49
- chunks << chunk
50
- case chunk
51
- when "hi!" then server.get "/send?msg=hello"
52
- when "hello" then server.get "/send?close=1"
53
- end
54
- end
55
-
56
- assert_equal ['hi!', 'hello'], chunks
57
- end
58
- end
59
-
60
- it 'streams async from subclass' do
61
- next unless server.thin?
62
-
63
- Timeout.timeout(3) do
64
- chunks = []
65
- server.get_stream '/subclass/async' do |chunk|
66
- next if chunk.empty?
67
- chunks << chunk
68
- case chunk
69
- when "hi!" then server.get "/subclass/send?msg=hello"
70
- when "hello" then server.get "/subclass/send?close=1"
71
- end
72
- end
73
-
74
- assert_equal ['hi!', 'hello'], chunks
75
- end
76
- end
77
-
78
- it 'starts the correct server' do
79
- exp = %r{
80
- ==\sSinatra\s\(v#{Sinatra::VERSION}\)\s
81
- has\staken\sthe\sstage\son\s\d+\sfor\sdevelopment\s
82
- with\sbackup\sfrom\s#{server}
83
- }ix
84
-
85
- # because Net HTTP Server logs to $stderr by default
86
- assert_match exp, server.log unless server.net_http_server?
87
- end
88
-
89
- it 'does not generate warnings' do
90
- assert_raises(OpenURI::HTTPError) { server.get '/' }
91
- server.get '/app_file'
92
- assert_equal [], server.warnings
93
- end
94
-
95
- it 'sets the Content-Length response header when sending files' do
96
- response = server.get_response '/send_file'
97
- assert response['Content-Length']
98
- end
99
-
100
- it "doesn't ignore Content-Length header when streaming" do
101
- response = server.get_response '/streaming'
102
- assert_equal '46', response['Content-Length']
103
- end
104
- end
data/test/less_test.rb DELETED
@@ -1,69 +0,0 @@
1
- require File.expand_path('../helper', __FILE__)
2
-
3
- begin
4
- require 'less'
5
-
6
- class LessTest < Minitest::Test
7
- def less_app(options = {}, &block)
8
- mock_app do
9
- set :views, File.dirname(__FILE__) + '/views'
10
- set options
11
- get('/', &block)
12
- end
13
- get '/'
14
- end
15
-
16
- it 'renders inline Less strings' do
17
- less_app {
18
- less "@white_color: #fff; #main { background-color: @white_color }"
19
- }
20
- assert ok?
21
- assert_equal "#main{background-color:#ffffff;}", body.gsub(/\s/, "")
22
- end
23
-
24
- it 'defaults content type to css' do
25
- less_app {
26
- less "@white_color: #fff; #main { background-color: @white_color }"
27
- }
28
- assert ok?
29
- assert_equal "text/css;charset=utf-8", response['Content-Type']
30
- end
31
-
32
- it 'defaults allows setting content type per route' do
33
- less_app do
34
- content_type :html
35
- less "@white_color: #fff; #main { background-color: @white_color }"
36
- end
37
- assert ok?
38
- assert_equal "text/html;charset=utf-8", response['Content-Type']
39
- end
40
-
41
- it 'defaults allows setting content type globally' do
42
- less_app(:less => { :content_type => 'html' }) do
43
- less "@white_color: #fff; #main { background-color: @white_color }"
44
- end
45
- assert ok?
46
- assert_equal "text/html;charset=utf-8", response['Content-Type']
47
- end
48
-
49
- it 'renders .less files in views path' do
50
- less_app { less :hello }
51
- assert ok?
52
- assert_equal "#main{background-color:#ffffff;}", body.gsub(/\s/, "")
53
- end
54
-
55
- it 'ignores the layout option' do
56
- less_app { less :hello, :layout => :layout2 }
57
- assert ok?
58
- assert_equal "#main{background-color:#ffffff;}", body.gsub(/\s/, "")
59
- end
60
-
61
- it "raises error if template not found" do
62
- mock_app { get('/') { less :no_such_template } }
63
- assert_raises(Errno::ENOENT) { get('/') }
64
- end
65
- end
66
-
67
- rescue LoadError
68
- warn "#{$!.to_s}: skipping less tests"
69
- end
data/test/liquid_test.rb DELETED
@@ -1,77 +0,0 @@
1
- require File.expand_path('../helper', __FILE__)
2
-
3
- begin
4
- require 'liquid'
5
-
6
- class LiquidTest < Minitest::Test
7
- def liquid_app(&block)
8
- mock_app do
9
- set :views, File.dirname(__FILE__) + '/views'
10
- get('/', &block)
11
- end
12
- get '/'
13
- end
14
-
15
- it 'renders inline liquid strings' do
16
- liquid_app { liquid '<h1>Hiya</h1>' }
17
- assert ok?
18
- assert_equal "<h1>Hiya</h1>", body
19
- end
20
-
21
- it 'renders .liquid files in views path' do
22
- liquid_app { liquid :hello }
23
- assert ok?
24
- assert_equal "<h1>Hello From Liquid</h1>\n", body
25
- end
26
-
27
- it "renders with inline layouts" do
28
- mock_app do
29
- layout { "<h1>THIS. IS. {{ yield }}</h1>" }
30
- get('/') { liquid '<EM>SPARTA</EM>' }
31
- end
32
- get '/'
33
- assert ok?
34
- assert_equal "<h1>THIS. IS. <EM>SPARTA</EM></h1>", body
35
- end
36
-
37
- it "renders with file layouts" do
38
- liquid_app { liquid 'Hello World', :layout => :layout2 }
39
- assert ok?
40
- assert_equal "<h1>Liquid Layout!</h1>\n<p>Hello World</p>\n", body
41
- end
42
-
43
- it "raises error if template not found" do
44
- mock_app { get('/') { liquid :no_such_template } }
45
- assert_raises(Errno::ENOENT) { get('/') }
46
- end
47
-
48
- it "allows passing locals" do
49
- liquid_app {
50
- liquid '{{ value }}', :locals => { :value => 'foo' }
51
- }
52
- assert ok?
53
- assert_equal 'foo', body
54
- end
55
-
56
- it "can render truly nested layouts by accepting a layout and a block with the contents" do
57
- mock_app do
58
- template(:main_outer_layout) { "<h1>Title</h1>\n{{ yield }}" }
59
- template(:an_inner_layout) { "<h2>Subtitle</h2>\n{{ yield }}" }
60
- template(:a_page) { "<p>Contents.</p>\n" }
61
- get('/') do
62
- liquid :main_outer_layout, :layout => false do
63
- liquid :an_inner_layout do
64
- liquid :a_page
65
- end
66
- end
67
- end
68
- end
69
- get '/'
70
- assert ok?
71
- assert_body "<h1>Title</h1>\n<h2>Subtitle</h2>\n<p>Contents.</p>\n"
72
- end
73
- end
74
-
75
- rescue LoadError
76
- warn "#{$!.to_s}: skipping liquid tests"
77
- end