sinatra 1.4.8 → 2.0.0

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -47
  3. data/CONTRIBUTING.md +1 -1
  4. data/Gemfile +41 -49
  5. data/LICENSE +4 -1
  6. data/MAINTENANCE.md +42 -0
  7. data/README.de.md +644 -436
  8. data/README.es.md +6 -6
  9. data/README.fr.md +9 -9
  10. data/README.hu.md +37 -3
  11. data/README.ja.md +103 -45
  12. data/README.ko.md +8 -8
  13. data/README.md +471 -363
  14. data/README.pt-br.md +3 -3
  15. data/README.pt-pt.md +2 -2
  16. data/README.ru.md +42 -64
  17. data/README.zh.md +8 -8
  18. data/Rakefile +72 -49
  19. data/SECURITY.md +35 -0
  20. data/lib/sinatra/base.rb +137 -195
  21. data/lib/sinatra/indifferent_hash.rb +150 -0
  22. data/lib/sinatra/main.rb +1 -0
  23. data/lib/sinatra/show_exceptions.rb +63 -55
  24. data/lib/sinatra/version.rb +1 -1
  25. data/sinatra.gemspec +19 -7
  26. metadata +30 -164
  27. data/lib/sinatra/ext.rb +0 -17
  28. data/test/asciidoctor_test.rb +0 -72
  29. data/test/base_test.rb +0 -167
  30. data/test/builder_test.rb +0 -91
  31. data/test/coffee_test.rb +0 -96
  32. data/test/compile_test.rb +0 -183
  33. data/test/contest.rb +0 -91
  34. data/test/creole_test.rb +0 -65
  35. data/test/delegator_test.rb +0 -160
  36. data/test/encoding_test.rb +0 -20
  37. data/test/erb_test.rb +0 -116
  38. data/test/extensions_test.rb +0 -98
  39. data/test/filter_test.rb +0 -487
  40. data/test/haml_test.rb +0 -109
  41. data/test/helper.rb +0 -132
  42. data/test/helpers_test.rb +0 -1917
  43. data/test/integration/app.rb +0 -79
  44. data/test/integration_helper.rb +0 -236
  45. data/test/integration_test.rb +0 -104
  46. data/test/less_test.rb +0 -69
  47. data/test/liquid_test.rb +0 -77
  48. data/test/mapped_error_test.rb +0 -285
  49. data/test/markaby_test.rb +0 -80
  50. data/test/markdown_test.rb +0 -85
  51. data/test/mediawiki_test.rb +0 -68
  52. data/test/middleware_test.rb +0 -68
  53. data/test/nokogiri_test.rb +0 -67
  54. data/test/public/favicon.ico +0 -0
  55. data/test/public/hello+world.txt +0 -1
  56. data/test/rabl_test.rb +0 -89
  57. data/test/rack_test.rb +0 -45
  58. data/test/radius_test.rb +0 -59
  59. data/test/rdoc_test.rb +0 -66
  60. data/test/readme_test.rb +0 -130
  61. data/test/request_test.rb +0 -100
  62. data/test/response_test.rb +0 -63
  63. data/test/result_test.rb +0 -76
  64. data/test/route_added_hook_test.rb +0 -59
  65. data/test/routing_test.rb +0 -1456
  66. data/test/sass_test.rb +0 -115
  67. data/test/scss_test.rb +0 -88
  68. data/test/server_test.rb +0 -56
  69. data/test/settings_test.rb +0 -582
  70. data/test/sinatra_test.rb +0 -12
  71. data/test/slim_test.rb +0 -102
  72. data/test/static_test.rb +0 -266
  73. data/test/streaming_test.rb +0 -149
  74. data/test/stylus_test.rb +0 -90
  75. data/test/templates_test.rb +0 -382
  76. data/test/textile_test.rb +0 -65
  77. data/test/views/a/in_a.str +0 -1
  78. data/test/views/ascii.erb +0 -2
  79. data/test/views/b/in_b.str +0 -1
  80. data/test/views/calc.html.erb +0 -1
  81. data/test/views/error.builder +0 -3
  82. data/test/views/error.erb +0 -3
  83. data/test/views/error.haml +0 -3
  84. data/test/views/error.sass +0 -2
  85. data/test/views/explicitly_nested.str +0 -1
  86. data/test/views/foo/hello.test +0 -1
  87. data/test/views/hello.asciidoc +0 -1
  88. data/test/views/hello.builder +0 -1
  89. data/test/views/hello.coffee +0 -1
  90. data/test/views/hello.creole +0 -1
  91. data/test/views/hello.erb +0 -1
  92. data/test/views/hello.haml +0 -1
  93. data/test/views/hello.less +0 -5
  94. data/test/views/hello.liquid +0 -1
  95. data/test/views/hello.mab +0 -1
  96. data/test/views/hello.md +0 -1
  97. data/test/views/hello.mediawiki +0 -1
  98. data/test/views/hello.nokogiri +0 -1
  99. data/test/views/hello.rabl +0 -2
  100. data/test/views/hello.radius +0 -1
  101. data/test/views/hello.rdoc +0 -1
  102. data/test/views/hello.sass +0 -2
  103. data/test/views/hello.scss +0 -3
  104. data/test/views/hello.slim +0 -1
  105. data/test/views/hello.str +0 -1
  106. data/test/views/hello.styl +0 -2
  107. data/test/views/hello.test +0 -1
  108. data/test/views/hello.textile +0 -1
  109. data/test/views/hello.wlang +0 -1
  110. data/test/views/hello.yajl +0 -1
  111. data/test/views/layout2.builder +0 -3
  112. data/test/views/layout2.erb +0 -2
  113. data/test/views/layout2.haml +0 -2
  114. data/test/views/layout2.liquid +0 -2
  115. data/test/views/layout2.mab +0 -2
  116. data/test/views/layout2.nokogiri +0 -3
  117. data/test/views/layout2.rabl +0 -3
  118. data/test/views/layout2.radius +0 -2
  119. data/test/views/layout2.slim +0 -3
  120. data/test/views/layout2.str +0 -2
  121. data/test/views/layout2.test +0 -1
  122. data/test/views/layout2.wlang +0 -2
  123. data/test/views/nested.str +0 -1
  124. data/test/views/utf8.erb +0 -2
  125. data/test/wlang_test.rb +0 -87
  126. data/test/yajl_test.rb +0 -86
