actionpack 7.2.2 → 8.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +83 -129
  3. data/lib/abstract_controller/helpers.rb +0 -2
  4. data/lib/action_controller/metal/allow_browser.rb +1 -1
  5. data/lib/action_controller/metal/conditional_get.rb +5 -1
  6. data/lib/action_controller/metal/http_authentication.rb +4 -1
  7. data/lib/action_controller/metal/instrumentation.rb +1 -2
  8. data/lib/action_controller/metal/live.rb +10 -2
  9. data/lib/action_controller/metal/rate_limiting.rb +13 -4
  10. data/lib/action_controller/metal/renderers.rb +2 -1
  11. data/lib/action_controller/metal/streaming.rb +5 -84
  12. data/lib/action_controller/metal/strong_parameters.rb +274 -73
  13. data/lib/action_controller/railtie.rb +1 -1
  14. data/lib/action_controller/test_case.rb +2 -0
  15. data/lib/action_dispatch/http/cache.rb +27 -10
  16. data/lib/action_dispatch/http/content_security_policy.rb +9 -4
  17. data/lib/action_dispatch/http/filter_parameters.rb +4 -9
  18. data/lib/action_dispatch/http/filter_redirect.rb +2 -9
  19. data/lib/action_dispatch/http/permissions_policy.rb +2 -0
  20. data/lib/action_dispatch/http/request.rb +4 -2
  21. data/lib/action_dispatch/journey/parser.rb +99 -196
  22. data/lib/action_dispatch/journey/scanner.rb +40 -42
  23. data/lib/action_dispatch/middleware/cookies.rb +4 -2
  24. data/lib/action_dispatch/middleware/debug_exceptions.rb +16 -3
  25. data/lib/action_dispatch/middleware/request_id.rb +2 -1
  26. data/lib/action_dispatch/middleware/ssl.rb +13 -3
  27. data/lib/action_dispatch/railtie.rb +2 -0
  28. data/lib/action_dispatch/routing/inspector.rb +1 -1
  29. data/lib/action_dispatch/routing/mapper.rb +25 -17
  30. data/lib/action_dispatch/routing/route_set.rb +18 -6
  31. data/lib/action_dispatch/system_testing/browser.rb +12 -21
  32. data/lib/action_dispatch.rb +0 -4
  33. data/lib/action_pack/gem_version.rb +4 -4
  34. metadata +12 -34
  35. data/lib/action_dispatch/journey/parser.y +0 -50
  36. data/lib/action_dispatch/journey/parser_extras.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 805d9e62e9937e7cd8f12e22e2b806035577bd452e5ce321f75372c7f152edd7
4
- data.tar.gz: 0fb9629eae17852ae5eb92ad885f79a6938e36e8b72dfe4ce775920d8d0c153c
3
+ metadata.gz: 4392b60cf6c4af7ed943daf2c4e438440689b8f869a859510b1e0e5808204cf2
4
+ data.tar.gz: ee9993b25b397af527f1730dc439a0425a81d4b03afb148e310dac8862003261
5
5
  SHA512:
6
- metadata.gz: ed08caeeb60bf9f444ddca5eafb519eab94c8475e0452ba146b98585d3f426f0444730e05f5a1e40583b5237e1ef535cad62c8d92bc96ac62e73987c19aed8a8
7
- data.tar.gz: 85304714962564e3997fad42e395efe05061bf95d5cc9ef89394d53f99e899862f93a7ff38d12e16c232d7b7ab39ea012268b3f0b7214ed373c9fd39c5608e91
6
+ metadata.gz: 2063ad6ca3243b066226af6a1d1ad616d808c48a18f80df374d02b064ad4839a971e4eff804321621d910111829b0c1130b5a05f5a44afabb380ec9f7d5985b7
7
+ data.tar.gz: f3f1e1ce84c47654f69cf3f3ada2afa48e412dac1b7a5abd10c4d0fc34b66b7574f2454410c323cfa26a000005da585815db8a27dc3f1e9c2a71a504b0f3021d
data/CHANGELOG.md CHANGED
@@ -1,181 +1,135 @@
1
- ## Rails 7.2.2 (October 30, 2024) ##
1
+ ## Rails 8.0.0.beta1 (September 26, 2024) ##
2
2
 
3
3
  * Fix non-GET requests not updating cookies in `ActionController::TestCase`.
4
4
 
5
5
  *Jon Moss*, *Hartley McGuire*
6
6
 
