actionpack 5.2.4.rc1 → 6.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +120 -366
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/abstract_controller/base.rb +4 -2
- data/lib/abstract_controller/caching/fragments.rb +6 -21
- data/lib/abstract_controller/callbacks.rb +12 -0
- data/lib/abstract_controller/collector.rb +1 -1
- data/lib/abstract_controller/helpers.rb +2 -2
- data/lib/abstract_controller/railties/routes_helpers.rb +1 -1
- data/lib/action_controller.rb +1 -0
- data/lib/action_controller/api.rb +2 -1
- data/lib/action_controller/base.rb +2 -7
- data/lib/action_controller/caching.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +8 -5
- data/lib/action_controller/metal.rb +2 -2
- data/lib/action_controller/metal/conditional_get.rb +9 -3
- data/lib/action_controller/metal/data_streaming.rb +5 -6
- data/lib/action_controller/metal/default_headers.rb +17 -0
- data/lib/action_controller/metal/exceptions.rb +22 -1
- data/lib/action_controller/metal/flash.rb +5 -5
- data/lib/action_controller/metal/force_ssl.rb +17 -57
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +1 -2
- data/lib/action_controller/metal/http_authentication.rb +20 -21
- data/lib/action_controller/metal/implicit_render.rb +2 -12
- data/lib/action_controller/metal/instrumentation.rb +3 -5
- data/lib/action_controller/metal/live.rb +28 -26
- data/lib/action_controller/metal/mime_responds.rb +13 -2
- data/lib/action_controller/metal/params_wrapper.rb +18 -14
- data/lib/action_controller/metal/redirecting.rb +32 -11
- data/lib/action_controller/metal/rendering.rb +1 -1
- data/lib/action_controller/metal/request_forgery_protection.rb +22 -11
- data/lib/action_controller/metal/strong_parameters.rb +57 -32
- data/lib/action_controller/metal/url_for.rb +1 -1
- data/lib/action_controller/railties/helpers.rb +1 -1
- data/lib/action_controller/renderer.rb +15 -2
- data/lib/action_controller/test_case.rb +3 -7
- data/lib/action_dispatch.rb +3 -1
- data/lib/action_dispatch/http/cache.rb +14 -10
- data/lib/action_dispatch/http/content_disposition.rb +45 -0
- data/lib/action_dispatch/http/content_security_policy.rb +9 -8
- data/lib/action_dispatch/http/filter_parameters.rb +8 -6
- data/lib/action_dispatch/http/filter_redirect.rb +1 -1
- data/lib/action_dispatch/http/headers.rb +1 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +7 -10
- data/lib/action_dispatch/http/mime_type.rb +1 -5
- data/lib/action_dispatch/http/parameter_filter.rb +5 -79
- data/lib/action_dispatch/http/parameters.rb +13 -3
- data/lib/action_dispatch/http/request.rb +10 -13
- data/lib/action_dispatch/http/response.rb +14 -14
- data/lib/action_dispatch/http/upload.rb +5 -0
- data/lib/action_dispatch/http/url.rb +81 -81
- data/lib/action_dispatch/journey/formatter.rb +1 -1
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -2
- data/lib/action_dispatch/journey/nodes/node.rb +9 -8
- data/lib/action_dispatch/journey/path/pattern.rb +3 -4
- data/lib/action_dispatch/journey/router.rb +0 -3
- data/lib/action_dispatch/journey/router/utils.rb +10 -10
- data/lib/action_dispatch/journey/scanner.rb +11 -4
- data/lib/action_dispatch/journey/visitors.rb +1 -1
- data/lib/action_dispatch/middleware/callbacks.rb +2 -4
- data/lib/action_dispatch/middleware/cookies.rb +49 -70
- data/lib/action_dispatch/middleware/debug_exceptions.rb +32 -58
- data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
- data/lib/action_dispatch/middleware/debug_view.rb +50 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +36 -7
- data/lib/action_dispatch/middleware/flash.rb +1 -1
- data/lib/action_dispatch/middleware/host_authorization.rb +103 -0
- data/lib/action_dispatch/middleware/remote_ip.rb +6 -8
- data/lib/action_dispatch/middleware/request_id.rb +2 -2
- data/lib/action_dispatch/middleware/session/cookie_store.rb +4 -10
- data/lib/action_dispatch/middleware/ssl.rb +8 -8
- data/lib/action_dispatch/middleware/stack.rb +2 -2
- data/lib/action_dispatch/middleware/static.rb +5 -6
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +20 -2
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +3 -0
- data/lib/action_dispatch/railtie.rb +1 -0
- data/lib/action_dispatch/request/session.rb +8 -0
- data/lib/action_dispatch/routing.rb +3 -2
- data/lib/action_dispatch/routing/inspector.rb +99 -50
- data/lib/action_dispatch/routing/mapper.rb +36 -29
- data/lib/action_dispatch/routing/polymorphic_routes.rb +3 -4
- data/lib/action_dispatch/routing/route_set.rb +11 -12
- data/lib/action_dispatch/routing/url_for.rb +1 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +3 -3
- data/lib/action_dispatch/testing/assertions/response.rb +2 -3
- data/lib/action_dispatch/testing/assertions/routing.rb +7 -2
- data/lib/action_dispatch/testing/integration.rb +11 -4
- data/lib/action_dispatch/testing/test_process.rb +2 -2
- data/lib/action_dispatch/testing/test_response.rb +4 -32
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/gem_version.rb +4 -4
- metadata +20 -12
@@ -50,7 +50,7 @@ module ActionDispatch
|
|
50
50
|
unmatched_keys = (missing_keys || []) & constraints.keys
|
51
51
|
missing_keys = (missing_keys || []) - unmatched_keys
|
52
52
|
|
53
|
-
message = "No route matches #{Hash[constraints.sort_by { |k, v| k.to_s }].inspect}"
|
53
|
+
message = +"No route matches #{Hash[constraints.sort_by { |k, v| k.to_s }].inspect}"
|
54
54
|
message << ", missing required keys: #{missing_keys.sort.inspect}" if missing_keys && !missing_keys.empty?
|
55
55
|
message << ", possible unmatched constraints: #{unmatched_keys.sort.inspect}" if unmatched_keys && !unmatched_keys.empty?
|
56
56
|
|
@@ -32,7 +32,7 @@ module ActionDispatch
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def name
|
35
|
-
left.tr
|
35
|
+
-left.tr("*:", "")
|
36
36
|
end
|
37
37
|
|
38
38
|
def type
|
@@ -65,12 +65,12 @@ module ActionDispatch
|
|
65
65
|
def literal?; false; end
|
66
66
|
end
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
68
|
+
class Slash < Terminal # :nodoc:
|
69
|
+
def type; :SLASH; end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Dot < Terminal # :nodoc:
|
73
|
+
def type; :DOT; end
|
74
74
|
end
|
75
75
|
|
76
76
|
class Symbol < Terminal # :nodoc:
|
@@ -82,13 +82,14 @@ module ActionDispatch
|
|
82
82
|
def initialize(left)
|
83
83
|
super
|
84
84
|
@regexp = DEFAULT_EXP
|
85
|
-
@name = left.tr
|
85
|
+
@name = -left.tr("*:", "")
|
86
86
|
end
|
87
87
|
|
88
88
|
def default_regexp?
|
89
89
|
regexp == DEFAULT_EXP
|
90
90
|
end
|
91
91
|
|
92
|
+
def type; :SYMBOL; end
|
92
93
|
def symbol?; true; end
|
93
94
|
end
|
94
95
|
|
@@ -90,7 +90,7 @@ module ActionDispatch
|
|
90
90
|
return @separator_re unless @matchers.key?(node)
|
91
91
|
|
92
92
|
re = @matchers[node]
|
93
|
-
"(#{re})"
|
93
|
+
"(#{Regexp.union(re)})"
|
94
94
|
end
|
95
95
|
|
96
96
|
def visit_GROUP(node)
|
@@ -119,8 +119,7 @@ module ActionDispatch
|
|
119
119
|
|
120
120
|
class UnanchoredRegexp < AnchoredRegexp # :nodoc:
|
121
121
|
def accept(node)
|
122
|
-
|
123
|
-
path == "/" ? %r{\A/} : %r{\A#{path}(?:\b|\Z|/)}
|
122
|
+
%r{\A#{visit node}}
|
124
123
|
end
|
125
124
|
end
|
126
125
|
|
@@ -184,7 +183,7 @@ module ActionDispatch
|
|
184
183
|
node = node.to_sym
|
185
184
|
|
186
185
|
if @requirements.key?(node)
|
187
|
-
re = /#{@requirements[node]}|/
|
186
|
+
re = /#{Regexp.union(@requirements[node])}|/
|
188
187
|
@offsets.push((re.match("").length - 1) + @offsets.last)
|
189
188
|
else
|
190
189
|
@offsets << @offsets.last
|
@@ -17,11 +17,11 @@ module ActionDispatch
|
|
17
17
|
def self.normalize_path(path)
|
18
18
|
path ||= ""
|
19
19
|
encoding = path.encoding
|
20
|
-
path = "/#{path}"
|
21
|
-
path.squeeze!("/"
|
22
|
-
path.sub!(%r{/+\Z}, ""
|
20
|
+
path = +"/#{path}"
|
21
|
+
path.squeeze!("/")
|
22
|
+
path.sub!(%r{/+\Z}, "")
|
23
23
|
path.gsub!(/(%[a-f0-9]{2})/) { $1.upcase }
|
24
|
-
path = "/"
|
24
|
+
path = +"/" if path == ""
|
25
25
|
path.force_encoding(encoding)
|
26
26
|
path
|
27
27
|
end
|
@@ -29,16 +29,16 @@ module ActionDispatch
|
|
29
29
|
# URI path and fragment escaping
|
30
30
|
# https://tools.ietf.org/html/rfc3986
|
31
31
|
class UriEncoder # :nodoc:
|
32
|
-
ENCODE = "%%%02X"
|
32
|
+
ENCODE = "%%%02X"
|
33
33
|
US_ASCII = Encoding::US_ASCII
|
34
34
|
UTF_8 = Encoding::UTF_8
|
35
|
-
EMPTY = "".
|
35
|
+
EMPTY = (+"").force_encoding(US_ASCII).freeze
|
36
36
|
DEC2HEX = (0..255).to_a.map { |i| ENCODE % i }.map { |s| s.force_encoding(US_ASCII) }
|
37
37
|
|
38
|
-
ALPHA = "a-zA-Z"
|
39
|
-
DIGIT = "0-9"
|
40
|
-
UNRESERVED = "#{ALPHA}#{DIGIT}\\-\\._~"
|
41
|
-
SUB_DELIMS = "!\\$&'\\(\\)\\*\\+,;="
|
38
|
+
ALPHA = "a-zA-Z"
|
39
|
+
DIGIT = "0-9"
|
40
|
+
UNRESERVED = "#{ALPHA}#{DIGIT}\\-\\._~"
|
41
|
+
SUB_DELIMS = "!\\$&'\\(\\)\\*\\+,;="
|
42
42
|
|
43
43
|
ESCAPED = /%[a-zA-Z0-9]{2}/.freeze
|
44
44
|
|
@@ -34,6 +34,13 @@ module ActionDispatch
|
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
+
# takes advantage of String @- deduping capabilities in Ruby 2.5 upwards
|
38
|
+
# see: https://bugs.ruby-lang.org/issues/13077
|
39
|
+
def dedup_scan(regex)
|
40
|
+
r = @ss.scan(regex)
|
41
|
+
r ? -r : nil
|
42
|
+
end
|
43
|
+
|
37
44
|
def scan
|
38
45
|
case
|
39
46
|
# /
|
@@ -47,15 +54,15 @@ module ActionDispatch
|
|
47
54
|
[:OR, "|"]
|
48
55
|
when @ss.skip(/\./)
|
49
56
|
[:DOT, "."]
|
50
|
-
when text =
|
57
|
+
when text = dedup_scan(/:\w+/)
|
51
58
|
[:SYMBOL, text]
|
52
|
-
when text =
|
59
|
+
when text = dedup_scan(/\*\w+/)
|
53
60
|
[:STAR, text]
|
54
61
|
when text = @ss.scan(/(?:[\w%\-~!$&'*+,;=@]|\\[:()])+/)
|
55
62
|
text.tr! "\\", ""
|
56
|
-
[:LITERAL, text]
|
63
|
+
[:LITERAL, -text]
|
57
64
|
# any char
|
58
|
-
when text =
|
65
|
+
when text = dedup_scan(/./)
|
59
66
|
[:LITERAL, text]
|
60
67
|
end
|
61
68
|
end
|
@@ -9,7 +9,7 @@ require "rack/utils"
|
|
9
9
|
module ActionDispatch
|
10
10
|
class Request
|
11
11
|
def cookie_jar
|
12
|
-
fetch_header("action_dispatch.cookies"
|
12
|
+
fetch_header("action_dispatch.cookies") do
|
13
13
|
self.cookie_jar = Cookies::CookieJar.build(self, cookies)
|
14
14
|
end
|
15
15
|
end
|
@@ -22,11 +22,11 @@ module ActionDispatch
|
|
22
22
|
}
|
23
23
|
|
24
24
|
def have_cookie_jar?
|
25
|
-
has_header? "action_dispatch.cookies"
|
25
|
+
has_header? "action_dispatch.cookies"
|
26
26
|
end
|
27
27
|
|
28
28
|
def cookie_jar=(jar)
|
29
|
-
set_header "action_dispatch.cookies"
|
29
|
+
set_header "action_dispatch.cookies", jar
|
30
30
|
end
|
31
31
|
|
32
32
|
def key_generator
|
@@ -61,10 +61,6 @@ module ActionDispatch
|
|
61
61
|
get_header Cookies::SIGNED_COOKIE_DIGEST
|
62
62
|
end
|
63
63
|
|
64
|
-
def secret_token
|
65
|
-
get_header Cookies::SECRET_TOKEN
|
66
|
-
end
|
67
|
-
|
68
64
|
def secret_key_base
|
69
65
|
get_header Cookies::SECRET_KEY_BASE
|
70
66
|
end
|
@@ -81,6 +77,10 @@ module ActionDispatch
|
|
81
77
|
get_header Cookies::COOKIES_ROTATIONS
|
82
78
|
end
|
83
79
|
|
80
|
+
def use_cookies_with_metadata
|
81
|
+
get_header Cookies::USE_COOKIES_WITH_METADATA
|
82
|
+
end
|
83
|
+
|
84
84
|
# :startdoc:
|
85
85
|
end
|
86
86
|
|
@@ -168,20 +168,20 @@ module ActionDispatch
|
|
168
168
|
# * <tt>:httponly</tt> - Whether this cookie is accessible via scripting or
|
169
169
|
# only HTTP. Defaults to +false+.
|
170
170
|
class Cookies
|
171
|
-
HTTP_HEADER = "Set-Cookie"
|
172
|
-
GENERATOR_KEY = "action_dispatch.key_generator"
|
173
|
-
SIGNED_COOKIE_SALT = "action_dispatch.signed_cookie_salt"
|
174
|
-
ENCRYPTED_COOKIE_SALT = "action_dispatch.encrypted_cookie_salt"
|
175
|
-
ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt"
|
176
|
-
AUTHENTICATED_ENCRYPTED_COOKIE_SALT = "action_dispatch.authenticated_encrypted_cookie_salt"
|
177
|
-
USE_AUTHENTICATED_COOKIE_ENCRYPTION = "action_dispatch.use_authenticated_cookie_encryption"
|
178
|
-
ENCRYPTED_COOKIE_CIPHER = "action_dispatch.encrypted_cookie_cipher"
|
179
|
-
SIGNED_COOKIE_DIGEST = "action_dispatch.signed_cookie_digest"
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
171
|
+
HTTP_HEADER = "Set-Cookie"
|
172
|
+
GENERATOR_KEY = "action_dispatch.key_generator"
|
173
|
+
SIGNED_COOKIE_SALT = "action_dispatch.signed_cookie_salt"
|
174
|
+
ENCRYPTED_COOKIE_SALT = "action_dispatch.encrypted_cookie_salt"
|
175
|
+
ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt"
|
176
|
+
AUTHENTICATED_ENCRYPTED_COOKIE_SALT = "action_dispatch.authenticated_encrypted_cookie_salt"
|
177
|
+
USE_AUTHENTICATED_COOKIE_ENCRYPTION = "action_dispatch.use_authenticated_cookie_encryption"
|
178
|
+
ENCRYPTED_COOKIE_CIPHER = "action_dispatch.encrypted_cookie_cipher"
|
179
|
+
SIGNED_COOKIE_DIGEST = "action_dispatch.signed_cookie_digest"
|
180
|
+
SECRET_KEY_BASE = "action_dispatch.secret_key_base"
|
181
|
+
COOKIES_SERIALIZER = "action_dispatch.cookies_serializer"
|
182
|
+
COOKIES_DIGEST = "action_dispatch.cookies_digest"
|
183
|
+
COOKIES_ROTATIONS = "action_dispatch.cookies_rotations"
|
184
|
+
USE_COOKIES_WITH_METADATA = "action_dispatch.use_cookies_with_metadata"
|
185
185
|
|
186
186
|
# Cookies can typically store 4096 bytes.
|
187
187
|
MAX_COOKIE_SIZE = 4096
|
@@ -210,9 +210,6 @@ module ActionDispatch
|
|
210
210
|
# the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed
|
211
211
|
# cookie was tampered with by the user (or a 3rd party), +nil+ will be returned.
|
212
212
|
#
|
213
|
-
# If +secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
|
214
|
-
# legacy cookies signed with the old key generator will be transparently upgraded.
|
215
|
-
#
|
216
213
|
# This jar requires that you set a suitable secret for the verification on your app's +secret_key_base+.
|
217
214
|
#
|
218
215
|
# Example:
|
@@ -228,9 +225,6 @@ module ActionDispatch
|
|
228
225
|
# Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read.
|
229
226
|
# If the cookie was tampered with by the user (or a 3rd party), +nil+ will be returned.
|
230
227
|
#
|
231
|
-
# If +secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
|
232
|
-
# legacy cookies signed with the old key generator will be transparently upgraded.
|
233
|
-
#
|
234
228
|
# If +config.action_dispatch.encrypted_cookie_salt+ and +config.action_dispatch.encrypted_signed_cookie_salt+
|
235
229
|
# are both set, legacy cookies encrypted with HMAC AES-256-CBC will be transparently upgraded.
|
236
230
|
#
|
@@ -259,10 +253,6 @@ module ActionDispatch
|
|
259
253
|
|
260
254
|
private
|
261
255
|
|
262
|
-
def upgrade_legacy_signed_cookies?
|
263
|
-
request.secret_token.present? && request.secret_key_base.present?
|
264
|
-
end
|
265
|
-
|
266
256
|
def upgrade_legacy_hmac_aes_cbc_cookies?
|
267
257
|
request.secret_key_base.present? &&
|
268
258
|
request.encrypted_signed_cookie_salt.present? &&
|
@@ -470,7 +460,7 @@ module ActionDispatch
|
|
470
460
|
|
471
461
|
def [](name)
|
472
462
|
if data = @parent_jar[name.to_s]
|
473
|
-
parse name, data
|
463
|
+
parse(name, data, purpose: "cookie.#{name}") || parse(name, data)
|
474
464
|
end
|
475
465
|
end
|
476
466
|
|
@@ -481,7 +471,7 @@ module ActionDispatch
|
|
481
471
|
options = { value: options }
|
482
472
|
end
|
483
473
|
|
484
|
-
commit(options)
|
474
|
+
commit(name, options)
|
485
475
|
@parent_jar[name] = options
|
486
476
|
end
|
487
477
|
|
@@ -490,24 +480,31 @@ module ActionDispatch
|
|
490
480
|
|
491
481
|
private
|
492
482
|
def expiry_options(options)
|
493
|
-
if
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
483
|
+
if options[:expires].respond_to?(:from_now)
|
484
|
+
{ expires_in: options[:expires] }
|
485
|
+
else
|
486
|
+
{ expires_at: options[:expires] }
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
def cookie_metadata(name, options)
|
491
|
+
if request.use_cookies_with_metadata
|
492
|
+
metadata = expiry_options(options)
|
493
|
+
metadata[:purpose] = "cookie.#{name}"
|
494
|
+
|
495
|
+
metadata
|
499
496
|
else
|
500
497
|
{}
|
501
498
|
end
|
502
499
|
end
|
503
500
|
|
504
|
-
def parse(name, data); data; end
|
505
|
-
def commit(options); end
|
501
|
+
def parse(name, data, purpose: nil); data; end
|
502
|
+
def commit(name, options); end
|
506
503
|
end
|
507
504
|
|
508
505
|
class PermanentCookieJar < AbstractCookieJar # :nodoc:
|
509
506
|
private
|
510
|
-
def commit(options)
|
507
|
+
def commit(name, options)
|
511
508
|
options[:expires] = 20.years.from_now
|
512
509
|
end
|
513
510
|
end
|
@@ -523,7 +520,7 @@ module ActionDispatch
|
|
523
520
|
end
|
524
521
|
|
525
522
|
module SerializedCookieJars # :nodoc:
|
526
|
-
MARSHAL_SIGNATURE = "\x04\x08"
|
523
|
+
MARSHAL_SIGNATURE = "\x04\x08"
|
527
524
|
SERIALIZER = ActiveSupport::MessageEncryptor::NullSerializer
|
528
525
|
|
529
526
|
protected
|
@@ -580,21 +577,17 @@ module ActionDispatch
|
|
580
577
|
request.cookies_rotations.signed.each do |*secrets, **options|
|
581
578
|
@verifier.rotate(*secrets, serializer: SERIALIZER, **options)
|
582
579
|
end
|
583
|
-
|
584
|
-
if upgrade_legacy_signed_cookies?
|
585
|
-
@verifier.rotate request.secret_token, serializer: SERIALIZER
|
586
|
-
end
|
587
580
|
end
|
588
581
|
|
589
582
|
private
|
590
|
-
def parse(name, signed_message)
|
583
|
+
def parse(name, signed_message, purpose: nil)
|
591
584
|
deserialize(name) do |rotate|
|
592
|
-
@verifier.verified(signed_message, on_rotation: rotate)
|
585
|
+
@verifier.verified(signed_message, on_rotation: rotate, purpose: purpose)
|
593
586
|
end
|
594
587
|
end
|
595
588
|
|
596
|
-
def commit(options)
|
597
|
-
options[:value] = @verifier.generate(serialize(options[:value]),
|
589
|
+
def commit(name, options)
|
590
|
+
options[:value] = @verifier.generate(serialize(options[:value]), cookie_metadata(name, options))
|
598
591
|
|
599
592
|
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
|
600
593
|
end
|
@@ -628,36 +621,22 @@ module ActionDispatch
|
|
628
621
|
|
629
622
|
@encryptor.rotate(secret, sign_secret, cipher: legacy_cipher, digest: digest, serializer: SERIALIZER)
|
630
623
|
end
|
631
|
-
|
632
|
-
if upgrade_legacy_signed_cookies?
|
633
|
-
@legacy_verifier = ActiveSupport::MessageVerifier.new(request.secret_token, digest: digest, serializer: SERIALIZER)
|
634
|
-
end
|
635
624
|
end
|
636
625
|
|
637
626
|
private
|
638
|
-
def parse(name, encrypted_message)
|
627
|
+
def parse(name, encrypted_message, purpose: nil)
|
639
628
|
deserialize(name) do |rotate|
|
640
|
-
@encryptor.decrypt_and_verify(encrypted_message, on_rotation: rotate)
|
629
|
+
@encryptor.decrypt_and_verify(encrypted_message, on_rotation: rotate, purpose: purpose)
|
641
630
|
end
|
642
631
|
rescue ActiveSupport::MessageEncryptor::InvalidMessage, ActiveSupport::MessageVerifier::InvalidSignature
|
643
|
-
|
632
|
+
nil
|
644
633
|
end
|
645
634
|
|
646
|
-
def commit(options)
|
647
|
-
options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]),
|
635
|
+
def commit(name, options)
|
636
|
+
options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]), cookie_metadata(name, options))
|
648
637
|
|
649
638
|
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
|
650
639
|
end
|
651
|
-
|
652
|
-
def parse_legacy_signed_message(name, legacy_signed_message)
|
653
|
-
if defined?(@legacy_verifier)
|
654
|
-
deserialize(name) do |rotate|
|
655
|
-
rotate.call
|
656
|
-
|
657
|
-
@legacy_verifier.verified(legacy_signed_message)
|
658
|
-
end
|
659
|
-
end
|
660
|
-
end
|
661
640
|
end
|
662
641
|
|
663
642
|
def initialize(app)
|
@@ -3,57 +3,26 @@
|
|
3
3
|
require "action_dispatch/http/request"
|
4
4
|
require "action_dispatch/middleware/exception_wrapper"
|
5
5
|
require "action_dispatch/routing/inspector"
|
6
|
+
|
6
7
|
require "action_view"
|
7
8
|
require "action_view/base"
|
8
9
|
|
9
|
-
require "pp"
|
10
|
-
|
11
10
|
module ActionDispatch
|
12
11
|
# This middleware is responsible for logging exceptions and
|
13
12
|
# showing a debugging page in case the request is local.
|
14
13
|
class DebugExceptions
|
15
|
-
|
16
|
-
|
17
|
-
class DebugView < ActionView::Base
|
18
|
-
def debug_params(params)
|
19
|
-
clean_params = params.clone
|
20
|
-
clean_params.delete("action")
|
21
|
-
clean_params.delete("controller")
|
22
|
-
|
23
|
-
if clean_params.empty?
|
24
|
-
"None"
|
25
|
-
else
|
26
|
-
PP.pp(clean_params, "".dup, 200)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def debug_headers(headers)
|
31
|
-
if headers.present?
|
32
|
-
headers.inspect.gsub(",", ",\n")
|
33
|
-
else
|
34
|
-
"None"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def debug_hash(object)
|
39
|
-
object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
|
40
|
-
end
|
41
|
-
|
42
|
-
def render(*)
|
43
|
-
logger = ActionView::Base.logger
|
14
|
+
cattr_reader :interceptors, instance_accessor: false, default: []
|
44
15
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
super
|
49
|
-
end
|
50
|
-
end
|
16
|
+
def self.register_interceptor(object = nil, &block)
|
17
|
+
interceptor = object || block
|
18
|
+
interceptors << interceptor
|
51
19
|
end
|
52
20
|
|
53
|
-
def initialize(app, routes_app = nil, response_format = :default)
|
21
|
+
def initialize(app, routes_app = nil, response_format = :default, interceptors = self.class.interceptors)
|
54
22
|
@app = app
|
55
23
|
@routes_app = routes_app
|
56
24
|
@response_format = response_format
|
25
|
+
@interceptors = interceptors
|
57
26
|
end
|
58
27
|
|
59
28
|
def call(env)
|
@@ -67,12 +36,24 @@ module ActionDispatch
|
|
67
36
|
|
68
37
|
response
|
69
38
|
rescue Exception => exception
|
39
|
+
invoke_interceptors(request, exception)
|
70
40
|
raise exception unless request.show_exceptions?
|
71
41
|
render_exception(request, exception)
|
72
42
|
end
|
73
43
|
|
74
44
|
private
|
75
45
|
|
46
|
+
def invoke_interceptors(request, exception)
|
47
|
+
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
|
48
|
+
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
|
49
|
+
|
50
|
+
@interceptors.each do |interceptor|
|
51
|
+
interceptor.call(request, exception)
|
52
|
+
rescue Exception
|
53
|
+
log_error(request, wrapper)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
76
57
|
def render_exception(request, exception)
|
77
58
|
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
|
78
59
|
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
|
@@ -130,23 +111,13 @@ module ActionDispatch
|
|
130
111
|
end
|
131
112
|
|
132
113
|
def create_template(request, wrapper)
|
133
|
-
|
134
|
-
|
135
|
-
trace_to_show = "Application Trace"
|
136
|
-
if traces[trace_to_show].empty? && wrapper.rescue_template != "routing_error"
|
137
|
-
trace_to_show = "Full Trace"
|
138
|
-
end
|
139
|
-
|
140
|
-
if source_to_show = traces[trace_to_show].first
|
141
|
-
source_to_show_id = source_to_show[:id]
|
142
|
-
end
|
143
|
-
|
144
|
-
DebugView.new([RESCUES_TEMPLATE_PATH],
|
114
|
+
DebugView.new(
|
145
115
|
request: request,
|
116
|
+
exception_wrapper: wrapper,
|
146
117
|
exception: wrapper.exception,
|
147
|
-
traces: traces,
|
148
|
-
show_source_idx: source_to_show_id,
|
149
|
-
trace_to_show: trace_to_show,
|
118
|
+
traces: wrapper.traces,
|
119
|
+
show_source_idx: wrapper.source_to_show_id,
|
120
|
+
trace_to_show: wrapper.trace_to_show,
|
150
121
|
routes_inspector: routes_inspector(wrapper.exception),
|
151
122
|
source_extracts: wrapper.source_extracts,
|
152
123
|
line_number: wrapper.line_number,
|
@@ -168,11 +139,14 @@ module ActionDispatch
|
|
168
139
|
trace = wrapper.framework_trace if trace.empty?
|
169
140
|
|
170
141
|
ActiveSupport::Deprecation.silence do
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
142
|
+
message = []
|
143
|
+
message << " "
|
144
|
+
message << "#{exception.class} (#{exception.message}):"
|
145
|
+
message.concat(exception.annoted_source_code) if exception.respond_to?(:annoted_source_code)
|
146
|
+
message << " "
|
147
|
+
message.concat(trace)
|
148
|
+
|
149
|
+
log_array(logger, message)
|
176
150
|
end
|
177
151
|
end
|
178
152
|
|