data/test/static_test.rb DELETED
@@ -1,266 +0,0 @@
1
- require File.expand_path('../helper', __FILE__)
2
-
3
- class StaticTest < Minitest::Test
4
- setup do
5
- mock_app do
6
- set :static, true
7
- set :public_folder, File.dirname(__FILE__)
8
- end
9
- end
10
-
11
- it 'serves GET requests for files in the public directory' do
12
- get "/#{File.basename(__FILE__)}"
13
- assert ok?
14
- assert_equal File.read(__FILE__), body
15
- assert_equal File.size(__FILE__).to_s, response['Content-Length']
16
- assert response.headers.include?('Last-Modified')
17
- end
18
-
19
- it 'produces a body that can be iterated over multiple times' do
20
- env = Rack::MockRequest.env_for("/#{File.basename(__FILE__)}")
21
- _, _, body = @app.call(env)
22
- buf1, buf2 = [], []
23
- body.each { |part| buf1 << part }
24
- body.each { |part| buf2 << part }
25
- assert_equal buf1.join, buf2.join
26
- assert_equal File.read(__FILE__), buf1.join
27
- end
28
-
29
- it 'sets the sinatra.static_file env variable if served' do
30
- env = Rack::MockRequest.env_for("/#{File.basename(__FILE__)}")
31
- @app.call(env)
32
- assert_equal File.expand_path(__FILE__), env['sinatra.static_file']
33
- end
34
-
35
- it 'serves HEAD requests for files in the public directory' do
36
- head "/#{File.basename(__FILE__)}"
37
- assert ok?
38
- assert_equal '', body
39
- assert response.headers.include?('Last-Modified')
40
- assert_equal File.size(__FILE__).to_s, response['Content-Length']
41
- end
42
-
43
- %w[POST PUT DELETE].each do |verb|
44
- it "does not serve #{verb} requests" do
45
- send verb.downcase, "/#{File.basename(__FILE__)}"
46
- assert_equal 404, status
47
- end
48
- end
49
-
50
- it 'serves files in preference to custom routes' do
51
- @app.get("/#{File.basename(__FILE__)}") { 'Hello World' }
52
- get "/#{File.basename(__FILE__)}"
53
- assert ok?
54
- assert body != 'Hello World'
55
- end
56
-
57
- it 'does not serve directories' do
58
- get "/"
59
- assert not_found?
60
- end
61
-
62
- it 'passes to the next handler when the static option is disabled' do
63
- @app.set :static, false
64
- get "/#{File.basename(__FILE__)}"
65
- assert not_found?
66
- end
67
-
68
- it 'passes to the next handler when the public option is nil' do
69
- @app.set :public_folder, nil
70
- get "/#{File.basename(__FILE__)}"
71
- assert not_found?
72
- end
73
-
74
- it '404s when a file is not found' do
75
- get "/foobarbaz.txt"
76
- assert not_found?
77
- end
78
-
79
- it 'serves files when .. path traverses within public directory' do
80
- get "/data/../#{File.basename(__FILE__)}"
81
- assert ok?
82
- assert_equal File.read(__FILE__), body
83
- end
84
-
85
- it '404s when .. path traverses outside of public directory' do
86
- mock_app do
87
- set :static, true
88
- set :public_folder, File.dirname(__FILE__) + '/data'
89
- end
90
- get "/../#{File.basename(__FILE__)}"
91
- assert not_found?
92
- end
93
-
94
- def assert_valid_range(http_range, range, path, file)
95
- request = Rack::MockRequest.new(@app)
96
- response = request.get("/#{File.basename(path)}", 'HTTP_RANGE' => http_range)
97
-
98
- should_be = file[range]
99
- expected_range = "bytes #{range.begin}-#{range.end}/#{file.length}"
100
-
101
- assert_equal(
102
- 206,response.status,
103
- "Should be HTTP/1.1 206 Partial content"
104
- )
105
- assert_equal(
106
- should_be.length,
107
- response.body.length,
108
- "Unexpected response length for #{http_range}"
109
- )
110
- assert_equal(
111
- should_be,
112
- response.body,
113
- "Unexpected response data for #{http_range}"
114
- )
115
- assert_equal(
116
- should_be.length.to_s,
117
- response['Content-Length'],
118
- "Incorrect Content-Length for #{http_range}"
119
- )
120
- assert_equal(
121
- expected_range,
122
- response['Content-Range'],
123
- "Incorrect Content-Range for #{http_range}"
124
- )
125
- end
126
-
127
- it 'handles valid byte ranges correctly' do
128
- # Use the biggest file in this dir so we can test ranges > 8k bytes. (StaticFile sends in 8k chunks.)
129
- path = File.dirname(__FILE__) + '/helpers_test.rb' # currently 16k bytes
130
- file = File.read(path)
131
- length = file.length
132
- assert length > 9000, "The test file #{path} is too short (#{length} bytes) to run these tests"
133
-
134
- [0..0, 42..88, 1234..1234, 100..9000, 0..(length-1), (length-1)..(length-1)].each do |range|
135
- assert_valid_range("bytes=#{range.begin}-#{range.end}", range, path, file)
136
- end
137
-
138
- [0, 100, length-100, length-1].each do |start|
139
- assert_valid_range("bytes=#{start}-", (start..length-1), path, file)
140
- end
141
-
142
- [1, 100, length-100, length-1, length].each do |range_length|
143
- assert_valid_range("bytes=-#{range_length}", (length-range_length..length-1), path, file)
144
- end
145
-
146
- # Some valid ranges that exceed the length of the file:
147
- assert_valid_range("bytes=100-999999", (100..length-1), path, file)
148
- assert_valid_range("bytes=100-#{length}", (100..length-1), path, file)
149
- assert_valid_range("bytes=-#{length}", (0..length-1), path, file)
150
- assert_valid_range("bytes=-#{length+1}", (0..length-1), path, file)
151
- assert_valid_range("bytes=-999999", (0..length-1), path, file)
152
- end
153
-
154
- it 'correctly ignores syntactically invalid range requests' do
155
- # ...and also ignores multi-range requests, which aren't supported yet
156
- ["bytes=45-40", "bytes=IV-LXVI", "octets=10-20", "bytes=-", "bytes=1-2,3-4"].each do |http_range|
157
- request = Rack::MockRequest.new(@app)
158
- response = request.get("/#{File.basename(__FILE__)}", 'HTTP_RANGE' => http_range)
159
-
160
- assert_equal(
161
- 200,
162
- response.status,
163
- "Invalid range '#{http_range}' should be ignored"
164
- )
165
- assert_equal(
166
- nil,
167
- response['Content-Range'],
168
- "Invalid range '#{http_range}' should be ignored"
169
- )
170
- end
171
- end
172
-
173
- it 'returns error 416 for unsatisfiable range requests' do
174
- # An unsatisfiable request is one that specifies a start that's at or past the end of the file.
175
- length = File.read(__FILE__).length
176
- ["bytes=888888-", "bytes=888888-999999", "bytes=#{length}-#{length}"].each do |http_range|
177
- request = Rack::MockRequest.new(@app)
178
- response = request.get("/#{File.basename(__FILE__)}", 'HTTP_RANGE' => http_range)
179
-
180
- assert_equal(
181
- 416,
182
- response.status,
183
- "Unsatisfiable range '#{http_range}' should return 416"
184
- )
185
- assert_equal(
186
- "bytes */#{length}",
187
- response['Content-Range'],
188
- "416 response should include actual length"
189
- )
190
- end
191
- end
192
-
193
- it 'does not include static cache control headers by default' do
194
- env = Rack::MockRequest.env_for("/#{File.basename(__FILE__)}")
195
- _, headers, _ = @app.call(env)
196
- assert !headers.has_key?('Cache-Control')
197
- end
198
-
199
- it 'sets cache control headers on static files if set' do
200
- @app.set :static_cache_control, :public
201
- env = Rack::MockRequest.env_for("/#{File.basename(__FILE__)}")
202
- status, headers, body = @app.call(env)
203
- assert headers.has_key?('Cache-Control')
204
- assert_equal headers['Cache-Control'], 'public'
205
-
206
- @app.set(
207
- :static_cache_control,
208
- [:public, :must_revalidate, {:max_age => 300}]
209
- )
210
- env = Rack::MockRequest.env_for("/#{File.basename(__FILE__)}")
211
- status, headers, body = @app.call(env)
212
- assert headers.has_key?('Cache-Control')
213
- assert_equal(
214
- headers['Cache-Control'],
215
- 'public, must-revalidate, max-age=300'
216
- )
217
- end
218
-
219
- it 'renders static assets with custom status via options' do
220
- mock_app do
221
- set :static, true
222
- set :public_folder, File.dirname(__FILE__)
223
-
224
- post '/*' do
225
- static!(:status => params[:status])
226
- end
227
- end
228
-
229
- post "/#{File.basename(__FILE__)}?status=422"
230
- assert_equal response.status, 422
231
- assert_equal File.read(__FILE__), body
232
- assert_equal File.size(__FILE__).to_s, response['Content-Length']
233
- assert response.headers.include?('Last-Modified')
234
- end
235
-
236
- it 'serves files with a + sign in the path' do
237
- mock_app do
238
- set :static, true
239
- set :public_folder, File.join(File.dirname(__FILE__), 'public')
240
- end
241
-
242
- get "/hello+world.txt"
243
-
244
- real_path = File.join(File.dirname(__FILE__), 'public', 'hello+world.txt')
245
- assert ok?
246
- assert_equal File.read(real_path), body
247
- assert_equal File.size(real_path).to_s, response['Content-Length']
248
- assert response.headers.include?('Last-Modified')
249
- end
250
-
251
- it 'serves files with a URL encoded + sign (%2B) in the path' do
252
- mock_app do
253
- set :static, true
254
- set :public_folder, File.join(File.dirname(__FILE__), 'public')
255
- end
256
-
257
- get "/hello%2bworld.txt"
258
-
259
- real_path = File.join(File.dirname(__FILE__), 'public', 'hello+world.txt')
260
- assert ok?
261
- assert_equal File.read(real_path), body
262
- assert_equal File.size(real_path).to_s, response['Content-Length']
263
- assert response.headers.include?('Last-Modified')
264
- end
265
-
266
- end
@@ -1,149 +0,0 @@
1
- require File.expand_path('../helper', __FILE__)
2
-
3
- class StreamingTest < Minitest::Test
4
- Stream = Sinatra::Helpers::Stream
5
-
6
- it 'returns the concatenated body' do
7
- mock_app do
8
- get('/') do
9
- stream do |out|
10
- out << "Hello" << " "
11
- out << "World!"
12
- end
13
- end
14
- end
15
-
16
- get('/')
17
- assert_body "Hello World!"
18
- end
19
-
20
- it 'always yields strings' do
21
- stream = Stream.new { |out| out << :foo }
22
- stream.each { |str| assert_equal 'foo', str }
23
- end
24
-
25
- it 'postpones body generation' do
26
- step = 0
27
-
28
- stream = Stream.new do |out|
29
- 10.times do
30
- out << step
31
- step += 1
32
- end
33
- end
34
-
35
- stream.each do |s|
36
- assert_equal s, step.to_s
37
- step += 1
38
- end
39
- end
40
-
41
- it 'calls the callback after it is done' do
42
- step = 0
43
- final = 0
44
- stream = Stream.new { |_| 10.times { step += 1 }}
45
- stream.callback { final = step }
46
- stream.each {|_|}
47
- assert_equal 10, final
48
- end
49
-
50
- it 'does not trigger the callback if close is set to :keep_open' do
51
- step = 0
52
- final = 0
53
- stream = Stream.new(Stream, :keep_open) { |_| 10.times { step += 1 } }
54
- stream.callback { final = step }
55
- stream.each {|_|}
56
- assert_equal 0, final
57
- end
58
-
59
- it 'allows adding more than one callback' do
60
- a = b = false
61
- stream = Stream.new { }
62
- stream.callback { a = true }
63
- stream.callback { b = true }
64
- stream.each {|_| }
65
- assert a, 'should trigger first callback'
66
- assert b, 'should trigger second callback'
67
- end
68
-
69
- class MockScheduler
70
- def initialize(*) @schedule, @defer = [], [] end
71
- def schedule(&block) @schedule << block end
72
- def defer(&block) @defer << block end
73
- def schedule!(*) @schedule.pop.call until @schedule.empty? end
74
- def defer!(*) @defer.pop.call until @defer.empty? end
75
- end
76
-
77
- it 'allows dropping in another scheduler' do
78
- scheduler = MockScheduler.new
79
- processing = sending = done = false
80
-
81
- stream = Stream.new(scheduler) do |out|
82
- processing = true
83
- out << :foo
84
- end
85
-
86
- stream.each { sending = true}
87
- stream.callback { done = true }
88
-
89
- scheduler.schedule!
90
- assert !processing
91
- assert !sending
92
- assert !done
93
-
94
- scheduler.defer!
95
- assert processing
96
- assert !sending
97
- assert !done
98
-
99
- scheduler.schedule!
100
- assert sending
101
- assert done
102
- end
103
-
104
- it 'schedules exceptions to be raised on the main thread/event loop/...' do
105
- scheduler = MockScheduler.new
106
- Stream.new(scheduler) { fail 'should be caught' }.each { }
107
- scheduler.defer!
108
- assert_raises(RuntimeError) { scheduler.schedule! }
109
- end
110
-
111
- it 'does not trigger an infinite loop if you call close in a callback' do
112
- stream = Stream.new { |out| out.callback { out.close }}
113
- stream.each { |_| }
114
- end
115
-
116
- it 'gives access to route specific params' do
117
- mock_app do
118
- get('/:name') do
119
- stream { |o| o << params[:name] }
120
- end
121
- end
122
- get '/foo'
123
- assert_body 'foo'
124
- end
125
-
126
- it 'sets up async.close if available' do
127
- ran = false
128
- mock_app do
129
- get('/') do
130
- close = Object.new
131
- def close.callback; yield end
132
- def close.errback; end
133
- env['async.close'] = close
134
- stream(:keep_open) do |out|
135
- out.callback { ran = true }
136
- end
137
- end
138
- end
139
- get '/'
140
- assert ran
141
- end
142
-
143
- it 'has a public interface to inspect its open/closed state' do
144
- stream = Stream.new(Stream) { |out| out << :foo }
145
- assert !stream.closed?
146
- stream.close
147
- assert stream.closed?
148
- end
149
- end
data/test/stylus_test.rb DELETED
@@ -1,90 +0,0 @@
1
- require File.expand_path('../helper', __FILE__)
2
-
3
- begin
4
- require 'stylus'
5
- require 'stylus/tilt'
6
-
7
- begin
8
- Stylus.compile '1'
9
- rescue RuntimeError
10
- raise LoadError, 'unable to find Stylus compiler'
11
- end
12
-
13
- class StylusTest < Minitest::Test
14
- def stylus_app(options = {}, &block)
15
- mock_app do
16
- set :views, File.dirname(__FILE__) + '/views'
17
- set(options)
18
- get('/', &block)
19
- end
20
- get '/'
21
- end
22
-
23
- it 'renders inline Stylus strings' do
24
- stylus_app { stylus "a\n margin auto\n" }
25
- assert ok?
26
- assert body.include?("a {\n margin: auto;\n}\n")
27
- end
28
-
29
- it 'defaults content type to css' do
30
- stylus_app { stylus :hello }
31
- assert ok?
32
- assert_equal "text/css;charset=utf-8", response['Content-Type']
33
- end
34
-
35
- it 'defaults allows setting content type per route' do
36
- stylus_app do
37
- content_type :html
38
- stylus :hello
39
- end
40
- assert ok?
41
- assert_equal "text/html;charset=utf-8", response['Content-Type']
42
- end
43
-
44
- it 'defaults allows setting content type globally' do
45
- stylus_app(:styl => { :content_type => 'html' }) do
46
- stylus :hello
47
- end
48
- assert ok?
49
- assert_equal "text/html;charset=utf-8", response['Content-Type']
50
- end
51
-
52
- it 'renders .styl files in views path' do
53
- stylus_app { stylus :hello }
54
- assert ok?
55
- assert_include body, "a {\n margin: auto;\n}\n"
56
- end
57
-
58
- it 'ignores the layout option' do
59
- stylus_app { stylus :hello, :layout => :layout2 }
60
- assert ok?
61
- assert_include body, "a {\n margin: auto;\n}\n"
62
- end
63
-
64
- it "raises error if template not found" do
65
- mock_app {
66
- get('/') { stylus :no_such_template }
67
- }
68
- assert_raises(Errno::ENOENT) { get('/') }
69
- end
70
-
71
- it "passes stylus options to the stylus engine" do
72
- stylus_app { stylus :hello, :no_wrap => true }
73
- assert ok?
74
- assert_body "a {\n margin: auto;\n}\n"
75
- end
76
-
77
- it "passes default stylus options to the stylus engine" do
78
- mock_app do
79
- set :stylus, :no_wrap => true # default stylus style is :nested
80
- get('/') { stylus :hello }
81
- end
82
- get '/'
83
- assert ok?
84
- assert_body "a {\n margin: auto;\n}\n"
85
- end
86
- end
87
-
88
- rescue LoadError
89
- warn "#{$!.to_s}: skipping stylus tests"
90
- end