7
+ * Update `ActionController::Live` to use a thread-pool to reuse threads across requests.
7
8
 
8
- ## Rails 7.2.1.2 (October 23, 2024) ##
9
+ *Adam Renberg Tamm*
9
10
 
10
- * No changes.
11
+ * Introduce safer, more explicit params handling method with `params#expect` such that
12
+ `params.expect(table: [ :attr ])` replaces `params.require(:table).permit(:attr)`
11
13
 
14
+ Ensures params are filtered with consideration for the expected
15
+ types of values, improving handling of params and avoiding ignorable
16
+ errors caused by params tampering.
12
17
 
13
- ## Rails 7.2.1.1 (October 15, 2024) ##
18
+ ```ruby
19
+ # If the url is altered to ?person=hacked
20
+ # Before
21
+ params.require(:person).permit(:name, :age, pets: [:name])
22
+ # raises NoMethodError, causing a 500 and potential error reporting
23
+
24
+ # After
25
+ params.expect(person: [ :name, :age, pets: [[:name]] ])
26
+ # raises ActionController::ParameterMissing, correctly returning a 400 error
27
+ ```
14
28
 
15
- * Avoid regex backtracking in HTTP Token authentication
29
+ You may also notice the new double array `[[:name]]`. In order to
30
+ declare when a param is expected to be an array of parameter hashes,
31
+ this new double array syntax is used to explicitly declare an array.
32
+ `expect` requires you to declare expected arrays in this way, and will
33
+ ignore arrays that are passed when, for example, `pet: [:name]` is used.
16
34
 
17
- [CVE-2024-47887]
35
+ In order to preserve compatibility, `permit` does not adopt the new
36
+ double array syntax and is therefore more permissive about unexpected
37
+ types. Using `expect` everywhere is recommended.
18
38
 
19
- *John Hawthorn*
39
+ We suggest replacing `params.require(:person).permit(:name, :age)`
40
+ with the direct replacement `params.expect(person: [:name, :age])`
41
+ to prevent external users from manipulating params to trigger 500
42
+ errors. A 400 error will be returned instead, using public/400.html
20
43
 
21
- * Avoid regex backtracking in query parameter filtering
44
+ Usage of `params.require(:id)` should likewise be replaced with
45
+ `params.expect(:id)` which is designed to ensure that `params[:id]`
46
+ is a scalar and not an array or hash, also requiring the param.
22
47
 
23
- [CVE-2024-41128]
48
+ ```ruby
49
+ # Before
50
+ User.find(params.require(:id)) # allows an array, altering behavior
24
51
 
25
- *John Hawthorn*
52
+ # After
53
+ User.find(params.expect(:id)) # expect only returns non-blank permitted scalars (excludes Hash, Array, nil, "", etc)
54
+ ```
26
55
 
56
+ *Martin Emde*
27
57
 
28
- ## Rails 7.2.1 (August 22, 2024) ##
58
+ * System Testing: Disable Chrome's search engine choice by default in system tests.
59
+
60
+ *glaszig*
29
61
 
30
62
  * Fix `Request#raw_post` raising `NoMethodError` when `rack.input` is `nil`.
31
63
 
32
64
  *Hartley McGuire*
33
65
 
66
+ * Remove `racc` dependency by manually writing `ActionDispatch::Journey::Scanner`.
34
67
 
35
- ## Rails 7.2.0 (August 09, 2024) ##
36
-
37
- * Allow bots to ignore `allow_browser`.
38
-
39
- *Matthew Nguyen*
40
-
41
- * Include the HTTP Permissions-Policy on non-HTML Content-Types
42
- [CVE-2024-28103]
43
-
44
- *Aaron Patterson*, *Zack Deveau*
45
-
46
- * Fix `Mime::Type.parse` handling type parameters for HTTP Accept headers.
47
-
48
- *Taylor Chaparro*
49
-
50
- * Fix the error page that is displayed when a view template is missing to account for nested controller paths in the
51
- suggested correct location for the missing template.
52
-
53
- *Joshua Young*
54
-
55
- * Add `save_and_open_page` helper to `IntegrationTest`.
56
-
57
- `save_and_open_page` is a helpful helper to keep a short feedback loop when working on system tests.
58
- A similar helper with matching signature has been added to integration tests.
59
-
60
- *Joé Dupuis*
61
-
62
- * Fix a regression in 7.1.3 passing a `to:` option without a controller when the controller is already defined by a scope.
63
-
64
- ```ruby
65
- Rails.application.routes.draw do
66
- controller :home do
67
- get "recent", to: "recent_posts"
68
- end
69
- end
70
- ```
71
-
72
- *Étienne Barrié*
73
-
74
- * Request Forgery takes relative paths into account.
68
+ *Gannon McGibbon*
75
69
 
