roda 3.28.0 → 3.29.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +10 -0
  3. data/README.rdoc +10 -0
  4. data/doc/release_notes/3.29.0.txt +15 -0
  5. data/lib/roda.rb +1 -0
  6. data/lib/roda/plugins/caching.rb +2 -0
  7. data/lib/roda/plugins/common_logger.rb +1 -1
  8. data/lib/roda/plugins/exception_page.rb +7 -1
  9. data/lib/roda/plugins/indifferent_params.rb +2 -0
  10. data/lib/roda/version.rb +1 -1
  11. metadata +4 -214
  12. data/Rakefile +0 -108
  13. data/doc/release_notes/1.0.0.txt +0 -329
  14. data/doc/release_notes/1.1.0.txt +0 -226
  15. data/doc/release_notes/1.2.0.txt +0 -406
  16. data/doc/release_notes/1.3.0.txt +0 -109
  17. data/doc/release_notes/2.0.0.txt +0 -75
  18. data/doc/release_notes/2.1.0.txt +0 -124
  19. data/doc/release_notes/2.10.0.txt +0 -27
  20. data/doc/release_notes/2.11.0.txt +0 -70
  21. data/doc/release_notes/2.12.0.txt +0 -40
  22. data/doc/release_notes/2.13.0.txt +0 -10
  23. data/doc/release_notes/2.14.0.txt +0 -44
  24. data/doc/release_notes/2.15.0.txt +0 -53
  25. data/doc/release_notes/2.16.0.txt +0 -48
  26. data/doc/release_notes/2.17.0.txt +0 -62
  27. data/doc/release_notes/2.18.0.txt +0 -69
  28. data/doc/release_notes/2.19.0.txt +0 -30
  29. data/doc/release_notes/2.2.0.txt +0 -97
  30. data/doc/release_notes/2.20.0.txt +0 -5
  31. data/doc/release_notes/2.21.0.txt +0 -17
  32. data/doc/release_notes/2.22.0.txt +0 -41
  33. data/doc/release_notes/2.23.0.txt +0 -29
  34. data/doc/release_notes/2.24.0.txt +0 -65
  35. data/doc/release_notes/2.25.0.txt +0 -14
  36. data/doc/release_notes/2.26.0.txt +0 -13
  37. data/doc/release_notes/2.27.0.txt +0 -56
  38. data/doc/release_notes/2.28.0.txt +0 -17
  39. data/doc/release_notes/2.29.0.txt +0 -156
  40. data/doc/release_notes/2.3.0.txt +0 -109
  41. data/doc/release_notes/2.4.0.txt +0 -55
  42. data/doc/release_notes/2.5.0.txt +0 -23
  43. data/doc/release_notes/2.5.1.txt +0 -4
  44. data/doc/release_notes/2.6.0.txt +0 -21
  45. data/doc/release_notes/2.7.0.txt +0 -75
  46. data/doc/release_notes/2.8.0.txt +0 -44
  47. data/doc/release_notes/2.9.0.txt +0 -6
  48. data/spec/all.rb +0 -1
  49. data/spec/assets/css/app.scss +0 -1
  50. data/spec/assets/css/no_access.css +0 -1
  51. data/spec/assets/css/raw.css +0 -1
  52. data/spec/assets/js/head/app.js +0 -1
  53. data/spec/composition_spec.rb +0 -31
  54. data/spec/define_roda_method_spec.rb +0 -274
  55. data/spec/env_spec.rb +0 -11
  56. data/spec/freeze_spec.rb +0 -37
  57. data/spec/integration_spec.rb +0 -209
  58. data/spec/matchers_spec.rb +0 -832
  59. data/spec/opts_spec.rb +0 -42
  60. data/spec/plugin/_after_hook_spec.rb +0 -19
  61. data/spec/plugin/all_verbs_spec.rb +0 -29
  62. data/spec/plugin/assets_preloading_spec.rb +0 -98
  63. data/spec/plugin/assets_spec.rb +0 -745
  64. data/spec/plugin/backtracking_array_spec.rb +0 -42
  65. data/spec/plugin/branch_locals_spec.rb +0 -106
  66. data/spec/plugin/caching_spec.rb +0 -337
  67. data/spec/plugin/chunked_spec.rb +0 -201
  68. data/spec/plugin/class_level_routing_spec.rb +0 -164
  69. data/spec/plugin/class_matchers_spec.rb +0 -40
  70. data/spec/plugin/common_logger_spec.rb +0 -85
  71. data/spec/plugin/content_for_spec.rb +0 -162
  72. data/spec/plugin/content_security_policy_spec.rb +0 -175
  73. data/spec/plugin/cookies_spec.rb +0 -51
  74. data/spec/plugin/csrf_spec.rb +0 -111
  75. data/spec/plugin/default_headers_spec.rb +0 -82
  76. data/spec/plugin/default_status_spec.rb +0 -95
  77. data/spec/plugin/delay_build_spec.rb +0 -23
  78. data/spec/plugin/delegate_spec.rb +0 -23
  79. data/spec/plugin/delete_empty_headers_spec.rb +0 -27
  80. data/spec/plugin/direct_call_spec.rb +0 -28
  81. data/spec/plugin/disallow_file_uploads_spec.rb +0 -25
  82. data/spec/plugin/drop_body_spec.rb +0 -24
  83. data/spec/plugin/early_hints_spec.rb +0 -19
  84. data/spec/plugin/empty_root_spec.rb +0 -14
  85. data/spec/plugin/environments_spec.rb +0 -42
  86. data/spec/plugin/error_email_spec.rb +0 -97
  87. data/spec/plugin/error_handler_spec.rb +0 -216
  88. data/spec/plugin/error_mail_spec.rb +0 -93
  89. data/spec/plugin/exception_page_spec.rb +0 -168
  90. data/spec/plugin/flash_spec.rb +0 -121
  91. data/spec/plugin/h_spec.rb +0 -11
  92. data/spec/plugin/halt_spec.rb +0 -119
  93. data/spec/plugin/hash_matcher_spec.rb +0 -27
  94. data/spec/plugin/hash_routes_spec.rb +0 -535
  95. data/spec/plugin/head_spec.rb +0 -52
  96. data/spec/plugin/header_matchers_spec.rb +0 -98
  97. data/spec/plugin/heartbeat_spec.rb +0 -74
  98. data/spec/plugin/hooks_spec.rb +0 -152
  99. data/spec/plugin/indifferent_params_spec.rb +0 -14
  100. data/spec/plugin/json_parser_spec.rb +0 -141
  101. data/spec/plugin/json_spec.rb +0 -83
  102. data/spec/plugin/mail_processor_spec.rb +0 -451
  103. data/spec/plugin/mailer_spec.rb +0 -282
  104. data/spec/plugin/match_affix_spec.rb +0 -43
  105. data/spec/plugin/match_hook_spec.rb +0 -79
  106. data/spec/plugin/middleware_spec.rb +0 -237
  107. data/spec/plugin/middleware_stack_spec.rb +0 -81
  108. data/spec/plugin/module_include_spec.rb +0 -48
  109. data/spec/plugin/multi_route_spec.rb +0 -268
  110. data/spec/plugin/multi_run_spec.rb +0 -87
  111. data/spec/plugin/multi_view_spec.rb +0 -50
  112. data/spec/plugin/multibyte_string_matcher_spec.rb +0 -44
  113. data/spec/plugin/named_templates_spec.rb +0 -96
  114. data/spec/plugin/not_allowed_spec.rb +0 -69
  115. data/spec/plugin/not_found_spec.rb +0 -128
  116. data/spec/plugin/optimized_string_matchers_spec.rb +0 -43
  117. data/spec/plugin/padrino_render_spec.rb +0 -34
  118. data/spec/plugin/param_matchers_spec.rb +0 -69
  119. data/spec/plugin/params_capturing_spec.rb +0 -33
  120. data/spec/plugin/partials_spec.rb +0 -43
  121. data/spec/plugin/pass_spec.rb +0 -29
  122. data/spec/plugin/path_matchers_spec.rb +0 -42
  123. data/spec/plugin/path_rewriter_spec.rb +0 -45
  124. data/spec/plugin/path_spec.rb +0 -222
  125. data/spec/plugin/placeholder_string_matchers_spec.rb +0 -126
  126. data/spec/plugin/precompile_templates_spec.rb +0 -61
  127. data/spec/plugin/public_spec.rb +0 -85
  128. data/spec/plugin/render_each_spec.rb +0 -82
  129. data/spec/plugin/render_locals_spec.rb +0 -114
  130. data/spec/plugin/render_spec.rb +0 -912
  131. data/spec/plugin/request_aref_spec.rb +0 -51
  132. data/spec/plugin/request_headers_spec.rb +0 -39
  133. data/spec/plugin/response_request_spec.rb +0 -43
  134. data/spec/plugin/route_block_args_spec.rb +0 -86
  135. data/spec/plugin/route_csrf_spec.rb +0 -305
  136. data/spec/plugin/run_append_slash_spec.rb +0 -77
  137. data/spec/plugin/run_handler_spec.rb +0 -53
  138. data/spec/plugin/sessions_spec.rb +0 -452
  139. data/spec/plugin/shared_vars_spec.rb +0 -45
  140. data/spec/plugin/sinatra_helpers_spec.rb +0 -537
  141. data/spec/plugin/slash_path_empty_spec.rb +0 -22
  142. data/spec/plugin/static_routing_spec.rb +0 -192
  143. data/spec/plugin/static_spec.rb +0 -30
  144. data/spec/plugin/status_303_spec.rb +0 -28
  145. data/spec/plugin/status_handler_spec.rb +0 -158
  146. data/spec/plugin/streaming_spec.rb +0 -246
  147. data/spec/plugin/strip_path_prefix_spec.rb +0 -24
  148. data/spec/plugin/symbol_matchers_spec.rb +0 -51
  149. data/spec/plugin/symbol_status_spec.rb +0 -25
  150. data/spec/plugin/symbol_views_spec.rb +0 -32
  151. data/spec/plugin/timestamp_public_spec.rb +0 -85
  152. data/spec/plugin/type_routing_spec.rb +0 -348
  153. data/spec/plugin/typecast_params_spec.rb +0 -1370
  154. data/spec/plugin/unescape_path_spec.rb +0 -22
  155. data/spec/plugin/view_options_spec.rb +0 -170
  156. data/spec/plugin_spec.rb +0 -71
  157. data/spec/redirect_spec.rb +0 -41
  158. data/spec/request_spec.rb +0 -97
  159. data/spec/response_spec.rb +0 -199
  160. data/spec/route_spec.rb +0 -39
  161. data/spec/session_middleware_spec.rb +0 -129
  162. data/spec/session_spec.rb +0 -37
  163. data/spec/spec_helper.rb +0 -137
  164. data/spec/version_spec.rb +0 -14
  165. data/spec/views/_test.erb +0 -1
  166. data/spec/views/a.erb +0 -1
  167. data/spec/views/a.rdoc +0 -2
  168. data/spec/views/about.erb +0 -1
  169. data/spec/views/about.str +0 -1
  170. data/spec/views/about/_test.css.gz +0 -0
  171. data/spec/views/about/_test.erb +0 -1
  172. data/spec/views/about/_test.erb.gz +0 -0
  173. data/spec/views/about/comp_test.erb +0 -1
  174. data/spec/views/b.erb +0 -1
  175. data/spec/views/c.erb +0 -1
  176. data/spec/views/comp_layout.erb +0 -1
  177. data/spec/views/comp_test.erb +0 -1
  178. data/spec/views/content-yield.erb +0 -1
  179. data/spec/views/each.str +0 -1
  180. data/spec/views/home.erb +0 -2
  181. data/spec/views/home.str +0 -2
  182. data/spec/views/iv.erb +0 -1
  183. data/spec/views/layout-alternative.erb +0 -2
  184. data/spec/views/layout-yield.erb +0 -3
  185. data/spec/views/layout.erb +0 -2
  186. data/spec/views/layout.str +0 -2
  187. data/spec/views/multiple-layout.erb +0 -1
  188. 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
@@ -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