actionpack 5.2.2.1 → 6.0.2
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 +197 -274
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -2
- data/lib/abstract_controller/base.rb +4 -2
- data/lib/abstract_controller/caching/fragments.rb +6 -22
- 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/abstract_controller/translation.rb +1 -0
- data/lib/action_controller.rb +5 -1
- 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 +3 -3
- data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
- 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/etag_with_template_digest.rb +1 -1
- data/lib/action_controller/metal/exceptions.rb +23 -2
- data/lib/action_controller/metal/flash.rb +5 -5
- data/lib/action_controller/metal/force_ssl.rb +15 -56
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +3 -4
- data/lib/action_controller/metal/http_authentication.rb +20 -21
- data/lib/action_controller/metal/implicit_render.rb +4 -14
- data/lib/action_controller/metal/instrumentation.rb +3 -5
- data/lib/action_controller/metal/live.rb +29 -27
- 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 +5 -5
- data/lib/action_controller/metal/renderers.rb +4 -4
- data/lib/action_controller/metal/rendering.rb +2 -2
- data/lib/action_controller/metal/request_forgery_protection.rb +23 -12
- data/lib/action_controller/metal/strong_parameters.rb +63 -44
- 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 +16 -3
- data/lib/action_controller/template_assertions.rb +1 -1
- data/lib/action_controller/test_case.rb +6 -8
- data/lib/action_dispatch.rb +4 -2
- data/lib/action_dispatch/http/cache.rb +20 -14
- data/lib/action_dispatch/http/content_disposition.rb +45 -0
- data/lib/action_dispatch/http/content_security_policy.rb +28 -16
- 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 -5
- data/lib/action_dispatch/http/mime_type.rb +14 -6
- 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 +40 -20
- data/lib/action_dispatch/http/upload.rb +9 -1
- data/lib/action_dispatch/http/url.rb +81 -81
- data/lib/action_dispatch/journey/formatter.rb +2 -2
- 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 +8 -3
- data/lib/action_dispatch/journey/route.rb +5 -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/routes.rb +0 -1
- data/lib/action_dispatch/journey/scanner.rb +11 -4
- data/lib/action_dispatch/journey/visitors.rb +1 -1
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -4
- data/lib/action_dispatch/middleware/cookies.rb +52 -74
- data/lib/action_dispatch/middleware/debug_exceptions.rb +39 -59
- data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
- data/lib/action_dispatch/middleware/debug_view.rb +68 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +49 -15
- data/lib/action_dispatch/middleware/flash.rb +1 -1
- data/lib/action_dispatch/middleware/host_authorization.rb +103 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -2
- data/lib/action_dispatch/middleware/remote_ip.rb +9 -11
- data/lib/action_dispatch/middleware/request_id.rb +2 -2
- data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -6
- data/lib/action_dispatch/middleware/show_exceptions.rb +1 -1
- data/lib/action_dispatch/middleware/ssl.rb +8 -8
- data/lib/action_dispatch/middleware/stack.rb +34 -2
- data/lib/action_dispatch/middleware/static.rb +5 -6
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- 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 +26 -4
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -0
- 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 +7 -2
- data/lib/action_dispatch/request/session.rb +8 -0
- data/lib/action_dispatch/routing.rb +21 -20
- data/lib/action_dispatch/routing/inspector.rb +99 -50
- data/lib/action_dispatch/routing/mapper.rb +61 -39
- data/lib/action_dispatch/routing/polymorphic_routes.rb +3 -4
- data/lib/action_dispatch/routing/route_set.rb +24 -27
- data/lib/action_dispatch/routing/url_for.rb +1 -0
- data/lib/action_dispatch/system_test_case.rb +44 -5
- data/lib/action_dispatch/system_testing/browser.rb +38 -7
- data/lib/action_dispatch/system_testing/driver.rb +10 -1
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +6 -5
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +7 -6
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +2 -3
- data/lib/action_dispatch/testing/assertions/routing.rb +15 -3
- data/lib/action_dispatch/testing/integration.rb +12 -5
- data/lib/action_dispatch/testing/request_encoder.rb +2 -2
- 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 +3 -3
- metadata +29 -16
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
|
@@ -26,7 +26,7 @@ module ActionController
|
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
# ActionController::TestCase will be deprecated and moved to a gem in
|
|
29
|
+
# ActionController::TestCase will be deprecated and moved to a gem in the future.
|
|
30
30
|
# Please use ActionDispatch::IntegrationTest going forward.
|
|
31
31
|
class TestRequest < ActionDispatch::TestRequest #:nodoc:
|
|
32
32
|
DEFAULT_ENV = ActionDispatch::TestRequest::DEFAULT_ENV.dup
|
|
@@ -276,9 +276,6 @@ module ActionController
|
|
|
276
276
|
# after calling +post+. If the various assert methods are not sufficient, then you
|
|
277
277
|
# may use this object to inspect the HTTP response in detail.
|
|
278
278
|
#
|
|
279
|
-
# (Earlier versions of \Rails required each functional test to subclass
|
|
280
|
-
# Test::Unit::TestCase and define @controller, @request, @response in +setup+.)
|
|
281
|
-
#
|
|
282
279
|
# == Controller is automatically inferred
|
|
283
280
|
#
|
|
284
281
|
# ActionController::TestCase will automatically infer the controller under test
|
|
@@ -457,9 +454,10 @@ module ActionController
|
|
|
457
454
|
# respectively which will make tests more expressive.
|
|
458
455
|
#
|
|
459
456
|
# Note that the request method is not verified.
|
|
460
|
-
def process(action, method: "GET", params:
|
|
457
|
+
def process(action, method: "GET", params: nil, session: nil, body: nil, flash: {}, format: nil, xhr: false, as: nil)
|
|
461
458
|
check_required_ivars
|
|
462
459
|
|
|
460
|
+
action = +action.to_s
|
|
463
461
|
http_method = method.to_s.upcase
|
|
464
462
|
|
|
465
463
|
@html_document = nil
|
|
@@ -485,17 +483,17 @@ module ActionController
|
|
|
485
483
|
format ||= as
|
|
486
484
|
end
|
|
487
485
|
|
|
488
|
-
parameters = params.symbolize_keys
|
|
486
|
+
parameters = (params || {}).symbolize_keys
|
|
489
487
|
|
|
490
488
|
if format
|
|
491
489
|
parameters[:format] = format
|
|
492
490
|
end
|
|
493
491
|
|
|
494
|
-
generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action
|
|
492
|
+
generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action))
|
|
495
493
|
generated_path = generated_path(generated_extras)
|
|
496
494
|
query_string_keys = query_parameter_names(generated_extras)
|
|
497
495
|
|
|
498
|
-
@request.assign_parameters(@routes, controller_class_name, action
|
|
496
|
+
@request.assign_parameters(@routes, controller_class_name, action, parameters, generated_path, query_string_keys)
|
|
499
497
|
|
|
500
498
|
@request.session.update(session) if session
|
|
501
499
|
@request.flash.update(flash || {})
|
data/lib/action_dispatch.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
#--
|
|
4
|
-
# Copyright (c) 2004-
|
|
4
|
+
# Copyright (c) 2004-2019 David Heinemeier Hansson
|
|
5
5
|
#
|
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
7
7
|
# a copy of this software and associated documentation files (the
|
|
@@ -49,11 +49,14 @@ module ActionDispatch
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
autoload_under "middleware" do
|
|
52
|
+
autoload :HostAuthorization
|
|
52
53
|
autoload :RequestId
|
|
53
54
|
autoload :Callbacks
|
|
54
55
|
autoload :Cookies
|
|
56
|
+
autoload :ActionableExceptions
|
|
55
57
|
autoload :DebugExceptions
|
|
56
58
|
autoload :DebugLocks
|
|
59
|
+
autoload :DebugView
|
|
57
60
|
autoload :ExceptionWrapper
|
|
58
61
|
autoload :Executor
|
|
59
62
|
autoload :Flash
|
|
@@ -77,7 +80,6 @@ module ActionDispatch
|
|
|
77
80
|
autoload :MimeNegotiation
|
|
78
81
|
autoload :Parameters
|
|
79
82
|
autoload :ParameterFilter
|
|
80
|
-
autoload :Upload
|
|
81
83
|
autoload :UploadedFile, "action_dispatch/http/upload"
|
|
82
84
|
autoload :URL
|
|
83
85
|
end
|
|
@@ -4,8 +4,8 @@ module ActionDispatch
|
|
|
4
4
|
module Http
|
|
5
5
|
module Cache
|
|
6
6
|
module Request
|
|
7
|
-
HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE"
|
|
8
|
-
HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH"
|
|
7
|
+
HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE"
|
|
8
|
+
HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH"
|
|
9
9
|
|
|
10
10
|
def if_modified_since
|
|
11
11
|
if since = get_header(HTTP_IF_MODIFIED_SINCE)
|
|
@@ -124,8 +124,8 @@ module ActionDispatch
|
|
|
124
124
|
|
|
125
125
|
private
|
|
126
126
|
|
|
127
|
-
DATE = "Date"
|
|
128
|
-
LAST_MODIFIED = "Last-Modified"
|
|
127
|
+
DATE = "Date"
|
|
128
|
+
LAST_MODIFIED = "Last-Modified"
|
|
129
129
|
SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public private must-revalidate])
|
|
130
130
|
|
|
131
131
|
def generate_weak_etag(validators)
|
|
@@ -166,11 +166,11 @@ module ActionDispatch
|
|
|
166
166
|
@cache_control = cache_control_headers
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
-
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
|
|
170
|
-
NO_CACHE = "no-cache"
|
|
171
|
-
PUBLIC = "public"
|
|
172
|
-
PRIVATE = "private"
|
|
173
|
-
MUST_REVALIDATE = "must-revalidate"
|
|
169
|
+
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
|
|
170
|
+
NO_CACHE = "no-cache"
|
|
171
|
+
PUBLIC = "public"
|
|
172
|
+
PRIVATE = "private"
|
|
173
|
+
MUST_REVALIDATE = "must-revalidate"
|
|
174
174
|
|
|
175
175
|
def handle_conditional_get!
|
|
176
176
|
# Normally default cache control setting is handled by ETag
|
|
@@ -197,18 +197,24 @@ module ActionDispatch
|
|
|
197
197
|
if control.empty?
|
|
198
198
|
# Let middleware handle default behavior
|
|
199
199
|
elsif control[:no_cache]
|
|
200
|
-
|
|
201
|
-
if control[:
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
options = []
|
|
201
|
+
options << PUBLIC if control[:public]
|
|
202
|
+
options << NO_CACHE
|
|
203
|
+
options.concat(control[:extras]) if control[:extras]
|
|
204
|
+
|
|
205
|
+
self._cache_control = options.join(", ")
|
|
204
206
|
else
|
|
205
|
-
extras
|
|
207
|
+
extras = control[:extras]
|
|
206
208
|
max_age = control[:max_age]
|
|
209
|
+
stale_while_revalidate = control[:stale_while_revalidate]
|
|
210
|
+
stale_if_error = control[:stale_if_error]
|
|
207
211
|
|
|
208
212
|
options = []
|
|
209
213
|
options << "max-age=#{max_age.to_i}" if max_age
|
|
210
214
|
options << (control[:public] ? PUBLIC : PRIVATE)
|
|
211
215
|
options << MUST_REVALIDATE if control[:must_revalidate]
|
|
216
|
+
options << "stale-while-revalidate=#{stale_while_revalidate.to_i}" if stale_while_revalidate
|
|
217
|
+
options << "stale-if-error=#{stale_if_error.to_i}" if stale_if_error
|
|
212
218
|
options.concat(extras) if extras
|
|
213
219
|
|
|
214
220
|
self._cache_control = options.join(", ")
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActionDispatch
|
|
4
|
+
module Http
|
|
5
|
+
class ContentDisposition # :nodoc:
|
|
6
|
+
def self.format(disposition:, filename:)
|
|
7
|
+
new(disposition: disposition, filename: filename).to_s
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
attr_reader :disposition, :filename
|
|
11
|
+
|
|
12
|
+
def initialize(disposition:, filename:)
|
|
13
|
+
@disposition = disposition
|
|
14
|
+
@filename = filename
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/
|
|
18
|
+
|
|
19
|
+
def ascii_filename
|
|
20
|
+
'filename="' + percent_escape(I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/
|
|
24
|
+
|
|
25
|
+
def utf8_filename
|
|
26
|
+
"filename*=UTF-8''" + percent_escape(filename, RFC_5987_ESCAPED_CHAR)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_s
|
|
30
|
+
if filename
|
|
31
|
+
"#{disposition}; #{ascii_filename}; #{utf8_filename}"
|
|
32
|
+
else
|
|
33
|
+
"#{disposition}"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
def percent_escape(string, pattern)
|
|
39
|
+
string.gsub(pattern) do |char|
|
|
40
|
+
char.bytes.map { |byte| "%%%02X" % byte }.join
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -5,9 +5,9 @@ require "active_support/core_ext/object/deep_dup"
|
|
|
5
5
|
module ActionDispatch #:nodoc:
|
|
6
6
|
class ContentSecurityPolicy
|
|
7
7
|
class Middleware
|
|
8
|
-
CONTENT_TYPE = "Content-Type"
|
|
9
|
-
POLICY = "Content-Security-Policy"
|
|
10
|
-
POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only"
|
|
8
|
+
CONTENT_TYPE = "Content-Type"
|
|
9
|
+
POLICY = "Content-Security-Policy"
|
|
10
|
+
POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only"
|
|
11
11
|
|
|
12
12
|
def initialize(app)
|
|
13
13
|
@app = app
|
|
@@ -22,8 +22,9 @@ module ActionDispatch #:nodoc:
|
|
|
22
22
|
|
|
23
23
|
if policy = request.content_security_policy
|
|
24
24
|
nonce = request.content_security_policy_nonce
|
|
25
|
+
nonce_directives = request.content_security_policy_nonce_directives
|
|
25
26
|
context = request.controller_instance || request
|
|
26
|
-
headers[header_name(request)] = policy.build(context, nonce)
|
|
27
|
+
headers[header_name(request)] = policy.build(context, nonce, nonce_directives)
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
response
|
|
@@ -51,10 +52,11 @@ module ActionDispatch #:nodoc:
|
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
module Request
|
|
54
|
-
POLICY = "action_dispatch.content_security_policy"
|
|
55
|
-
POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only"
|
|
56
|
-
NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator"
|
|
57
|
-
NONCE = "action_dispatch.content_security_policy_nonce"
|
|
55
|
+
POLICY = "action_dispatch.content_security_policy"
|
|
56
|
+
POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only"
|
|
57
|
+
NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator"
|
|
58
|
+
NONCE = "action_dispatch.content_security_policy_nonce"
|
|
59
|
+
NONCE_DIRECTIVES = "action_dispatch.content_security_policy_nonce_directives"
|
|
58
60
|
|
|
59
61
|
def content_security_policy
|
|
60
62
|
get_header(POLICY)
|
|
@@ -80,6 +82,14 @@ module ActionDispatch #:nodoc:
|
|
|
80
82
|
set_header(NONCE_GENERATOR, generator)
|
|
81
83
|
end
|
|
82
84
|
|
|
85
|
+
def content_security_policy_nonce_directives
|
|
86
|
+
get_header(NONCE_DIRECTIVES)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def content_security_policy_nonce_directives=(generator)
|
|
90
|
+
set_header(NONCE_DIRECTIVES, generator)
|
|
91
|
+
end
|
|
92
|
+
|
|
83
93
|
def content_security_policy_nonce
|
|
84
94
|
if content_security_policy_nonce_generator
|
|
85
95
|
if nonce = get_header(NONCE)
|
|
@@ -127,14 +137,15 @@ module ActionDispatch #:nodoc:
|
|
|
127
137
|
manifest_src: "manifest-src",
|
|
128
138
|
media_src: "media-src",
|
|
129
139
|
object_src: "object-src",
|
|
140
|
+
prefetch_src: "prefetch-src",
|
|
130
141
|
script_src: "script-src",
|
|
131
142
|
style_src: "style-src",
|
|
132
143
|
worker_src: "worker-src"
|
|
133
144
|
}.freeze
|
|
134
145
|
|
|
135
|
-
|
|
146
|
+
DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze
|
|
136
147
|
|
|
137
|
-
private_constant :MAPPINGS, :DIRECTIVES, :
|
|
148
|
+
private_constant :MAPPINGS, :DIRECTIVES, :DEFAULT_NONCE_DIRECTIVES
|
|
138
149
|
|
|
139
150
|
attr_reader :directives
|
|
140
151
|
|
|
@@ -203,8 +214,9 @@ module ActionDispatch #:nodoc:
|
|
|
203
214
|
end
|
|
204
215
|
end
|
|
205
216
|
|
|
206
|
-
def build(context = nil, nonce = nil)
|
|
207
|
-
|
|
217
|
+
def build(context = nil, nonce = nil, nonce_directives = nil)
|
|
218
|
+
nonce_directives = DEFAULT_NONCE_DIRECTIVES if nonce_directives.nil?
|
|
219
|
+
build_directives(context, nonce, nonce_directives).compact.join("; ")
|
|
208
220
|
end
|
|
209
221
|
|
|
210
222
|
private
|
|
@@ -227,10 +239,10 @@ module ActionDispatch #:nodoc:
|
|
|
227
239
|
end
|
|
228
240
|
end
|
|
229
241
|
|
|
230
|
-
def build_directives(context, nonce)
|
|
242
|
+
def build_directives(context, nonce, nonce_directives)
|
|
231
243
|
@directives.map do |directive, sources|
|
|
232
244
|
if sources.is_a?(Array)
|
|
233
|
-
if nonce && nonce_directive?(directive)
|
|
245
|
+
if nonce && nonce_directive?(directive, nonce_directives)
|
|
234
246
|
"#{directive} #{build_directive(sources, context).join(' ')} 'nonce-#{nonce}'"
|
|
235
247
|
else
|
|
236
248
|
"#{directive} #{build_directive(sources, context).join(' ')}"
|
|
@@ -265,8 +277,8 @@ module ActionDispatch #:nodoc:
|
|
|
265
277
|
end
|
|
266
278
|
end
|
|
267
279
|
|
|
268
|
-
def nonce_directive?(directive)
|
|
269
|
-
|
|
280
|
+
def nonce_directive?(directive, nonce_directives)
|
|
281
|
+
nonce_directives.include?(directive)
|
|
270
282
|
end
|
|
271
283
|
end
|
|
272
284
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
3
|
+
require "active_support/parameter_filter"
|
|
4
4
|
|
|
5
5
|
module ActionDispatch
|
|
6
6
|
module Http
|
|
@@ -9,8 +9,8 @@ module ActionDispatch
|
|
|
9
9
|
# sub-hashes of the params hash to filter. Filtering only certain sub-keys
|
|
10
10
|
# from a hash is possible by using the dot notation: 'credit_card.number'.
|
|
11
11
|
# If a block is given, each key and value of the params hash and all
|
|
12
|
-
# sub-hashes
|
|
13
|
-
# String#replace or similar
|
|
12
|
+
# sub-hashes are passed to it, where the value or the key can be replaced using
|
|
13
|
+
# String#replace or similar methods.
|
|
14
14
|
#
|
|
15
15
|
# env["action_dispatch.parameter_filter"] = [:password]
|
|
16
16
|
# => replaces the value to all keys matching /password/i with "[FILTERED]"
|
|
@@ -28,8 +28,8 @@ module ActionDispatch
|
|
|
28
28
|
# => reverses the value to all keys matching /secret/i
|
|
29
29
|
module FilterParameters
|
|
30
30
|
ENV_MATCH = [/RAW_POST_DATA/, "rack.request.form_vars"] # :nodoc:
|
|
31
|
-
NULL_PARAM_FILTER = ParameterFilter.new # :nodoc:
|
|
32
|
-
NULL_ENV_FILTER = ParameterFilter.new ENV_MATCH # :nodoc:
|
|
31
|
+
NULL_PARAM_FILTER = ActiveSupport::ParameterFilter.new # :nodoc:
|
|
32
|
+
NULL_ENV_FILTER = ActiveSupport::ParameterFilter.new ENV_MATCH # :nodoc:
|
|
33
33
|
|
|
34
34
|
def initialize
|
|
35
35
|
super
|
|
@@ -41,6 +41,8 @@ module ActionDispatch
|
|
|
41
41
|
# Returns a hash of parameters with all sensitive data replaced.
|
|
42
42
|
def filtered_parameters
|
|
43
43
|
@filtered_parameters ||= parameter_filter.filter(parameters)
|
|
44
|
+
rescue ActionDispatch::Http::Parameters::ParseError
|
|
45
|
+
@filtered_parameters = {}
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
# Returns a hash of request.env with all sensitive data replaced.
|
|
@@ -69,7 +71,7 @@ module ActionDispatch
|
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
def parameter_filter_for(filters) # :doc:
|
|
72
|
-
ParameterFilter.new(filters)
|
|
74
|
+
ActiveSupport::ParameterFilter.new(filters)
|
|
73
75
|
end
|
|
74
76
|
|
|
75
77
|
KV_RE = "[^&;=]+"
|
|
@@ -121,7 +121,7 @@ module ActionDispatch
|
|
|
121
121
|
# not contained within the headers hash.
|
|
122
122
|
def env_name(key)
|
|
123
123
|
key = key.to_s
|
|
124
|
-
if key
|
|
124
|
+
if HTTP_HEADER.match?(key)
|
|
125
125
|
key = key.upcase.tr("-", "_")
|
|
126
126
|
key = "HTTP_" + key unless CGI_VARIABLES.include?(key)
|
|
127
127
|
end
|
|
@@ -7,6 +7,11 @@ module ActionDispatch
|
|
|
7
7
|
module MimeNegotiation
|
|
8
8
|
extend ActiveSupport::Concern
|
|
9
9
|
|
|
10
|
+
RESCUABLE_MIME_FORMAT_ERRORS = [
|
|
11
|
+
ActionController::BadRequest,
|
|
12
|
+
ActionDispatch::Http::Parameters::ParseError,
|
|
13
|
+
]
|
|
14
|
+
|
|
10
15
|
included do
|
|
11
16
|
mattr_accessor :ignore_accept_header, default: false
|
|
12
17
|
end
|
|
@@ -59,7 +64,7 @@ module ActionDispatch
|
|
|
59
64
|
fetch_header("action_dispatch.request.formats") do |k|
|
|
60
65
|
params_readable = begin
|
|
61
66
|
parameters[:format]
|
|
62
|
-
rescue
|
|
67
|
+
rescue *RESCUABLE_MIME_FORMAT_ERRORS
|
|
63
68
|
false
|
|
64
69
|
end
|
|
65
70
|
|
|
@@ -90,10 +95,7 @@ module ActionDispatch
|
|
|
90
95
|
if variant.all? { |v| v.is_a?(Symbol) }
|
|
91
96
|
@variant = ActiveSupport::ArrayInquirer.new(variant)
|
|
92
97
|
else
|
|
93
|
-
raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols.
|
|
94
|
-
"For security reasons, never directly set the variant to a user-provided value, " \
|
|
95
|
-
"like params[:variant].to_sym. Check user-provided value against a whitelist first, " \
|
|
96
|
-
"then set the variant: request.variant = :tablet if params[:variant] == 'tablet'"
|
|
98
|
+
raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols."
|
|
97
99
|
end
|
|
98
100
|
end
|
|
99
101
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# -*- frozen-string-literal: true -*-
|
|
4
|
-
|
|
5
3
|
require "singleton"
|
|
6
4
|
require "active_support/core_ext/string/starts_ends_with"
|
|
7
5
|
|
|
@@ -74,7 +72,7 @@ module Mime
|
|
|
74
72
|
def initialize(index, name, q = nil)
|
|
75
73
|
@index = index
|
|
76
74
|
@name = name
|
|
77
|
-
q ||= 0.0 if @name == "*/*"
|
|
75
|
+
q ||= 0.0 if @name == "*/*" # Default wildcard match to end of list.
|
|
78
76
|
@q = ((q || 1.0).to_f * 100).to_i
|
|
79
77
|
end
|
|
80
78
|
|
|
@@ -172,6 +170,7 @@ module Mime
|
|
|
172
170
|
def parse(accept_header)
|
|
173
171
|
if !accept_header.include?(",")
|
|
174
172
|
accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first
|
|
173
|
+
return [] unless accept_header
|
|
175
174
|
parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)].compact
|
|
176
175
|
else
|
|
177
176
|
list, index = [], 0
|
|
@@ -223,7 +222,18 @@ module Mime
|
|
|
223
222
|
|
|
224
223
|
attr_reader :hash
|
|
225
224
|
|
|
225
|
+
MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
|
|
226
|
+
MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
|
|
227
|
+
MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?"
|
|
228
|
+
MIME_PARAMETER = "\s*\;\s+#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
|
|
229
|
+
MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?:\s*#{MIME_PARAMETER}\s*)*)\z/
|
|
230
|
+
|
|
231
|
+
class InvalidMimeType < StandardError; end
|
|
232
|
+
|
|
226
233
|
def initialize(string, symbol = nil, synonyms = [])
|
|
234
|
+
unless MIME_REGEXP.match?(string)
|
|
235
|
+
raise InvalidMimeType, "#{string.inspect} is not a valid MIME type"
|
|
236
|
+
end
|
|
227
237
|
@symbol, @synonyms = symbol, synonyms
|
|
228
238
|
@string = string
|
|
229
239
|
@hash = [@string, @synonyms, @symbol].hash
|
|
@@ -279,8 +289,6 @@ module Mime
|
|
|
279
289
|
|
|
280
290
|
def all?; false; end
|
|
281
291
|
|
|
282
|
-
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
|
283
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
|
284
292
|
protected
|
|
285
293
|
|
|
286
294
|
attr_reader :string, :synonyms
|
|
@@ -307,7 +315,7 @@ module Mime
|
|
|
307
315
|
include Singleton
|
|
308
316
|
|
|
309
317
|
def initialize
|
|
310
|
-
super "*/*",
|
|
318
|
+
super "*/*", nil
|
|
311
319
|
end
|
|
312
320
|
|
|
313
321
|
def all?; true; end
|