76
- *Stefan Wienert*
70
+ * Speed up `ActionDispatch::Routing::Mapper::Scope#[]` by merging frame hashes.
77
71
 
78
- * Add ".test" as a default allowed host in development to ensure smooth golden-path setup with puma.dev.
72
+ *Gannon McGibbon*
79
73
 
80
- *DHH*
74
+ * Allow bots to ignore `allow_browser`.
81
75
 
82
- * Add `allow_browser` to set minimum browser versions for the application.
76
+ *Matthew Nguyen*
83
77
 
84
- A browser that's blocked will by default be served the file in `public/406-unsupported-browser.html` with a HTTP status code of "406 Not Acceptable".
78
+ * Deprecate drawing routes with multiple paths to make routing faster.
79
+ You may use `with_options` or a loop to make drawing multiple paths easier.
85
80
 
86
81
  ```ruby
87
- class ApplicationController < ActionController::Base
88
- # Allow only browsers natively supporting webp images, web push, badges, import maps, CSS nesting + :has
89
- allow_browser versions: :modern
90
- end
91
-
92
- class ApplicationController < ActionController::Base
93
- # All versions of Chrome and Opera will be allowed, but no versions of "internet explorer" (ie). Safari needs to be 16.4+ and Firefox 121+.
94
- allow_browser versions: { safari: 16.4, firefox: 121, ie: false }
95
- end
96
-
97
- class MessagesController < ApplicationController
98
- # In addition to the browsers blocked by ApplicationController, also block Opera below 104 and Chrome below 119 for the show action.
99
- allow_browser versions: { opera: 104, chrome: 119 }, only: :show
100
- end
101
- ```
102
-
103
- *DHH*
104
-
105
- * Add rate limiting API.
82
+ # Before
83
+ get "/users", "/other_path", to: "users#index"
106
84
 
107
- ```ruby
108
- class SessionsController < ApplicationController
109
- rate_limit to: 10, within: 3.minutes, only: :create
110
- end
111
-
112
- class SignupsController < ApplicationController
113
- rate_limit to: 1000, within: 10.seconds,
114
- by: -> { request.domain }, with: -> { redirect_to busy_controller_url, alert: "Too many signups!" }, only: :new
115
- end
85
+ # After
86
+ get "/users", to: "users#index"
87
+ get "/other_path", to: "users#index"
116
88
  ```
117
89
 
118
- *DHH*, *Jean Boussier*
119
-
120
- * Add `image/svg+xml` to the compressible content types of `ActionDispatch::Static`.
121
-
122
- *Georg Ledermann*
123
-
124
- * Add instrumentation for `ActionController::Live#send_stream`.
125
-
126
- Allows subscribing to `send_stream` events. The event payload contains the filename, disposition, and type.
127
-
128
- *Hannah Ramadan*
129
-
130
- * Add support for `with_routing` test helper in `ActionDispatch::IntegrationTest`.
131
-
132
90
  *Gannon McGibbon*
133
91
 
134
- * Remove deprecated support to set `Rails.application.config.action_dispatch.show_exceptions` to `true` and `false`.
135
-
136
- *Rafael Mendonça França*
137
-
138
- * Remove deprecated `speaker`, `vibrate`, and `vr` permissions policy directives.
139
-
140
- *Rafael Mendonça França*
141
-
142
- * Remove deprecated `Rails.application.config.action_dispatch.return_only_request_media_type_on_content_type`.
92
+ * Make `http_cache_forever` use `immutable: true`
143
93
 
144
- *Rafael Mendonça França*
94
+ *Nate Matykiewicz*
145
95
 
146
- * Deprecate `Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality`.
96
+ * Add `config.action_dispatch.strict_freshness`.
147
97
 
148
- *Rafael Mendonça França*
98
+ When set to `true`, the `ETag` header takes precedence over the `Last-Modified` header when both are present,
99
+ as specified by RFC 7232, Section 6.
149
100
 
150
- * Remove deprecated comparison between `ActionController::Parameters` and `Hash`.
101
+ Defaults to `false` to maintain compatibility with previous versions of Rails, but is enabled as part of
102
+ Rails 8.0 defaults.
151
103
 
