roda 3.28.0 → 3.29.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG +10 -0
- data/README.rdoc +10 -0
- data/doc/release_notes/3.29.0.txt +15 -0
- data/lib/roda.rb +1 -0
- data/lib/roda/plugins/caching.rb +2 -0
- data/lib/roda/plugins/common_logger.rb +1 -1
- data/lib/roda/plugins/exception_page.rb +7 -1
- data/lib/roda/plugins/indifferent_params.rb +2 -0
- data/lib/roda/version.rb +1 -1
- metadata +4 -214
- data/Rakefile +0 -108
- data/doc/release_notes/1.0.0.txt +0 -329
- data/doc/release_notes/1.1.0.txt +0 -226
- data/doc/release_notes/1.2.0.txt +0 -406
- data/doc/release_notes/1.3.0.txt +0 -109
- data/doc/release_notes/2.0.0.txt +0 -75
- data/doc/release_notes/2.1.0.txt +0 -124
- data/doc/release_notes/2.10.0.txt +0 -27
- data/doc/release_notes/2.11.0.txt +0 -70
- data/doc/release_notes/2.12.0.txt +0 -40
- data/doc/release_notes/2.13.0.txt +0 -10
- data/doc/release_notes/2.14.0.txt +0 -44
- data/doc/release_notes/2.15.0.txt +0 -53
- data/doc/release_notes/2.16.0.txt +0 -48
- data/doc/release_notes/2.17.0.txt +0 -62
- data/doc/release_notes/2.18.0.txt +0 -69
- data/doc/release_notes/2.19.0.txt +0 -30
- data/doc/release_notes/2.2.0.txt +0 -97
- data/doc/release_notes/2.20.0.txt +0 -5
- data/doc/release_notes/2.21.0.txt +0 -17
- data/doc/release_notes/2.22.0.txt +0 -41
- data/doc/release_notes/2.23.0.txt +0 -29
- data/doc/release_notes/2.24.0.txt +0 -65
- data/doc/release_notes/2.25.0.txt +0 -14
- data/doc/release_notes/2.26.0.txt +0 -13
- data/doc/release_notes/2.27.0.txt +0 -56
- data/doc/release_notes/2.28.0.txt +0 -17
- data/doc/release_notes/2.29.0.txt +0 -156
- data/doc/release_notes/2.3.0.txt +0 -109
- data/doc/release_notes/2.4.0.txt +0 -55
- data/doc/release_notes/2.5.0.txt +0 -23
- data/doc/release_notes/2.5.1.txt +0 -4
- data/doc/release_notes/2.6.0.txt +0 -21
- data/doc/release_notes/2.7.0.txt +0 -75
- data/doc/release_notes/2.8.0.txt +0 -44
- data/doc/release_notes/2.9.0.txt +0 -6
- data/spec/all.rb +0 -1
- data/spec/assets/css/app.scss +0 -1
- data/spec/assets/css/no_access.css +0 -1
- data/spec/assets/css/raw.css +0 -1
- data/spec/assets/js/head/app.js +0 -1
- data/spec/composition_spec.rb +0 -31
- data/spec/define_roda_method_spec.rb +0 -274
- data/spec/env_spec.rb +0 -11
- data/spec/freeze_spec.rb +0 -37
- data/spec/integration_spec.rb +0 -209
- data/spec/matchers_spec.rb +0 -832
- data/spec/opts_spec.rb +0 -42
- data/spec/plugin/_after_hook_spec.rb +0 -19
- data/spec/plugin/all_verbs_spec.rb +0 -29
- data/spec/plugin/assets_preloading_spec.rb +0 -98
- data/spec/plugin/assets_spec.rb +0 -745
- data/spec/plugin/backtracking_array_spec.rb +0 -42
- data/spec/plugin/branch_locals_spec.rb +0 -106
- data/spec/plugin/caching_spec.rb +0 -337
- data/spec/plugin/chunked_spec.rb +0 -201
- data/spec/plugin/class_level_routing_spec.rb +0 -164
- data/spec/plugin/class_matchers_spec.rb +0 -40
- data/spec/plugin/common_logger_spec.rb +0 -85
- data/spec/plugin/content_for_spec.rb +0 -162
- data/spec/plugin/content_security_policy_spec.rb +0 -175
- data/spec/plugin/cookies_spec.rb +0 -51
- data/spec/plugin/csrf_spec.rb +0 -111
- data/spec/plugin/default_headers_spec.rb +0 -82
- data/spec/plugin/default_status_spec.rb +0 -95
- data/spec/plugin/delay_build_spec.rb +0 -23
- data/spec/plugin/delegate_spec.rb +0 -23
- data/spec/plugin/delete_empty_headers_spec.rb +0 -27
- data/spec/plugin/direct_call_spec.rb +0 -28
- data/spec/plugin/disallow_file_uploads_spec.rb +0 -25
- data/spec/plugin/drop_body_spec.rb +0 -24
- data/spec/plugin/early_hints_spec.rb +0 -19
- data/spec/plugin/empty_root_spec.rb +0 -14
- data/spec/plugin/environments_spec.rb +0 -42
- data/spec/plugin/error_email_spec.rb +0 -97
- data/spec/plugin/error_handler_spec.rb +0 -216
- data/spec/plugin/error_mail_spec.rb +0 -93
- data/spec/plugin/exception_page_spec.rb +0 -168
- data/spec/plugin/flash_spec.rb +0 -121
- data/spec/plugin/h_spec.rb +0 -11
- data/spec/plugin/halt_spec.rb +0 -119
- data/spec/plugin/hash_matcher_spec.rb +0 -27
- data/spec/plugin/hash_routes_spec.rb +0 -535
- data/spec/plugin/head_spec.rb +0 -52
- data/spec/plugin/header_matchers_spec.rb +0 -98
- data/spec/plugin/heartbeat_spec.rb +0 -74
- data/spec/plugin/hooks_spec.rb +0 -152
- data/spec/plugin/indifferent_params_spec.rb +0 -14
- data/spec/plugin/json_parser_spec.rb +0 -141
- data/spec/plugin/json_spec.rb +0 -83
- data/spec/plugin/mail_processor_spec.rb +0 -451
- data/spec/plugin/mailer_spec.rb +0 -282
- data/spec/plugin/match_affix_spec.rb +0 -43
- data/spec/plugin/match_hook_spec.rb +0 -79
- data/spec/plugin/middleware_spec.rb +0 -237
- data/spec/plugin/middleware_stack_spec.rb +0 -81
- data/spec/plugin/module_include_spec.rb +0 -48
- data/spec/plugin/multi_route_spec.rb +0 -268
- data/spec/plugin/multi_run_spec.rb +0 -87
- data/spec/plugin/multi_view_spec.rb +0 -50
- data/spec/plugin/multibyte_string_matcher_spec.rb +0 -44
- data/spec/plugin/named_templates_spec.rb +0 -96
- data/spec/plugin/not_allowed_spec.rb +0 -69
- data/spec/plugin/not_found_spec.rb +0 -128
- data/spec/plugin/optimized_string_matchers_spec.rb +0 -43
- data/spec/plugin/padrino_render_spec.rb +0 -34
- data/spec/plugin/param_matchers_spec.rb +0 -69
- data/spec/plugin/params_capturing_spec.rb +0 -33
- data/spec/plugin/partials_spec.rb +0 -43
- data/spec/plugin/pass_spec.rb +0 -29
- data/spec/plugin/path_matchers_spec.rb +0 -42
- data/spec/plugin/path_rewriter_spec.rb +0 -45
- data/spec/plugin/path_spec.rb +0 -222
- data/spec/plugin/placeholder_string_matchers_spec.rb +0 -126
- data/spec/plugin/precompile_templates_spec.rb +0 -61
- data/spec/plugin/public_spec.rb +0 -85
- data/spec/plugin/render_each_spec.rb +0 -82
- data/spec/plugin/render_locals_spec.rb +0 -114
- data/spec/plugin/render_spec.rb +0 -912
- data/spec/plugin/request_aref_spec.rb +0 -51
- data/spec/plugin/request_headers_spec.rb +0 -39
- data/spec/plugin/response_request_spec.rb +0 -43
- data/spec/plugin/route_block_args_spec.rb +0 -86
- data/spec/plugin/route_csrf_spec.rb +0 -305
- data/spec/plugin/run_append_slash_spec.rb +0 -77
- data/spec/plugin/run_handler_spec.rb +0 -53
- data/spec/plugin/sessions_spec.rb +0 -452
- data/spec/plugin/shared_vars_spec.rb +0 -45
- data/spec/plugin/sinatra_helpers_spec.rb +0 -537
- data/spec/plugin/slash_path_empty_spec.rb +0 -22
- data/spec/plugin/static_routing_spec.rb +0 -192
- data/spec/plugin/static_spec.rb +0 -30
- data/spec/plugin/status_303_spec.rb +0 -28
- data/spec/plugin/status_handler_spec.rb +0 -158
- data/spec/plugin/streaming_spec.rb +0 -246
- data/spec/plugin/strip_path_prefix_spec.rb +0 -24
- data/spec/plugin/symbol_matchers_spec.rb +0 -51
- data/spec/plugin/symbol_status_spec.rb +0 -25
- data/spec/plugin/symbol_views_spec.rb +0 -32
- data/spec/plugin/timestamp_public_spec.rb +0 -85
- data/spec/plugin/type_routing_spec.rb +0 -348
- data/spec/plugin/typecast_params_spec.rb +0 -1370
- data/spec/plugin/unescape_path_spec.rb +0 -22
- data/spec/plugin/view_options_spec.rb +0 -170
- data/spec/plugin_spec.rb +0 -71
- data/spec/redirect_spec.rb +0 -41
- data/spec/request_spec.rb +0 -97
- data/spec/response_spec.rb +0 -199
- data/spec/route_spec.rb +0 -39
- data/spec/session_middleware_spec.rb +0 -129
- data/spec/session_spec.rb +0 -37
- data/spec/spec_helper.rb +0 -137
- data/spec/version_spec.rb +0 -14
- data/spec/views/_test.erb +0 -1
- data/spec/views/a.erb +0 -1
- data/spec/views/a.rdoc +0 -2
- data/spec/views/about.erb +0 -1
- data/spec/views/about.str +0 -1
- data/spec/views/about/_test.css.gz +0 -0
- data/spec/views/about/_test.erb +0 -1
- data/spec/views/about/_test.erb.gz +0 -0
- data/spec/views/about/comp_test.erb +0 -1
- data/spec/views/b.erb +0 -1
- data/spec/views/c.erb +0 -1
- data/spec/views/comp_layout.erb +0 -1
- data/spec/views/comp_test.erb +0 -1
- data/spec/views/content-yield.erb +0 -1
- data/spec/views/each.str +0 -1
- data/spec/views/home.erb +0 -2
- data/spec/views/home.str +0 -2
- data/spec/views/iv.erb +0 -1
- data/spec/views/layout-alternative.erb +0 -2
- data/spec/views/layout-yield.erb +0 -3
- data/spec/views/layout.erb +0 -2
- data/spec/views/layout.str +0 -2
- data/spec/views/multiple-layout.erb +0 -1
- data/spec/views/multiple.erb +0 -1
@@ -1,22 +0,0 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
|
-
describe "slash_path_empty" do
|
4
|
-
it "considers a / path as empty" do
|
5
|
-
app(:slash_path_empty) do |r|
|
6
|
-
r.is{"1"}
|
7
|
-
r.is("a"){"2"}
|
8
|
-
r.get("b"){"3"}
|
9
|
-
end
|
10
|
-
|
11
|
-
body("").must_equal '1'
|
12
|
-
body.must_equal '1'
|
13
|
-
body("a").must_equal ''
|
14
|
-
body("/a").must_equal '2'
|
15
|
-
body("/a/").must_equal '2'
|
16
|
-
body("/a/b").must_equal ''
|
17
|
-
body("b").must_equal ''
|
18
|
-
body("/b").must_equal '3'
|
19
|
-
body("/b/").must_equal '3'
|
20
|
-
body("/b/c").must_equal ''
|
21
|
-
end
|
22
|
-
end
|
@@ -1,192 +0,0 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
|
-
describe "static_routing plugin" do
|
4
|
-
it "adds support for static routes that are taken before normal routes" do
|
5
|
-
app(:bare) do
|
6
|
-
plugin :static_routing
|
7
|
-
static_route "/foo" do |r|
|
8
|
-
"#{r.path}:#{r.remaining_path}"
|
9
|
-
end
|
10
|
-
static_route "/bar" do |r|
|
11
|
-
r.get{"GET:#{r.path}:#{r.remaining_path}"}
|
12
|
-
r.post{"POST:#{r.path}:#{r.remaining_path}"}
|
13
|
-
end
|
14
|
-
static_get "/bar" do |r|
|
15
|
-
r.get{"GET2:#{r.path}:#{r.remaining_path}"}
|
16
|
-
end
|
17
|
-
static_route "/quux" do |r|
|
18
|
-
r.halt [500, {}, []]
|
19
|
-
end
|
20
|
-
|
21
|
-
route do |r|
|
22
|
-
r.on 'foo' do
|
23
|
-
r.get true do
|
24
|
-
'foo1'
|
25
|
-
end
|
26
|
-
r.root do
|
27
|
-
'foo2'
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
r.get 'baz' do
|
32
|
-
'baz'
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
2.times do
|
38
|
-
body('/foo').must_equal '/foo:'
|
39
|
-
body('/foo/').must_equal 'foo2'
|
40
|
-
body('/bar').must_equal 'GET2:/bar:'
|
41
|
-
body('/bar', 'REQUEST_METHOD'=>'POST').must_equal 'POST:/bar:'
|
42
|
-
status('/bar', 'REQUEST_METHOD'=>'PATCH').must_equal 404
|
43
|
-
body('/baz').must_equal 'baz'
|
44
|
-
status('/quux').must_equal 500
|
45
|
-
@app = Class.new(@app)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
it "works with hooks plugin if loaded after" do
|
50
|
-
a = []
|
51
|
-
app(:bare) do
|
52
|
-
plugin :hooks
|
53
|
-
plugin :static_routing
|
54
|
-
|
55
|
-
before{a << 1}
|
56
|
-
after{a << 2}
|
57
|
-
|
58
|
-
static_route "/foo" do |r|
|
59
|
-
a << 3
|
60
|
-
"bar"
|
61
|
-
end
|
62
|
-
|
63
|
-
route{}
|
64
|
-
end
|
65
|
-
body('/foo').must_equal 'bar'
|
66
|
-
a.must_equal [1,3,2]
|
67
|
-
end
|
68
|
-
|
69
|
-
it "works with hooks plugin if loaded before" do
|
70
|
-
a = []
|
71
|
-
app(:bare) do
|
72
|
-
plugin :static_routing
|
73
|
-
plugin :hooks
|
74
|
-
|
75
|
-
before{a << 1}
|
76
|
-
after{a << 2}
|
77
|
-
|
78
|
-
static_route "/foo" do |r|
|
79
|
-
a << 3
|
80
|
-
"bar"
|
81
|
-
end
|
82
|
-
|
83
|
-
route{}
|
84
|
-
end
|
85
|
-
body('/foo').must_equal 'bar'
|
86
|
-
a.must_equal [1,3,2]
|
87
|
-
end
|
88
|
-
|
89
|
-
it "supports overridding static routes" do
|
90
|
-
app(:static_routing) do |r|
|
91
|
-
end
|
92
|
-
app.static_route('/foo'){'bar'}
|
93
|
-
body('/foo').must_equal 'bar'
|
94
|
-
app.static_route('/foo'){'baz'}
|
95
|
-
body('/foo').must_equal 'baz'
|
96
|
-
end
|
97
|
-
|
98
|
-
it "keeps existing routes when loading the plugin" do
|
99
|
-
app(:bare) do
|
100
|
-
plugin :static_routing
|
101
|
-
static_route "/foo" do |r|
|
102
|
-
"#{r.path}:#{r.remaining_path}"
|
103
|
-
end
|
104
|
-
plugin :static_routing
|
105
|
-
|
106
|
-
route{}
|
107
|
-
end
|
108
|
-
body('/foo').must_equal '/foo:'
|
109
|
-
end
|
110
|
-
|
111
|
-
it "does not allow placeholders in static routes" do
|
112
|
-
app(:bare) do
|
113
|
-
plugin :static_routing
|
114
|
-
static_route "/:foo" do |r|
|
115
|
-
"#{r.path}:#{r.remaining_path}"
|
116
|
-
end
|
117
|
-
|
118
|
-
route{}
|
119
|
-
end
|
120
|
-
body('/:foo').must_equal '/:foo:'
|
121
|
-
status('/a').must_equal 404
|
122
|
-
end
|
123
|
-
|
124
|
-
it "duplicates data structures in subclasses" do
|
125
|
-
app(:bare) do
|
126
|
-
plugin :static_routing
|
127
|
-
static_route "/foo" do |r|
|
128
|
-
'foo'
|
129
|
-
end
|
130
|
-
|
131
|
-
route{}
|
132
|
-
end
|
133
|
-
|
134
|
-
old_app = @app
|
135
|
-
@app = Class.new(old_app)
|
136
|
-
old_app.static_route '/bar' do |r|
|
137
|
-
'bar1'
|
138
|
-
end
|
139
|
-
old_app.static_get '/foo' do |r|
|
140
|
-
'foop'
|
141
|
-
end
|
142
|
-
@app.static_route '/bar' do |r|
|
143
|
-
'bar2'
|
144
|
-
end
|
145
|
-
|
146
|
-
body('/foo').must_equal 'foo'
|
147
|
-
body('/bar').must_equal 'bar2'
|
148
|
-
body('/foo', 'REQUEST_METHOD'=>'POST').must_equal 'foo'
|
149
|
-
@app = old_app
|
150
|
-
body('/foo').must_equal 'foop'
|
151
|
-
body('/bar').must_equal 'bar1'
|
152
|
-
body('/foo', 'REQUEST_METHOD'=>'POST').must_equal 'foo'
|
153
|
-
end
|
154
|
-
|
155
|
-
it "freezes static routes when app is frozen" do
|
156
|
-
app(:bare) do
|
157
|
-
plugin :static_routing
|
158
|
-
static_route("/foo"){}
|
159
|
-
freeze
|
160
|
-
|
161
|
-
proc do
|
162
|
-
static_get("/foo"){}
|
163
|
-
end.must_raise
|
164
|
-
|
165
|
-
proc do
|
166
|
-
static_route("/bar"){}
|
167
|
-
end.must_raise
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
it 'works with route_block_args plugin' do
|
172
|
-
app(:bare) do
|
173
|
-
plugin :static_routing
|
174
|
-
plugin :route_block_args do
|
175
|
-
[request.request_method, request.path]
|
176
|
-
end
|
177
|
-
|
178
|
-
static_route "/foo" do |meth, path|
|
179
|
-
"#{path}-#{meth}"
|
180
|
-
end
|
181
|
-
|
182
|
-
static_get "/bar" do |meth, path|
|
183
|
-
"#{path}-#{meth}-bar"
|
184
|
-
end
|
185
|
-
|
186
|
-
route{'a'}
|
187
|
-
end
|
188
|
-
|
189
|
-
body('/foo').must_equal '/foo-GET'
|
190
|
-
body('/bar').must_equal '/bar-GET-bar'
|
191
|
-
end
|
192
|
-
end
|
data/spec/plugin/static_spec.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
|
-
describe "static plugin" do
|
4
|
-
it "adds support for serving static files" do
|
5
|
-
app(:bare) do
|
6
|
-
plugin :static, ['/about'], :root=>'spec/views'
|
7
|
-
|
8
|
-
route do
|
9
|
-
'a'
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
body.must_equal 'a'
|
14
|
-
body('/about/_test.erb').must_equal File.read('spec/views/about/_test.erb')
|
15
|
-
end
|
16
|
-
|
17
|
-
it "respects the application's :root option" do
|
18
|
-
app(:bare) do
|
19
|
-
opts[:root] = File.expand_path('../../', __FILE__)
|
20
|
-
plugin :static, ['/about'], :root=>'views'
|
21
|
-
|
22
|
-
route do
|
23
|
-
'a'
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
body.must_equal 'a'
|
28
|
-
body('/about/_test.erb').must_equal File.read('spec/views/about/_test.erb')
|
29
|
-
end
|
30
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
|
-
describe "status_303 plugin" do
|
4
|
-
it 'uses a 302 for get requests' do
|
5
|
-
app(:status_303) do
|
6
|
-
request.redirect '/foo'
|
7
|
-
fail 'redirect should halt'
|
8
|
-
end
|
9
|
-
status.must_equal 302
|
10
|
-
body.must_equal ''
|
11
|
-
header('Location').must_equal '/foo'
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'uses the code given when specified' do
|
15
|
-
app(:status_303) do
|
16
|
-
request.redirect '/foo', 301
|
17
|
-
end
|
18
|
-
status.must_equal 301
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'uses 303 for post requests if request is HTTP 1.1, 302 for 1.0' do
|
22
|
-
app(:status_303) do
|
23
|
-
request.redirect '/foo'
|
24
|
-
end
|
25
|
-
status('HTTP_VERSION' => 'HTTP/1.1', 'REQUEST_METHOD'=>'POST').must_equal 303
|
26
|
-
status('HTTP_VERSION' => 'HTTP/1.0', 'REQUEST_METHOD'=>'POST').must_equal 302
|
27
|
-
end
|
28
|
-
end
|
@@ -1,158 +0,0 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
|
-
describe "status_handler plugin" do
|
4
|
-
it "executes on no arguments" do
|
5
|
-
app(:bare) do
|
6
|
-
plugin :status_handler
|
7
|
-
|
8
|
-
status_handler(404) do
|
9
|
-
"not found"
|
10
|
-
end
|
11
|
-
|
12
|
-
route do |r|
|
13
|
-
r.on "a" do
|
14
|
-
"found"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
body.must_equal 'not found'
|
20
|
-
status.must_equal 404
|
21
|
-
body("/a").must_equal 'found'
|
22
|
-
status("/a").must_equal 200
|
23
|
-
end
|
24
|
-
|
25
|
-
it "passes request if block accepts argument" do
|
26
|
-
app(:bare) do
|
27
|
-
plugin :status_handler
|
28
|
-
|
29
|
-
status_handler(404) do |r|
|
30
|
-
r.path + 'foo'
|
31
|
-
end
|
32
|
-
|
33
|
-
route do |r|
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
body('/').must_equal '/foo'
|
38
|
-
body("/a").must_equal '/afoo'
|
39
|
-
status("/").must_equal 404
|
40
|
-
end
|
41
|
-
|
42
|
-
it "allows overriding status inside status_handler" do
|
43
|
-
app(:bare) do
|
44
|
-
plugin :status_handler
|
45
|
-
|
46
|
-
status_handler(404) do
|
47
|
-
response.status = 403
|
48
|
-
"not found"
|
49
|
-
end
|
50
|
-
|
51
|
-
route do |r|
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
status.must_equal 403
|
56
|
-
end
|
57
|
-
|
58
|
-
it "calculates correct Content-Length" do
|
59
|
-
app(:bare) do
|
60
|
-
plugin :status_handler
|
61
|
-
|
62
|
-
status_handler(404) do
|
63
|
-
"a"
|
64
|
-
end
|
65
|
-
|
66
|
-
route{}
|
67
|
-
end
|
68
|
-
|
69
|
-
header('Content-Length').must_equal "1"
|
70
|
-
end
|
71
|
-
|
72
|
-
it "clears existing headers" do
|
73
|
-
app(:bare) do
|
74
|
-
plugin :status_handler
|
75
|
-
|
76
|
-
status_handler(404) do
|
77
|
-
"a"
|
78
|
-
end
|
79
|
-
|
80
|
-
route do |r|
|
81
|
-
response['Content-Type'] = 'text/pdf'
|
82
|
-
response['Foo'] = 'bar'
|
83
|
-
nil
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
header('Content-Type').must_equal 'text/html'
|
88
|
-
header('Foo').must_be_nil
|
89
|
-
end
|
90
|
-
|
91
|
-
it "does not modify behavior if status_handler is not called" do
|
92
|
-
app(:status_handler) do |r|
|
93
|
-
r.on "a" do
|
94
|
-
"found"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
body.must_equal ''
|
99
|
-
body("/a").must_equal 'found'
|
100
|
-
end
|
101
|
-
|
102
|
-
it "does not modify behavior if body is not an array" do
|
103
|
-
app(:bare) do
|
104
|
-
plugin :status_handler
|
105
|
-
|
106
|
-
status_handler(404) do
|
107
|
-
"not found"
|
108
|
-
end
|
109
|
-
|
110
|
-
o = Object.new
|
111
|
-
def o.each; end
|
112
|
-
route do |r|
|
113
|
-
r.halt [404, {}, o]
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
body.must_equal ''
|
118
|
-
end
|
119
|
-
|
120
|
-
it "does not modify behavior if body is not an empty array" do
|
121
|
-
app(:bare) do
|
122
|
-
plugin :status_handler
|
123
|
-
|
124
|
-
status_handler(404) do
|
125
|
-
"not found"
|
126
|
-
end
|
127
|
-
|
128
|
-
route do |r|
|
129
|
-
response.status = 404
|
130
|
-
response.write 'a'
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
body.must_equal 'a'
|
135
|
-
end
|
136
|
-
|
137
|
-
it "does not allow further status handlers to be added after freezing" do
|
138
|
-
app(:bare) do
|
139
|
-
plugin :status_handler
|
140
|
-
|
141
|
-
status_handler(404) do
|
142
|
-
"not found"
|
143
|
-
end
|
144
|
-
|
145
|
-
route{}
|
146
|
-
end
|
147
|
-
|
148
|
-
app.freeze
|
149
|
-
|
150
|
-
body.must_equal 'not found'
|
151
|
-
status.must_equal 404
|
152
|
-
|
153
|
-
proc{app.status_handler(404) { "blah" }}.must_raise
|
154
|
-
|
155
|
-
body.must_equal 'not found'
|
156
|
-
end
|
157
|
-
|
158
|
-
end
|
@@ -1,246 +0,0 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
|
-
describe "streaming plugin" do
|
4
|
-
it "adds stream method for streaming responses" do
|
5
|
-
app(:streaming) do |r|
|
6
|
-
stream do |out|
|
7
|
-
%w'a b c'.each do |v|
|
8
|
-
(out << v).must_equal out
|
9
|
-
out.write(v).must_equal 1
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
s, h, b = req
|
15
|
-
s.must_equal 200
|
16
|
-
h.must_equal('Content-Type'=>'text/html')
|
17
|
-
b.to_a.must_equal %w'a a b b c c'
|
18
|
-
end
|
19
|
-
|
20
|
-
it "works with IO.copy_stream" do
|
21
|
-
app(:streaming) do |r|
|
22
|
-
stream do |out|
|
23
|
-
%w'a b c'.each{|v| IO.copy_stream(StringIO.new(v), out) }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
s, h, b = req
|
28
|
-
s.must_equal 200
|
29
|
-
h.must_equal('Content-Type'=>'text/html')
|
30
|
-
# dup as copy_stream reuses the buffer
|
31
|
-
b.map(&:dup).must_equal %w'a b c'
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should handle errors when streaming, and run callbacks" do
|
35
|
-
a = []
|
36
|
-
app(:streaming) do |r|
|
37
|
-
stream(:callback=>proc{a << 'e'}) do |out|
|
38
|
-
%w'a b'.each{|v| out << v}
|
39
|
-
raise Roda::RodaError, 'foo'
|
40
|
-
out << 'c'
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
s, h, b = req
|
45
|
-
s.must_equal 200
|
46
|
-
h.must_equal('Content-Type'=>'text/html')
|
47
|
-
proc{b.each{|v| a << v}}.must_raise(Roda::RodaError)
|
48
|
-
a.must_equal %w'a b e'
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should handle :loop option to loop" do
|
52
|
-
a = []
|
53
|
-
app(:streaming) do |r|
|
54
|
-
b = %w'a b c'
|
55
|
-
stream(:loop=>true, :callback=>proc{a << 'e'}) do |out|
|
56
|
-
out << b.shift
|
57
|
-
raise Roda::RodaError, 'foo' if b.length == 1
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
s, h, b = req
|
62
|
-
s.must_equal 200
|
63
|
-
h.must_equal('Content-Type'=>'text/html')
|
64
|
-
proc{b.each{|v| a << v}}.must_raise(Roda::RodaError)
|
65
|
-
a.must_equal %w'a b e'
|
66
|
-
end
|
67
|
-
|
68
|
-
it "uses handle_stream_error for handling errors when streaming" do
|
69
|
-
a = []
|
70
|
-
app(:streaming) do |r|
|
71
|
-
b = %w'a b c'
|
72
|
-
stream(:loop=>true, :callback=>proc{a << 'e'}) do |out|
|
73
|
-
out << b.shift
|
74
|
-
raise Roda::RodaError, 'foo' if b.length == 1
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
app.send(:define_method, :handle_stream_error) do |error, out|
|
79
|
-
out << '1'
|
80
|
-
raise error
|
81
|
-
end
|
82
|
-
|
83
|
-
s, h, b = req
|
84
|
-
s.must_equal 200
|
85
|
-
h.must_equal('Content-Type'=>'text/html')
|
86
|
-
proc{b.each{|v| a << v}}.must_raise(Roda::RodaError)
|
87
|
-
a.must_equal %w'a b 1 e'
|
88
|
-
end
|
89
|
-
|
90
|
-
it "should allow closing the stream when handling an error" do
|
91
|
-
a = []
|
92
|
-
app(:streaming) do |r|
|
93
|
-
b = %w'a b c'
|
94
|
-
stream(:loop=>true, :callback=>proc{a << 'e'}) do |out|
|
95
|
-
out << b.shift
|
96
|
-
raise Roda::RodaError, 'foo' if b.length == 1
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
app.send(:define_method, :handle_stream_error) do |error, out|
|
101
|
-
out.close
|
102
|
-
end
|
103
|
-
|
104
|
-
s, h, b = req
|
105
|
-
s.must_equal 200
|
106
|
-
h.must_equal('Content-Type'=>'text/html')
|
107
|
-
b.each{|v| a << v}
|
108
|
-
a.must_equal %w'a b e'
|
109
|
-
end
|
110
|
-
|
111
|
-
it "should allow ignoring errors when streaming" do
|
112
|
-
a = []
|
113
|
-
b2 = %w'a b c'
|
114
|
-
|
115
|
-
app(:streaming) do |r|
|
116
|
-
stream(:loop=>true, :callback=>proc{a << 'e'}) do |out|
|
117
|
-
out << b2.shift
|
118
|
-
raise Roda::RodaError
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
app.send(:define_method, :handle_stream_error) do |error, out|
|
123
|
-
out << '1'
|
124
|
-
out.close if b2.empty?
|
125
|
-
end
|
126
|
-
|
127
|
-
s, h, b = req
|
128
|
-
s.must_equal 200
|
129
|
-
h.must_equal('Content-Type'=>'text/html')
|
130
|
-
b.each{|v| a << v}
|
131
|
-
a.must_equal %w'a 1 b 1 c 1 e'
|
132
|
-
end
|
133
|
-
|
134
|
-
describe "with :async" do
|
135
|
-
it "should stream in a thread" do
|
136
|
-
main_thread = Thread.current
|
137
|
-
minitest = self
|
138
|
-
app(:streaming) do |r|
|
139
|
-
stream(:async=>true) do |out|
|
140
|
-
minitest.refute_equal Thread.current, main_thread
|
141
|
-
%w'a b c'.each do |v|
|
142
|
-
out << v
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
s, h, b = req
|
148
|
-
s.must_equal 200
|
149
|
-
h.must_equal('Content-Type'=>'text/html')
|
150
|
-
b.to_a.must_equal %w'a b c'
|
151
|
-
end
|
152
|
-
|
153
|
-
it "should propagate exceptions" do
|
154
|
-
app(:streaming) do |r|
|
155
|
-
stream(:async=>true) do |out|
|
156
|
-
Thread.current.report_on_exception = false if Thread.current.respond_to?(:report_on_exception=)
|
157
|
-
%w'a b'.each{|v| out << v}
|
158
|
-
raise Roda::RodaError, 'foo'
|
159
|
-
out << 'c'
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
s, h, b = req
|
164
|
-
s.must_equal 200
|
165
|
-
h.must_equal('Content-Type'=>'text/html')
|
166
|
-
a = []
|
167
|
-
proc{b.each{|v| a << v}}.must_raise(Roda::RodaError)
|
168
|
-
a.must_equal %w'a b'
|
169
|
-
end
|
170
|
-
|
171
|
-
it "should terminate the thread on close" do
|
172
|
-
q = Queue.new
|
173
|
-
app(:streaming) do |r|
|
174
|
-
stream(:async=>true) do |out|
|
175
|
-
%w'a b c d e f g h i j'.each{|v| out << v}
|
176
|
-
q.deq
|
177
|
-
out << 'k'
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
*, b = req
|
182
|
-
e = b.enum_for(:each)
|
183
|
-
10.times{e.next}
|
184
|
-
b.close
|
185
|
-
q.enq 'x'
|
186
|
-
proc{e.next}.must_raise(StopIteration)
|
187
|
-
end
|
188
|
-
|
189
|
-
it "should still run callbacks on close" do
|
190
|
-
callback = false
|
191
|
-
app(:streaming) do |r|
|
192
|
-
stream(:async=>true, :callback=>proc{callback = true}) do |out|
|
193
|
-
%w'a b c'.each{|v| out << v}
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
*, b = req
|
198
|
-
b.close
|
199
|
-
callback.must_equal true
|
200
|
-
end
|
201
|
-
|
202
|
-
it "should apply backpressure by default" do
|
203
|
-
q = Queue.new
|
204
|
-
a = []
|
205
|
-
app(:streaming) do |r|
|
206
|
-
stream(:async=>true) do |out|
|
207
|
-
%w'a b c d e f g h i j'.each do |v|
|
208
|
-
out << v
|
209
|
-
a << v
|
210
|
-
end
|
211
|
-
|
212
|
-
q.enq 'x'
|
213
|
-
|
214
|
-
out << 'k'
|
215
|
-
a << 'k'
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
req
|
220
|
-
q.deq
|
221
|
-
a.must_equal %w'a b c d e f g h i j'
|
222
|
-
end
|
223
|
-
|
224
|
-
it "should handle :queue option to override queue" do
|
225
|
-
q = Queue.new
|
226
|
-
a = []
|
227
|
-
app(:streaming) do |r|
|
228
|
-
stream(:async=>true, queue: SizedQueue.new(5)) do |out|
|
229
|
-
%w'a b c d e'.each do |v|
|
230
|
-
out << v
|
231
|
-
a << v
|
232
|
-
end
|
233
|
-
|
234
|
-
q.enq 'x'
|
235
|
-
|
236
|
-
out << 'f'
|
237
|
-
a << 'f'
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
req
|
242
|
-
q.deq
|
243
|
-
a.must_equal %w'a b c d e'
|
244
|
-
end
|
245
|
-
end if RUBY_VERSION >= '2.3'
|
246
|
-
end
|