actionpack 7.2.2.1 → 8.0.1
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.md +123 -109
- data/lib/abstract_controller/rendering.rb +0 -1
- data/lib/action_controller/base.rb +1 -1
- data/lib/action_controller/form_builder.rb +3 -3
- data/lib/action_controller/metal/allow_browser.rb +11 -1
- data/lib/action_controller/metal/conditional_get.rb +5 -1
- data/lib/action_controller/metal/data_streaming.rb +4 -2
- data/lib/action_controller/metal/instrumentation.rb +1 -2
- data/lib/action_controller/metal/live.rb +13 -4
- data/lib/action_controller/metal/rate_limiting.rb +13 -4
- data/lib/action_controller/metal/redirecting.rb +2 -1
- data/lib/action_controller/metal/renderers.rb +2 -3
- data/lib/action_controller/metal/streaming.rb +5 -84
- data/lib/action_controller/metal/strong_parameters.rb +277 -89
- data/lib/action_controller/railtie.rb +1 -7
- data/lib/action_controller/test_case.rb +4 -2
- data/lib/action_dispatch/http/cache.rb +27 -10
- data/lib/action_dispatch/http/content_security_policy.rb +1 -0
- data/lib/action_dispatch/http/param_builder.rb +186 -0
- data/lib/action_dispatch/http/param_error.rb +26 -0
- data/lib/action_dispatch/http/permissions_policy.rb +2 -0
- data/lib/action_dispatch/http/query_parser.rb +53 -0
- data/lib/action_dispatch/http/request.rb +60 -16
- data/lib/action_dispatch/journey/parser.rb +99 -196
- data/lib/action_dispatch/journey/scanner.rb +44 -42
- data/lib/action_dispatch/middleware/cookies.rb +4 -2
- data/lib/action_dispatch/middleware/debug_exceptions.rb +16 -3
- data/lib/action_dispatch/middleware/debug_view.rb +0 -5
- data/lib/action_dispatch/middleware/exception_wrapper.rb +0 -6
- data/lib/action_dispatch/middleware/request_id.rb +2 -1
- data/lib/action_dispatch/middleware/ssl.rb +13 -3
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +0 -3
- data/lib/action_dispatch/railtie.rb +8 -0
- data/lib/action_dispatch/request/session.rb +1 -0
- data/lib/action_dispatch/request/utils.rb +9 -3
- data/lib/action_dispatch/routing/inspector.rb +1 -1
- data/lib/action_dispatch/routing/mapper.rb +90 -62
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -2
- data/lib/action_dispatch/routing/route_set.rb +20 -8
- data/lib/action_dispatch/system_testing/browser.rb +12 -21
- data/lib/action_dispatch/testing/assertions/response.rb +12 -2
- data/lib/action_dispatch/testing/assertions/routing.rb +4 -4
- data/lib/action_dispatch/testing/integration.rb +11 -1
- data/lib/action_dispatch/testing/test_process.rb +1 -2
- data/lib/action_dispatch.rb +6 -4
- data/lib/action_pack/gem_version.rb +4 -4
- metadata +15 -34
- data/lib/action_dispatch/journey/parser.y +0 -50
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e4dddbd1aa72f74822805435b23f5a92c79410529fc9e27048cb00d5092a612
|
4
|
+
data.tar.gz: 656ce52971952bc500713fe2892a980426ba65612907138c4ca0159951dbf338
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 814ef02acc2f6218c64045ba3e000fc379657b4cea039991a0fabe96792b0f77a9d843ba9592d04156c346d51b92c91535f4f9e7cde014ee03ffebe20e9292f7
|
7
|
+
data.tar.gz: 6568066218b50285be5baac02247119c5d296751e5f437ba6efe0131630f68cfe767656e0e7da485529747f562bebeb7282a8fa4d5a25e473af787da2a6e0c72
|
data/CHANGELOG.md
CHANGED
@@ -1,191 +1,205 @@
|
|
1
|
-
## Rails
|
1
|
+
## Rails 8.0.1 (December 13, 2024) ##
|
2
2
|
|
3
|
-
* Add
|
4
|
-
Developers should use multiple arguments, and different directive methods instead.
|
3
|
+
* Add `ActionDispatch::Request::Session#store` method to conform Rack spec.
|
5
4
|
|
6
|
-
|
5
|
+
*Yaroslav*
|
7
6
|
|
8
|
-
*Gannon McGibbon*
|
9
7
|
|
8
|
+
## Rails 8.0.0.1 (December 10, 2024) ##
|
10
9
|
|
11
|
-
|
10
|
+
* Add validation to content security policies to disallow spaces and semicolons.
|
11
|
+
Developers should use multiple arguments, and different directive methods instead.
|
12
12
|
|
13
|
-
|
13
|
+
[CVE-2024-54133]
|
14
14
|
|
15
|
-
*
|
15
|
+
*Gannon McGibbon*
|
16
16
|
|
17
17
|
|
18
|
-
## Rails
|
18
|
+
## Rails 8.0.0 (November 07, 2024) ##
|
19
19
|
|
20
20
|
* No changes.
|
21
21
|
|
22
22
|
|
23
|
-
## Rails
|
23
|
+
## Rails 8.0.0.rc2 (October 30, 2024) ##
|
24
24
|
|
25
|
-
*
|
25
|
+
* Fix routes with `::` in the path.
|
26
26
|
|
27
|
-
|
27
|
+
*Rafael Mendonça França*
|
28
28
|
|
29
|
-
|
29
|
+
* Maintain Rack 2 parameter parsing behaviour.
|
30
30
|
|
31
|
-
*
|
31
|
+
*Matthew Draper*
|
32
32
|
|
33
|
-
[CVE-2024-41128]
|
34
33
|
|
35
|
-
|
34
|
+
## Rails 8.0.0.rc1 (October 19, 2024) ##
|
36
35
|
|
36
|
+
* Remove `Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality`.
|
37
37
|
|
38
|
-
|
38
|
+
*Rafael Mendonça França*
|
39
39
|
|
40
|
-
*
|
40
|
+
* Improve `ActionController::TestCase` to expose a binary encoded `request.body`.
|
41
41
|
|
42
|
-
|
42
|
+
The rack spec clearly states:
|
43
43
|
|
44
|
+
> The input stream is an IO-like object which contains the raw HTTP POST data.
|
45
|
+
> When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode.
|
44
46
|
|
45
|
-
|
47
|
+
Until now its encoding was generally UTF-8, which doesn't accurately reflect production
|
48
|
+
behavior.
|
46
49
|
|
47
|
-
*
|
50
|
+
*Jean Boussier*
|
48
51
|
|
49
|
-
|
52
|
+
* Update `ActionController::AllowBrowser` to support passing method names to `:block`
|
50
53
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
*Aaron Patterson*, *Zack Deveau*
|
54
|
+
```ruby
|
55
|
+
class ApplicationController < ActionController::Base
|
56
|
+
allow_browser versions: :modern, block: :handle_outdated_browser
|
55
57
|
|
56
|
-
|
58
|
+
private
|
59
|
+
def handle_outdated_browser
|
60
|
+
render file: Rails.root.join("public/custom-error.html"), status: :not_acceptable
|
61
|
+
end
|
62
|
+
end
|
63
|
+
```
|
57
64
|
|
58
|
-
*
|
65
|
+
*Sean Doyle*
|
59
66
|
|
60
|
-
*
|
61
|
-
suggested correct location for the missing template.
|
67
|
+
* Raise an `ArgumentError` when invalid `:only` or `:except` options are passed into `#resource` and `#resources`.
|
62
68
|
|
63
69
|
*Joshua Young*
|
64
70
|
|
65
|
-
|
66
|
-
|
67
|
-
`save_and_open_page` is a helpful helper to keep a short feedback loop when working on system tests.
|
68
|
-
A similar helper with matching signature has been added to integration tests.
|
69
|
-
|
70
|
-
*Joé Dupuis*
|
71
|
-
|
72
|
-
* Fix a regression in 7.1.3 passing a `to:` option without a controller when the controller is already defined by a scope.
|
71
|
+
## Rails 8.0.0.beta1 (September 26, 2024) ##
|
73
72
|
|
74
|
-
|
75
|
-
Rails.application.routes.draw do
|
76
|
-
controller :home do
|
77
|
-
get "recent", to: "recent_posts"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
```
|
81
|
-
|
82
|
-
*Étienne Barrié*
|
83
|
-
|
84
|
-
* Request Forgery takes relative paths into account.
|
73
|
+
* Fix non-GET requests not updating cookies in `ActionController::TestCase`.
|
85
74
|
|
86
|
-
*
|
75
|
+
*Jon Moss*, *Hartley McGuire*
|
87
76
|
|
88
|
-
*
|
77
|
+
* Update `ActionController::Live` to use a thread-pool to reuse threads across requests.
|
89
78
|
|
90
|
-
*
|
79
|
+
*Adam Renberg Tamm*
|
91
80
|
|
92
|
-
*
|
81
|
+
* Introduce safer, more explicit params handling method with `params#expect` such that
|
82
|
+
`params.expect(table: [ :attr ])` replaces `params.require(:table).permit(:attr)`
|
93
83
|
|
94
|
-
|
84
|
+
Ensures params are filtered with consideration for the expected
|
85
|
+
types of values, improving handling of params and avoiding ignorable
|
86
|
+
errors caused by params tampering.
|
95
87
|
|
96
88
|
```ruby
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
89
|
+
# If the url is altered to ?person=hacked
|
90
|
+
# Before
|
91
|
+
params.require(:person).permit(:name, :age, pets: [:name])
|
92
|
+
# raises NoMethodError, causing a 500 and potential error reporting
|
93
|
+
|
94
|
+
# After
|
95
|
+
params.expect(person: [ :name, :age, pets: [[:name]] ])
|
96
|
+
# raises ActionController::ParameterMissing, correctly returning a 400 error
|
97
|
+
```
|
101
98
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
99
|
+
You may also notice the new double array `[[:name]]`. In order to
|
100
|
+
declare when a param is expected to be an array of parameter hashes,
|
101
|
+
this new double array syntax is used to explicitly declare an array.
|
102
|
+
`expect` requires you to declare expected arrays in this way, and will
|
103
|
+
ignore arrays that are passed when, for example, `pet: [:name]` is used.
|
106
104
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
end
|
111
|
-
```
|
105
|
+
In order to preserve compatibility, `permit` does not adopt the new
|
106
|
+
double array syntax and is therefore more permissive about unexpected
|
107
|
+
types. Using `expect` everywhere is recommended.
|
112
108
|
|
113
|
-
|
109
|
+
We suggest replacing `params.require(:person).permit(:name, :age)`
|
110
|
+
with the direct replacement `params.expect(person: [:name, :age])`
|
111
|
+
to prevent external users from manipulating params to trigger 500
|
112
|
+
errors. A 400 error will be returned instead, using public/400.html
|
114
113
|
|
115
|
-
|
114
|
+
Usage of `params.require(:id)` should likewise be replaced with
|
115
|
+
`params.expect(:id)` which is designed to ensure that `params[:id]`
|
116
|
+
is a scalar and not an array or hash, also requiring the param.
|
116
117
|
|
117
118
|
```ruby
|
118
|
-
|
119
|
-
|
120
|
-
end
|
119
|
+
# Before
|
120
|
+
User.find(params.require(:id)) # allows an array, altering behavior
|
121
121
|
|
122
|
-
|
123
|
-
|
124
|
-
by: -> { request.domain }, with: -> { redirect_to busy_controller_url, alert: "Too many signups!" }, only: :new
|
125
|
-
end
|
122
|
+
# After
|
123
|
+
User.find(params.expect(:id)) # expect only returns non-blank permitted scalars (excludes Hash, Array, nil, "", etc)
|
126
124
|
```
|
127
125
|
|
128
|
-
*
|
126
|
+
*Martin Emde*
|
127
|
+
|
128
|
+
* System Testing: Disable Chrome's search engine choice by default in system tests.
|
129
129
|
|
130
|
-
*
|
130
|
+
*glaszig*
|
131
131
|
|
132
|
-
|
132
|
+
* Fix `Request#raw_post` raising `NoMethodError` when `rack.input` is `nil`.
|
133
133
|
|
134
|
-
*
|
134
|
+
*Hartley McGuire*
|
135
135
|
|
136
|
-
|
136
|
+
* Remove `racc` dependency by manually writing `ActionDispatch::Journey::Scanner`.
|
137
137
|
|
138
|
-
*
|
138
|
+
*Gannon McGibbon*
|
139
139
|
|
140
|
-
*
|
140
|
+
* Speed up `ActionDispatch::Routing::Mapper::Scope#[]` by merging frame hashes.
|
141
141
|
|
142
142
|
*Gannon McGibbon*
|
143
143
|
|
144
|
-
*
|
144
|
+
* Allow bots to ignore `allow_browser`.
|
145
145
|
|
146
|
-
*
|
146
|
+
*Matthew Nguyen*
|
147
147
|
|
148
|
-
*
|
148
|
+
* Deprecate drawing routes with multiple paths to make routing faster.
|
149
|
+
You may use `with_options` or a loop to make drawing multiple paths easier.
|
149
150
|
|
150
|
-
|
151
|
+
```ruby
|
152
|
+
# Before
|
153
|
+
get "/users", "/other_path", to: "users#index"
|
151
154
|
|
152
|
-
|
155
|
+
# After
|
156
|
+
get "/users", to: "users#index"
|
157
|
+
get "/other_path", to: "users#index"
|
158
|
+
```
|
153
159
|
|
154
|
-
*
|
160
|
+
*Gannon McGibbon*
|
155
161
|
|
156
|
-
*
|
162
|
+
* Make `http_cache_forever` use `immutable: true`
|
157
163
|
|
158
|
-
*
|
164
|
+
*Nate Matykiewicz*
|
159
165
|
|
160
|
-
*
|
166
|
+
* Add `config.action_dispatch.strict_freshness`.
|
161
167
|
|
162
|
-
|
168
|
+
When set to `true`, the `ETag` header takes precedence over the `Last-Modified` header when both are present,
|
169
|
+
as specified by RFC 7232, Section 6.
|
163
170
|
|
164
|
-
|
171
|
+
Defaults to `false` to maintain compatibility with previous versions of Rails, but is enabled as part of
|
172
|
+
Rails 8.0 defaults.
|
165
173
|
|
166
|
-
*
|
174
|
+
*heka1024*
|
167
175
|
|
168
|
-
*
|
169
|
-
error with parallel system tests.
|
176
|
+
* Support `immutable` directive in Cache-Control
|
170
177
|
|
171
|
-
|
178
|
+
```ruby
|
179
|
+
expires_in 1.minute, public: true, immutable: true
|
180
|
+
# Cache-Control: public, max-age=60, immutable
|
181
|
+
```
|
172
182
|
|
173
|
-
*
|
183
|
+
*heka1024*
|
174
184
|
|
175
|
-
|
176
|
-
* Remove deprecated constant `ActionDispatch::IllegalStateError`.
|
185
|
+
* Add `:wasm_unsafe_eval` mapping for `content_security_policy`
|
177
186
|
|
178
|
-
|
187
|
+
```ruby
|
188
|
+
# Before
|
189
|
+
policy.script_src "'wasm-unsafe-eval'"
|
190
|
+
|
191
|
+
# After
|
192
|
+
policy.script_src :wasm_unsafe_eval
|
193
|
+
```
|
179
194
|
|
180
|
-
*
|
195
|
+
*Joe Haig*
|
181
196
|
|
182
|
-
|
183
|
-
The result would be like this:
|
197
|
+
* Add `display_capture` and `keyboard_map` in `permissions_policy`
|
184
198
|
|
185
|
-
|
199
|
+
*Cyril Blaecke*
|
186
200
|
|
187
|
-
|
201
|
+
* Add `connect` route helper.
|
188
202
|
|
189
|
-
*
|
203
|
+
*Samuel Williams*
|
190
204
|
|
191
|
-
Please check [7-
|
205
|
+
Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/actionpack/CHANGELOG.md) for previous changes.
|
@@ -266,7 +266,7 @@ module ActionController
|
|
266
266
|
ParamsWrapper
|
267
267
|
]
|
268
268
|
|
269
|
-
# Note: Documenting these severely
|
269
|
+
# Note: Documenting these severely degrades the performance of rdoc
|
270
270
|
# :stopdoc:
|
271
271
|
include AbstractController::Rendering
|
272
272
|
include AbstractController::Translation
|
@@ -22,10 +22,10 @@ module ActionController
|
|
22
22
|
# default_form_builder AdminFormBuilder
|
23
23
|
# end
|
24
24
|
#
|
25
|
-
# Then in the view any form using `form_for` will be an
|
26
|
-
# specified form builder:
|
25
|
+
# Then in the view any form using `form_with` or `form_for` will be an
|
26
|
+
# instance of the specified form builder:
|
27
27
|
#
|
28
|
-
# <%=
|
28
|
+
# <%= form_with(model: @instance) do |builder| %>
|
29
29
|
# <%= builder.special_field(:name) %>
|
30
30
|
# <% end %>
|
31
31
|
module FormBuilder
|
@@ -36,6 +36,16 @@ module ActionController # :nodoc:
|
|
36
36
|
# end
|
37
37
|
#
|
38
38
|
# class ApplicationController < ActionController::Base
|
39
|
+
# # Allow only browsers natively supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has
|
40
|
+
# allow_browser versions: :modern, block: :handle_outdated_browser
|
41
|
+
#
|
42
|
+
# private
|
43
|
+
# def handle_outdated_browser
|
44
|
+
# render file: Rails.root.join("public/custom-error.html"), status: :not_acceptable
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# class ApplicationController < ActionController::Base
|
39
49
|
# # 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+.
|
40
50
|
# allow_browser versions: { safari: 16.4, firefox: 121, ie: false }
|
41
51
|
# end
|
@@ -55,7 +65,7 @@ module ActionController # :nodoc:
|
|
55
65
|
|
56
66
|
if BrowserBlocker.new(request, versions: versions).blocked?
|
57
67
|
ActiveSupport::Notifications.instrument("browser_block.action_controller", request: request, versions: versions) do
|
58
|
-
instance_exec(&block)
|
68
|
+
block.is_a?(Symbol) ? send(block) : instance_exec(&block)
|
59
69
|
end
|
60
70
|
end
|
61
71
|
end
|
@@ -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,
|
@@ -28,7 +28,8 @@ module ActionController # :nodoc:
|
|
28
28
|
# `send_file(params[:path])` allows a malicious user to download any file on
|
29
29
|
# your server.
|
30
30
|
#
|
31
|
-
# Options:
|
31
|
+
# #### Options:
|
32
|
+
#
|
32
33
|
# * `:filename` - suggests a filename for the browser to use. Defaults to
|
33
34
|
# `File.basename(path)`.
|
34
35
|
# * `:type` - specifies an HTTP content type. You can specify either a string
|
@@ -90,7 +91,8 @@ module ActionController # :nodoc:
|
|
90
91
|
# inline data. You may also set the content type, the file name, and other
|
91
92
|
# things.
|
92
93
|
#
|
93
|
-
# Options:
|
94
|
+
# #### Options:
|
95
|
+
#
|
94
96
|
# * `:filename` - suggests a filename for the browser to use.
|
95
97
|
# * `:type` - specifies an HTTP content type. Defaults to
|
96
98
|
# `application/octet-stream`. You can specify either a string or a symbol
|
@@ -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.
|
31
|
+
ActiveSupport::Benchmark.realtime(:float_millisecond) { render_output = super }
|
33
32
|
end
|
34
33
|
render_output
|
35
34
|
end
|
@@ -58,7 +58,7 @@ module ActionController
|
|
58
58
|
|
59
59
|
module ClassMethods
|
60
60
|
def make_response!(request)
|
61
|
-
if request.get_header("HTTP_VERSION") == "HTTP/1.0"
|
61
|
+
if (request.get_header("SERVER_PROTOCOL") || request.get_header("HTTP_VERSION")) == "HTTP/1.0"
|
62
62
|
super
|
63
63
|
else
|
64
64
|
Live::Response.new.tap do |res|
|
@@ -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
|
@@ -328,7 +332,8 @@ module ActionController
|
|
328
332
|
# or other running data where you don't want the entire file buffered in memory
|
329
333
|
# first. Similar to send_data, but where the data is generated live.
|
330
334
|
#
|
331
|
-
# Options:
|
335
|
+
# #### Options:
|
336
|
+
#
|
332
337
|
# * `:filename` - suggests a filename for the browser to use.
|
333
338
|
# * `:type` - specifies an HTTP content type. You can specify either a string
|
334
339
|
# or a symbol for a registered type with `Mime::Type.register`, for example
|
@@ -371,11 +376,15 @@ module ActionController
|
|
371
376
|
# data from the response bodies. Nobody should call this method except in Rails
|
372
377
|
# internals. Seriously!
|
373
378
|
def new_controller_thread # :nodoc:
|
374
|
-
|
379
|
+
ActionController::Live.live_thread_pool_executor.post do
|
375
380
|
t2 = Thread.current
|
376
381
|
t2.abort_on_exception = true
|
377
382
|
yield
|
378
|
-
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
def self.live_thread_pool_executor
|
387
|
+
@live_thread_pool_executor ||= Concurrent::CachedThreadPool.new(name: "action_controller.live")
|
379
388
|
end
|
380
389
|
|
381
390
|
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 an 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
|
-
|
48
|
-
|
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
|
-
|
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)
|
@@ -106,13 +106,14 @@ module ActionController
|
|
106
106
|
|
107
107
|
allow_other_host = response_options.delete(:allow_other_host) { _allow_other_host }
|
108
108
|
|
109
|
-
|
109
|
+
proposed_status = _extract_redirect_to_status(options, response_options)
|
110
110
|
|
111
111
|
redirect_to_location = _compute_redirect_to_location(request, options)
|
112
112
|
_ensure_url_is_http_header_safe(redirect_to_location)
|
113
113
|
|
114
114
|
self.location = _enforce_open_redirect_protection(redirect_to_location, allow_other_host: allow_other_host)
|
115
115
|
self.response_body = ""
|
116
|
+
self.status = proposed_status
|
116
117
|
end
|
117
118
|
|
118
119
|
# Soft deprecated alias for #redirect_back_or_to where the `fallback_location`
|
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
# :markup: markdown
|
4
4
|
|
5
|
-
require "set"
|
6
|
-
|
7
5
|
module ActionController
|
8
6
|
# See Renderers.add
|
9
7
|
def self.add_renderer(key, &block)
|
@@ -154,7 +152,8 @@ module ActionController
|
|
154
152
|
end
|
155
153
|
|
156
154
|
add :json do |json, options|
|
157
|
-
|
155
|
+
json_options = options.except(:callback, :content_type, :status)
|
156
|
+
json = json.to_json(json_options) unless json.kind_of?(String)
|
158
157
|
|
159
158
|
if options[:callback].present?
|
160
159
|
if media_type.nil? || media_type == Mime[:json]
|