152
- *Rafael Mendonça França*
104
+ *heka1024*
153
105
 
154
- * Remove deprecated constant `AbstractController::Helpers::MissingHelperError`.
106
+ * Support `immutable` directive in Cache-Control
155
107
 
156
- *Rafael Mendonça França*
157
-
158
- * Fix a race condition that could cause a `Text file busy - chromedriver`
159
- error with parallel system tests.
108
+ ```ruby
109
+ expires_in 1.minute, public: true, immutable: true
110
+ # Cache-Control: public, max-age=60, immutable
111
+ ```
160
112
 
161
- *Matt Brictson*
113
+ *heka1024*
162
114
 
163
- * Add `racc` as a dependency since it will become a bundled gem in Ruby 3.4.0
115
+ * Add `:wasm_unsafe_eval` mapping for `content_security_policy`
164
116
 
165
- *Hartley McGuire*
166
- * Remove deprecated constant `ActionDispatch::IllegalStateError`.
117
+ ```ruby
118
+ # Before
119
+ policy.script_src "'wasm-unsafe-eval'"
167
120
 
168
- *Rafael Mendonça França*
121
+ # After
122
+ policy.script_src :wasm_unsafe_eval
123
+ ```
169
124
 
170
- * Add parameter filter capability for redirect locations.
125
+ *Joe Haig*
171
126
 
172
- It uses the `config.filter_parameters` to match what needs to be filtered.
173
- The result would be like this:
127
+ * Add `display_capture` and `keyboard_map` in `permissions_policy`
174
128
 
175
- Redirected to http://secret.foo.bar?username=roque&password=[FILTERED]
129
+ *Cyril Blaecke*
176
130
 
177
- Fixes #14055.
131
+ * Add `connect` route helper.
178
132
 
179
- *Roque Pinel*, *Trevor Turk*, *tonytonyjan*
133
+ *Samuel Williams*
180
134
 
181
- Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/actionpack/CHANGELOG.md) for previous changes.
135
+ Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/actionpack/CHANGELOG.md) for previous changes.
@@ -104,7 +104,6 @@ module AbstractController
104
104
  # Declare a controller method as a helper. For example, the following
105
105
  # makes the `current_user` and `logged_in?` controller methods available
106
106
  # to the view:
107
- #
108
107
  # class ApplicationController < ActionController::Base
109
108
  # helper_method :current_user, :logged_in?
110
109
  #
@@ -119,7 +118,6 @@ module AbstractController
119
118
  # end
120
119
  #
121
120
  # In a view:
122
- #
123
121
  # <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
124
122
  #
125
123
  # #### Parameters
@@ -60,7 +60,7 @@ module ActionController # :nodoc:
60
60
  end
61
61
  end
62
62
 
63
- class BrowserBlocker # :nodoc:
63
+ class BrowserBlocker
64
64
  SETS = {
65
65
  modern: { safari: 17.2, chrome: 120, firefox: 121, opera: 106, ie: false }
66
66
  }
@@ -259,6 +259,9 @@ module ActionController
259
259
  # `:stale_if_error`
260
260
  # : Sets the value of the `stale-if-error` directive.
261
261
  #
262
+ # `:immutable`
263
+ # : If true, adds the `immutable` directive.
264
+ #
262
265
  #
263
266
  # Any additional key-value pairs are concatenated as directives. For a list of
264
267
  # supported `Cache-Control` directives, see the [article on
@@ -292,6 +295,7 @@ module ActionController
292
295
  must_revalidate: options.delete(:must_revalidate),
293
296
  stale_while_revalidate: options.delete(:stale_while_revalidate),
294
297
  stale_if_error: options.delete(:stale_if_error),
298
+ immutable: options.delete(:immutable),
295
299
  )
296
300
  options.delete(:private)
297
301
 
@@ -315,7 +319,7 @@ module ActionController
315
319
  # user's web browser. To allow proxies to cache the response, set `true` to
316
320
  # indicate that they can serve the cached response to all users.
317
321
  def http_cache_forever(public: false)
318
- expires_in 100.years, public: public
322
+ expires_in 100.years, public: public, immutable: true
319
323
 
320
324
  yield if stale?(etag: request.fullpath,
321
325
  last_modified: Time.new(2011, 1, 1).utc,
@@ -513,11 +513,14 @@ module ActionController
513
513
  array_params.each { |param| (param[1] || +"").gsub! %r/^"|"$/, "" }
514
514
  end
515
515
 
516
+ WHITESPACED_AUTHN_PAIR_DELIMITERS = /\s*#{AUTHN_PAIR_DELIMITERS}\s*/
517
+ private_constant :WHITESPACED_AUTHN_PAIR_DELIMITERS
518
+
516
519
  # This method takes an authorization body and splits up the key-value pairs by
517
520
  # the standardized `:`, `;`, or `\t` delimiters defined in
518
521
  # `AUTHN_PAIR_DELIMITERS`.
519
522
  def raw_params(auth)
520
- _raw_params = auth.sub(TOKEN_REGEX, "").split(AUTHN_PAIR_DELIMITERS).map(&:strip)
523
+ _raw_params = auth.sub(TOKEN_REGEX, "").split(WHITESPACED_AUTHN_PAIR_DELIMITERS)
521
524
  _raw_params.reject!(&:empty?)
522
525
 
523
526
  if !_raw_params.first&.start_with?(TOKEN_KEY)
@@ -2,7 +2,6 @@
2
2
 
3
3
  # :markup: markdown
4
4
 
5
- require "benchmark"
6
5
  require "abstract_controller/logger"
7
6
 
8
7
  module ActionController
@@ -29,7 +28,7 @@ module ActionController
29
28
  def render(*)
30
29
  render_output = nil
31
30
  self.view_runtime = cleanup_view_runtime do
32
- Benchmark.ms { render_output = super }
31
+ ActiveSupport::Benchmark.realtime(:float_millisecond) { render_output = super }
33
32
  end
34
33
  render_output
35
34
  end
@@ -307,6 +307,10 @@ module ActionController
307
307
  error = e
308
308
  end
309
309
  ensure
310
+ # Ensure we clean up any thread locals we copied so that the thread can reused.
311
+ ActiveSupport::IsolatedExecutionState.clear
312
+ locals.each { |k, _| t2[k] = nil }
313
+
310
314
  @_response.commit!
311
315
  end
312
316
  end
@@ -371,11 +375,15 @@ module ActionController
371
375
  # data from the response bodies. Nobody should call this method except in Rails
372
376
  # internals. Seriously!
373
377
  def new_controller_thread # :nodoc:
374
- Thread.new {
378
+ ActionController::Live.live_thread_pool_executor.post do
375
379
  t2 = Thread.current
376
380
  t2.abort_on_exception = true
377
381
  yield
378
- }
382
+ end
383
+ end
384
+
385
+ def self.live_thread_pool_executor
386
+ @live_thread_pool_executor ||= Concurrent::CachedThreadPool.new(name: "action_controller.live")
379
387
  end
380
388
 
381
389
  def log_error(exception)
@@ -29,6 +29,9 @@ module ActionController # :nodoc:
29
29
  # datastore as your general caches, you can pass a custom store in the `store`
30
30
  # parameter.
31
31
  #
32
+ # If you want to use multiple rate limits per controller, you need to give each of
33
+ # them and explicit name via the `name:` option.
34
+ #
32
35
  # Examples:
33
36
  #
34
37
  # class SessionsController < ApplicationController
@@ -44,14 +47,20 @@ module ActionController # :nodoc:
44
47
  # RATE_LIMIT_STORE = ActiveSupport::Cache::RedisCacheStore.new(url: ENV["REDIS_URL"])
45
48
  # rate_limit to: 10, within: 3.minutes, store: RATE_LIMIT_STORE
46
49
  # end
47
- def rate_limit(to:, within:, by: -> { request.remote_ip }, with: -> { head :too_many_requests }, store: cache_store, **options)
48
- before_action -> { rate_limiting(to: to, within: within, by: by, with: with, store: store) }, **options
50
+ #
51
+ # class SessionsController < ApplicationController
52
+ # rate_limit to: 3, within: 2.seconds, name: "short-term"
53
+ # rate_limit to: 10, within: 5.minutes, name: "long-term"
54
+ # end
55
+ def rate_limit(to:, within:, by: -> { request.remote_ip }, with: -> { head :too_many_requests }, store: cache_store, name: nil, **options)
56
+ before_action -> { rate_limiting(to: to, within: within, by: by, with: with, store: store, name: name) }, **options
49
57
  end
50
58
  end
51
59
 
52
60
  private
53
- def rate_limiting(to:, within:, by:, with:, store:)
54
- count = store.increment("rate-limit:#{controller_path}:#{instance_exec(&by)}", 1, expires_in: within)
61
+ def rate_limiting(to:, within:, by:, with:, store:, name:)
62
+ cache_key = ["rate-limit", controller_path, name, instance_exec(&by)].compact.join(":")
63
+ count = store.increment(cache_key, 1, expires_in: within)
55
64
  if count && count > to
56
65
  ActiveSupport::Notifications.instrument("rate_limit.action_controller", request: request) do
57
66
  instance_exec(&with)
@@ -154,7 +154,8 @@ module ActionController
154
154
  end
155
155
 
156
156
  add :json do |json, options|
157
- json = json.to_json(options) unless json.kind_of?(String)
157
+ json_options = options.except(:callback, :content_type, :status)
158
+ json = json.to_json(json_options) unless json.kind_of?(String)
158
159
 
159
160
  if options[:callback].present?
160
161
  if media_type.nil? || media_type == Mime[:json]
@@ -165,95 +165,16 @@ module ActionController # :nodoc:
165
165
  #
166
166
  # ## Web server support
167
167
  #
168
- # Not all web servers support streaming out-of-the-box. You need to check the
169
- # instructions for each of them.
170
- #
171
- # #### Unicorn
172
- #
173
- # Unicorn supports streaming but it needs to be configured. For this, you need
174
- # to create a config file as follow:
175
- #
176
- # # unicorn.config.rb
177
- # listen 3000, tcp_nopush: false
178
- #
179
- # And use it on initialization:
180
- #
181
- # unicorn_rails --config-file unicorn.config.rb
182
- #
183
- # You may also want to configure other parameters like `:tcp_nodelay`.
184
- #
185
- # For more information, please check the
186
- # [documentation](https://bogomips.org/unicorn/Unicorn/Configurator.html#method-
187
- # i-listen).
188
- #
189
- # If you are using Unicorn with NGINX, you may need to tweak NGINX. Streaming
190
- # should work out of the box on Rainbows.
191
- #
192
- # #### Passenger
193
- #
194
- # Phusion Passenger with NGINX, offers two streaming mechanisms out of the box.
195
- #
196
- # 1. NGINX response buffering mechanism which is dependent on the value of
197
- # `passenger_buffer_response` option (default is "off").
198
- # 2. Passenger buffering system which is always 'on' irrespective of the value
199
- # of `passenger_buffer_response`.
200
- #
201
- #
202
- # When `passenger_buffer_response` is turned "on", then streaming would be done
203
- # at the NGINX level which waits until the application is done sending the
204
- # response back to the client.
205
- #
206
- # For more information, please check the [documentation]
207
- # (https://www.phusionpassenger.com/docs/references/config_reference/nginx/#passenger_buffer_response).
168
+ # Rack 3+ compatible servers all support streaming.
208
169
  module Streaming
209
- class Body # :nodoc:
210
- TERM = "\r\n"
211
- TAIL = "0#{TERM}"
212
-
213
- # Store the response body to be chunked.
214
- def initialize(body)
215
- @body = body
216
- end
217
-
218
- # For each element yielded by the response body, yield the element in chunked
219
- # encoding.
220
- def each(&block)
221
- term = TERM
222
- @body.each do |chunk|
223
- size = chunk.bytesize
224
- next if size == 0
225
-
226
- yield [size.to_s(16), term, chunk.b, term].join
227
- end
228
- yield TAIL
229
- yield term
230
- end
231
-
232
- # Close the response body if the response body supports it.
233
- def close
234
- @body.close if @body.respond_to?(:close)
235
- end
236
- end
237
-
238
170
  private
239
- # Set proper cache control and transfer encoding when streaming
240
- def _process_options(options)
241
- super
242
- if options[:stream]
243
- if request.version == "HTTP/1.0"
244
- options.delete(:stream)
245
- else
246
- headers["Cache-Control"] ||= "no-cache"
247
- headers["Transfer-Encoding"] = "chunked"
248
- headers.delete("Content-Length")
249
- end
250
- end
251
- end
252
-
253
171
  # Call render_body if we are streaming instead of usual `render`.
254
172
  def _render_template(options)
255
173
  if options.delete(:stream)
256
- Body.new view_renderer.render_body(view_context, options)
174
+ # It shoudn't be necessary to set this.
175
+ headers["cache-control"] ||= "no-cache"
176
+
177
+ view_renderer.render_body(view_context, options)
257
178
  else
258
179
  super
259
180
  end