actionpack 6.1.7 → 7.0.4.1

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.

Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +269 -406
  3. data/MIT-LICENSE +1 -0
  4. data/README.rdoc +2 -3
  5. data/lib/abstract_controller/asset_paths.rb +1 -1
  6. data/lib/abstract_controller/base.rb +13 -26
  7. data/lib/abstract_controller/caching/fragments.rb +2 -2
  8. data/lib/abstract_controller/caching.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +21 -7
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/error.rb +1 -1
  12. data/lib/abstract_controller/helpers.rb +4 -3
  13. data/lib/abstract_controller/logger.rb +1 -1
  14. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  15. data/lib/abstract_controller/translation.rb +3 -2
  16. data/lib/abstract_controller/url_for.rb +4 -6
  17. data/lib/action_controller/api.rb +6 -6
  18. data/lib/action_controller/base.rb +5 -4
  19. data/lib/action_controller/form_builder.rb +2 -2
  20. data/lib/action_controller/log_subscriber.rb +4 -3
  21. data/lib/action_controller/metal/conditional_get.rb +39 -2
  22. data/lib/action_controller/metal/content_security_policy.rb +36 -2
  23. data/lib/action_controller/metal/cookies.rb +1 -1
  24. data/lib/action_controller/metal/data_streaming.rb +5 -13
  25. data/lib/action_controller/metal/exceptions.rb +19 -30
  26. data/lib/action_controller/metal/flash.rb +6 -2
  27. data/lib/action_controller/metal/helpers.rb +2 -2
  28. data/lib/action_controller/metal/http_authentication.rb +66 -39
  29. data/lib/action_controller/metal/instrumentation.rb +57 -52
  30. data/lib/action_controller/metal/live.rb +43 -2
  31. data/lib/action_controller/metal/mime_responds.rb +3 -3
  32. data/lib/action_controller/metal/params_wrapper.rb +20 -11
  33. data/lib/action_controller/metal/permissions_policy.rb +19 -28
  34. data/lib/action_controller/metal/redirecting.rb +93 -18
  35. data/lib/action_controller/metal/renderers.rb +10 -11
  36. data/lib/action_controller/metal/rendering.rb +8 -8
  37. data/lib/action_controller/metal/request_forgery_protection.rb +78 -29
  38. data/lib/action_controller/metal/rescue.rb +1 -1
  39. data/lib/action_controller/metal/streaming.rb +6 -8
  40. data/lib/action_controller/metal/strong_parameters.rb +100 -54
  41. data/lib/action_controller/metal/testing.rb +9 -2
  42. data/lib/action_controller/metal/url_for.rb +3 -3
  43. data/lib/action_controller/metal.rb +10 -13
  44. data/lib/action_controller/railtie.rb +49 -6
  45. data/lib/action_controller/renderer.rb +1 -1
  46. data/lib/action_controller/test_case.rb +28 -7
  47. data/lib/action_controller.rb +2 -5
  48. data/lib/action_dispatch/http/cache.rb +14 -7
  49. data/lib/action_dispatch/http/content_security_policy.rb +108 -35
  50. data/lib/action_dispatch/http/filter_parameters.rb +5 -0
  51. data/lib/action_dispatch/http/mime_negotiation.rb +15 -5
  52. data/lib/action_dispatch/http/mime_type.rb +9 -11
  53. data/lib/action_dispatch/http/parameters.rb +5 -5
  54. data/lib/action_dispatch/http/permissions_policy.rb +17 -1
  55. data/lib/action_dispatch/http/request.rb +12 -21
  56. data/lib/action_dispatch/http/response.rb +3 -16
  57. data/lib/action_dispatch/http/url.rb +11 -19
  58. data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
  59. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
  60. data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
  61. data/lib/action_dispatch/journey/nodes/node.rb +70 -5
  62. data/lib/action_dispatch/journey/path/pattern.rb +22 -13
  63. data/lib/action_dispatch/journey/route.rb +6 -13
  64. data/lib/action_dispatch/journey/router/utils.rb +2 -2
  65. data/lib/action_dispatch/journey/router.rb +1 -1
  66. data/lib/action_dispatch/journey/routes.rb +3 -3
  67. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  68. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  69. data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
  70. data/lib/action_dispatch/middleware/cookies.rb +42 -27
  71. data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
  72. data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
  73. data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
  74. data/lib/action_dispatch/middleware/executor.rb +3 -0
  75. data/lib/action_dispatch/middleware/flash.rb +17 -18
  76. data/lib/action_dispatch/middleware/host_authorization.rb +1 -12
  77. data/lib/action_dispatch/middleware/remote_ip.rb +16 -4
  78. data/lib/action_dispatch/middleware/request_id.rb +1 -1
  79. data/lib/action_dispatch/middleware/server_timing.rb +76 -0
  80. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
  81. data/lib/action_dispatch/middleware/session/cookie_store.rb +9 -9
  82. data/lib/action_dispatch/middleware/show_exceptions.rb +7 -9
  83. data/lib/action_dispatch/middleware/stack.rb +27 -9
  84. data/lib/action_dispatch/middleware/static.rb +2 -6
  85. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
  86. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
  87. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
  88. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +3 -2
  89. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +2 -0
  90. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
  91. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
  92. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
  93. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
  94. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
  95. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  96. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  97. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
  98. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +5 -14
  99. data/lib/action_dispatch/railtie.rb +8 -2
  100. data/lib/action_dispatch/request/session.rb +43 -13
  101. data/lib/action_dispatch/routing/inspector.rb +1 -1
  102. data/lib/action_dispatch/routing/mapper.rb +59 -83
  103. data/lib/action_dispatch/routing/redirection.rb +5 -2
  104. data/lib/action_dispatch/routing/route_set.rb +17 -7
  105. data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
  106. data/lib/action_dispatch/routing/url_for.rb +4 -5
  107. data/lib/action_dispatch/routing.rb +5 -6
  108. data/lib/action_dispatch/system_test_case.rb +5 -5
  109. data/lib/action_dispatch/system_testing/browser.rb +2 -12
  110. data/lib/action_dispatch/system_testing/driver.rb +35 -11
  111. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +11 -7
  112. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
  113. data/lib/action_dispatch/testing/assertions/routing.rb +3 -2
  114. data/lib/action_dispatch/testing/assertions.rb +2 -5
  115. data/lib/action_dispatch/testing/integration.rb +6 -8
  116. data/lib/action_dispatch/testing/test_process.rb +3 -29
  117. data/lib/action_dispatch/testing/test_response.rb +20 -2
  118. data/lib/action_dispatch.rb +1 -0
  119. data/lib/action_pack/gem_version.rb +5 -5
  120. data/lib/action_pack/version.rb +1 -1
  121. metadata +16 -15
@@ -3,6 +3,7 @@
3
3
  require "abstract_controller"
4
4
  require "action_dispatch"
5
5
  require "action_controller/metal/strong_parameters"
6
+ require "action_controller/metal/exceptions"
6
7
 
7
8
  module ActionController
8
9
  extend ActiveSupport::Autoload
@@ -18,10 +19,6 @@ module ActionController
18
19
  end
19
20
 
20
21
  autoload_under "metal" do
21
- eager_autoload do
22
- autoload :Live
23
- end
24
-
25
22
  autoload :ConditionalGet
26
23
  autoload :ContentSecurityPolicy
27
24
  autoload :Cookies
@@ -37,6 +34,7 @@ module ActionController
37
34
  autoload :BasicImplicitRender
38
35
  autoload :ImplicitRender
39
36
  autoload :Instrumentation
37
+ autoload :Live
40
38
  autoload :Logging
41
39
  autoload :MimeResponds
42
40
  autoload :ParamsWrapper
@@ -65,5 +63,4 @@ require "active_support/core_ext/module/attribute_accessors"
65
63
  require "active_support/core_ext/load_error"
66
64
  require "active_support/core_ext/module/attr_internal"
67
65
  require "active_support/core_ext/name_error"
68
- require "active_support/core_ext/uri"
69
66
  require "active_support/inflector"
@@ -18,7 +18,7 @@ module ActionDispatch
18
18
  end
19
19
 
20
20
  def if_none_match_etags
21
- if_none_match ? if_none_match.split(/\s*,\s*/) : []
21
+ if_none_match ? if_none_match.split(",").each(&:strip!) : []
22
22
  end
23
23
 
24
24
  def not_modified?(modified_at)
@@ -187,13 +187,20 @@ module ActionDispatch
187
187
 
188
188
  return if control.empty? && cache_control.empty? # Let middleware handle default behavior
189
189
 
190
- if extras = control.delete(:extras)
191
- cache_control[:extras] ||= []
192
- cache_control[:extras] += extras
193
- cache_control[:extras].uniq!
194
- end
190
+ if cache_control.any?
191
+ # Any caching directive coming from a controller overrides
192
+ # no-cache/no-store in the default Cache-Control header.
193
+ control.delete(:no_cache)
194
+ control.delete(:no_store)
195
195
 
196
- control.merge! cache_control
196
+ if extras = control.delete(:extras)
197
+ cache_control[:extras] ||= []
198
+ cache_control[:extras] += extras
199
+ cache_control[:extras].uniq!
200
+ end
201
+
202
+ control.merge! cache_control
203
+ end
197
204
 
198
205
  options = []
199
206
 
@@ -3,7 +3,24 @@
3
3
  require "active_support/core_ext/object/deep_dup"
4
4
  require "active_support/core_ext/array/wrap"
5
5
 
6
- module ActionDispatch #:nodoc:
6
+ module ActionDispatch # :nodoc:
7
+ # Configures the HTTP
8
+ # {Content-Security-Policy}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy]
9
+ # response header to help protect against XSS and injection attacks.
10
+ #
11
+ # Example global policy:
12
+ #
13
+ # Rails.application.config.content_security_policy do |policy|
14
+ # policy.default_src :self, :https
15
+ # policy.font_src :self, :https, :data
16
+ # policy.img_src :self, :https, :data
17
+ # policy.object_src :none
18
+ # policy.script_src :self, :https
19
+ # policy.style_src :self, :https
20
+ #
21
+ # # Specify URI for violation reports
22
+ # policy.report_uri "/csp-violation-report-endpoint"
23
+ # end
7
24
  class ContentSecurityPolicy
8
25
  class Middleware
9
26
  CONTENT_TYPE = "Content-Type"
@@ -100,43 +117,47 @@ module ActionDispatch #:nodoc:
100
117
  end
101
118
 
102
119
  MAPPINGS = {
103
- self: "'self'",
104
- unsafe_eval: "'unsafe-eval'",
105
- unsafe_inline: "'unsafe-inline'",
106
- none: "'none'",
107
- http: "http:",
108
- https: "https:",
109
- data: "data:",
110
- mediastream: "mediastream:",
111
- blob: "blob:",
112
- filesystem: "filesystem:",
113
- report_sample: "'report-sample'",
114
- strict_dynamic: "'strict-dynamic'",
115
- ws: "ws:",
116
- wss: "wss:"
120
+ self: "'self'",
121
+ unsafe_eval: "'unsafe-eval'",
122
+ unsafe_inline: "'unsafe-inline'",
123
+ none: "'none'",
124
+ http: "http:",
125
+ https: "https:",
126
+ data: "data:",
127
+ mediastream: "mediastream:",
128
+ allow_duplicates: "'allow-duplicates'",
129
+ blob: "blob:",
130
+ filesystem: "filesystem:",
131
+ report_sample: "'report-sample'",
132
+ script: "'script'",
133
+ strict_dynamic: "'strict-dynamic'",
134
+ ws: "ws:",
135
+ wss: "wss:"
117
136
  }.freeze
118
137
 
119
138
  DIRECTIVES = {
120
- base_uri: "base-uri",
121
- child_src: "child-src",
122
- connect_src: "connect-src",
123
- default_src: "default-src",
124
- font_src: "font-src",
125
- form_action: "form-action",
126
- frame_ancestors: "frame-ancestors",
127
- frame_src: "frame-src",
128
- img_src: "img-src",
129
- manifest_src: "manifest-src",
130
- media_src: "media-src",
131
- object_src: "object-src",
132
- prefetch_src: "prefetch-src",
133
- script_src: "script-src",
134
- script_src_attr: "script-src-attr",
135
- script_src_elem: "script-src-elem",
136
- style_src: "style-src",
137
- style_src_attr: "style-src-attr",
138
- style_src_elem: "style-src-elem",
139
- worker_src: "worker-src"
139
+ base_uri: "base-uri",
140
+ child_src: "child-src",
141
+ connect_src: "connect-src",
142
+ default_src: "default-src",
143
+ font_src: "font-src",
144
+ form_action: "form-action",
145
+ frame_ancestors: "frame-ancestors",
146
+ frame_src: "frame-src",
147
+ img_src: "img-src",
148
+ manifest_src: "manifest-src",
149
+ media_src: "media-src",
150
+ object_src: "object-src",
151
+ prefetch_src: "prefetch-src",
152
+ require_trusted_types_for: "require-trusted-types-for",
153
+ script_src: "script-src",
154
+ script_src_attr: "script-src-attr",
155
+ script_src_elem: "script-src-elem",
156
+ style_src: "style-src",
157
+ style_src_attr: "style-src-attr",
158
+ style_src_elem: "style-src-elem",
159
+ trusted_types: "trusted-types",
160
+ worker_src: "worker-src"
140
161
  }.freeze
141
162
 
142
163
  DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze
@@ -164,6 +185,15 @@ module ActionDispatch #:nodoc:
164
185
  end
165
186
  end
166
187
 
188
+ # Specify whether to prevent the user agent from loading any assets over
189
+ # HTTP when the page uses HTTPS:
190
+ #
191
+ # policy.block_all_mixed_content
192
+ #
193
+ # Pass +false+ to allow it again:
194
+ #
195
+ # policy.block_all_mixed_content false
196
+ #
167
197
  def block_all_mixed_content(enabled = true)
168
198
  if enabled
169
199
  @directives["block-all-mixed-content"] = true
@@ -172,6 +202,14 @@ module ActionDispatch #:nodoc:
172
202
  end
173
203
  end
174
204
 
205
+ # Restricts the set of plugins that can be embedded:
206
+ #
207
+ # policy.plugin_types "application/x-shockwave-flash"
208
+ #
209
+ # Leave empty to allow all plugins:
210
+ #
211
+ # policy.plugin_types
212
+ #
175
213
  def plugin_types(*types)
176
214
  if types.first
177
215
  @directives["plugin-types"] = types
@@ -180,10 +218,24 @@ module ActionDispatch #:nodoc:
180
218
  end
181
219
  end
182
220
 
221
+ # Enable the {report-uri}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri]
222
+ # directive. Violation reports will be sent to the specified URI:
223
+ #
224
+ # policy.report_uri "/csp-violation-report-endpoint"
225
+ #
183
226
  def report_uri(uri)
184
227
  @directives["report-uri"] = [uri]
185
228
  end
186
229
 
230
+ # Specify asset types for which {Subresource Integrity}[https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity]
231
+ # is required:
232
+ #
233
+ # policy.require_sri_for :script, :style
234
+ #
235
+ # Leave empty to not require Subresource Integrity:
236
+ #
237
+ # policy.require_sri_for
238
+ #
187
239
  def require_sri_for(*types)
188
240
  if types.first
189
241
  @directives["require-sri-for"] = types
@@ -192,6 +244,19 @@ module ActionDispatch #:nodoc:
192
244
  end
193
245
  end
194
246
 
247
+ # Specify whether a {sandbox}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox]
248
+ # should be enabled for the requested resource:
249
+ #
250
+ # policy.sandbox
251
+ #
252
+ # Values can be passed as arguments:
253
+ #
254
+ # policy.sandbox "allow-scripts", "allow-modals"
255
+ #
256
+ # Pass +false+ to disable the sandbox:
257
+ #
258
+ # policy.sandbox false
259
+ #
195
260
  def sandbox(*values)
196
261
  if values.empty?
197
262
  @directives["sandbox"] = true
@@ -202,6 +267,14 @@ module ActionDispatch #:nodoc:
202
267
  end
203
268
  end
204
269
 
270
+ # Specify whether user agents should treat any assets over HTTP as HTTPS:
271
+ #
272
+ # policy.upgrade_insecure_requests
273
+ #
274
+ # Pass +false+ to disable it:
275
+ #
276
+ # policy.upgrade_insecure_requests false
277
+ #
205
278
  def upgrade_insecure_requests(enabled = true)
206
279
  if enabled
207
280
  @directives["upgrade-insecure-requests"] = true
@@ -18,6 +18,11 @@ module ActionDispatch
18
18
  # env["action_dispatch.parameter_filter"] = [:foo, "bar"]
19
19
  # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
20
20
  #
21
+ # env["action_dispatch.parameter_filter"] = [ /\Apin\z/i, /\Apin_/i ]
22
+ # => replaces the value for the exact (case-insensitive) key 'pin' and all
23
+ # (case-insensitive) keys beginning with 'pin_', with "[FILTERED]"
24
+ # Does not match keys with 'pin' as a substring, such as 'shipping_id'.
25
+ #
21
26
  # env["action_dispatch.parameter_filter"] = [ "credit_card.code" ]
22
27
  # => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
23
28
  # change { file: { code: "xxxx"} }
@@ -16,12 +16,13 @@ module ActionDispatch
16
16
 
17
17
  included do
18
18
  mattr_accessor :ignore_accept_header, default: false
19
+ cattr_accessor :return_only_media_type_on_content_type, default: false
19
20
  end
20
21
 
21
22
  # The MIME type of the HTTP request, such as Mime[:xml].
22
23
  def content_mime_type
23
24
  fetch_header("action_dispatch.request.content_type") do |k|
24
- v = if get_header("CONTENT_TYPE") =~ /^([^,\;]*)/
25
+ v = if get_header("CONTENT_TYPE") =~ /^([^,;]*)/
25
26
  Mime::Type.lookup($1.strip.downcase)
26
27
  else
27
28
  nil
@@ -33,7 +34,16 @@ module ActionDispatch
33
34
  end
34
35
 
35
36
  def content_type
36
- content_mime_type && content_mime_type.to_s
37
+ if self.class.return_only_media_type_on_content_type
38
+ ActiveSupport::Deprecation.warn(
39
+ "Rails 7.1 will return Content-Type header without modification." \
40
+ " If you want just the MIME type, please use `#media_type` instead."
41
+ )
42
+
43
+ content_mime_type&.to_s
44
+ else
45
+ super
46
+ end
37
47
  end
38
48
 
39
49
  def has_content_type? # :nodoc:
@@ -92,7 +102,7 @@ module ActionDispatch
92
102
  def variant=(variant)
93
103
  variant = Array(variant)
94
104
 
95
- if variant.all? { |v| v.is_a?(Symbol) }
105
+ if variant.all?(Symbol)
96
106
  @variant = ActiveSupport::ArrayInquirer.new(variant)
97
107
  else
98
108
  raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols."
@@ -122,8 +132,8 @@ module ActionDispatch
122
132
  # Sets the \formats by string extensions. This differs from #format= by allowing you
123
133
  # to set multiple, ordered formats, which is useful when you want to have a fallback.
124
134
  #
125
- # In this example, the :iphone format will be used if it's available, otherwise it'll fallback
126
- # to the :html format.
135
+ # In this example, the +:iphone+ format will be used if it's available, otherwise it'll fallback
136
+ # to the +:html+ format.
127
137
  #
128
138
  # class ApplicationController < ActionController::Base
129
139
  # before_action :adjust_format_for_iphone_with_html_fallback
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "singleton"
4
- require "active_support/core_ext/symbol/starts_ends_with"
5
4
 
6
5
  module Mime
7
6
  class Mimes
@@ -14,8 +13,8 @@ module Mime
14
13
  @symbols = []
15
14
  end
16
15
 
17
- def each
18
- @mimes.each { |x| yield x }
16
+ def each(&block)
17
+ @mimes.each(&block)
19
18
  end
20
19
 
21
20
  def <<(type)
@@ -43,9 +42,9 @@ module Mime
43
42
  Type.lookup_by_extension(type)
44
43
  end
45
44
 
46
- def fetch(type)
45
+ def fetch(type, &block)
47
46
  return type if type.is_a?(Type)
48
- EXTENSION_LOOKUP.fetch(type.to_s) { |k| yield k }
47
+ EXTENSION_LOOKUP.fetch(type.to_s, &block)
49
48
  end
50
49
  end
51
50
 
@@ -68,7 +67,7 @@ module Mime
68
67
  @register_callbacks = []
69
68
 
70
69
  # A simple helper class used in parsing the accept header.
71
- class AcceptItem #:nodoc:
70
+ class AcceptItem # :nodoc:
72
71
  attr_accessor :index, :name, :q
73
72
  alias :to_s :name
74
73
 
@@ -86,7 +85,7 @@ module Mime
86
85
  end
87
86
  end
88
87
 
89
- class AcceptList #:nodoc:
88
+ class AcceptList # :nodoc:
90
89
  def self.sort!(list)
91
90
  list.sort!
92
91
 
@@ -226,10 +225,9 @@ module Mime
226
225
  attr_reader :hash
227
226
 
228
227
  MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
229
- MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
230
- MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?"
231
- MIME_PARAMETER = "\s*\;\s*#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
232
- MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>\s*#{MIME_PARAMETER}\s*)*)\z/
228
+ MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?#{MIME_NAME}#{Regexp.escape('"')}?"
229
+ MIME_PARAMETER = "\s*;\s*#{MIME_NAME}(?:=#{MIME_PARAMETER_VALUE})?"
230
+ MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>#{MIME_PARAMETER})*\s*)\z/
233
231
 
234
232
  class InvalidMimeType < StandardError; end
235
233
 
@@ -17,8 +17,8 @@ module ActionDispatch
17
17
  # Raised when raw data from the request cannot be parsed by the parser
18
18
  # defined for request's content MIME type.
19
19
  class ParseError < StandardError
20
- def initialize
21
- super($!.message)
20
+ def initialize(message = $!.message)
21
+ super(message)
22
22
  end
23
23
  end
24
24
 
@@ -62,7 +62,7 @@ module ActionDispatch
62
62
  end
63
63
  alias :params :parameters
64
64
 
65
- def path_parameters=(parameters) #:nodoc:
65
+ def path_parameters=(parameters) # :nodoc:
66
66
  delete_header("action_dispatch.request.parameters")
67
67
 
68
68
  parameters = Request::Utils.set_binary_encoding(self, parameters, parameters[:controller], parameters[:action])
@@ -78,7 +78,7 @@ module ActionDispatch
78
78
  # Returns a hash with the \parameters used to form the \path of the request.
79
79
  # Returned hash keys are strings:
80
80
  #
81
- # {'action' => 'my_action', 'controller' => 'my_controller'}
81
+ # { action: "my_action", controller: "my_controller" }
82
82
  def path_parameters
83
83
  get_header(PARAMETERS_KEY) || set_header(PARAMETERS_KEY, {})
84
84
  end
@@ -93,7 +93,7 @@ module ActionDispatch
93
93
  strategy.call(raw_post)
94
94
  rescue # JSON or Ruby code block errors.
95
95
  log_parse_error_once
96
- raise ParseError
96
+ raise ParseError, "Error occurred while parsing request parameters"
97
97
  end
98
98
  end
99
99
 
@@ -2,7 +2,23 @@
2
2
 
3
3
  require "active_support/core_ext/object/deep_dup"
4
4
 
5
- module ActionDispatch #:nodoc:
5
+ module ActionDispatch # :nodoc:
6
+ # Configures the HTTP
7
+ # {Feature-Policy}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy]
8
+ # response header to specify which browser features the current document and
9
+ # its iframes can use.
10
+ #
11
+ # Example global policy:
12
+ #
13
+ # Rails.application.config.permissions_policy do |policy|
14
+ # policy.camera :none
15
+ # policy.gyroscope :none
16
+ # policy.microphone :none
17
+ # policy.usb :none
18
+ # policy.fullscreen :self
19
+ # policy.payment :self, "https://secure.example.com"
20
+ # end
21
+ #
6
22
  class PermissionsPolicy
7
23
  class Middleware
8
24
  CONTENT_TYPE = "Content-Type"
@@ -42,11 +42,8 @@ module ActionDispatch
42
42
  HTTP_NEGOTIATE HTTP_PRAGMA HTTP_CLIENT_IP
43
43
  HTTP_X_FORWARDED_FOR HTTP_ORIGIN HTTP_VERSION
44
44
  HTTP_X_CSRF_TOKEN HTTP_X_REQUEST_ID HTTP_X_FORWARDED_HOST
45
- SERVER_ADDR
46
45
  ].freeze
47
46
 
48
- # TODO: Remove SERVER_ADDR when we remove support to Rack 2.1.
49
- # See https://github.com/rack/rack/commit/c173b188d81ee437b588c1e046a1c9f031dea550
50
47
  ENV_METHODS.each do |env|
51
48
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
52
49
  # frozen_string_literal: true
@@ -90,7 +87,7 @@ module ActionDispatch
90
87
  controller_param = name.underscore
91
88
  const_name = controller_param.camelize << "Controller"
92
89
  begin
93
- ActiveSupport::Dependencies.constantize(const_name)
90
+ const_name.constantize
94
91
  rescue NameError => error
95
92
  if error.missing_name == const_name || const_name.start_with?("#{error.missing_name}::")
96
93
  raise MissingController.new(error.message, error.name)
@@ -165,7 +162,7 @@ module ActionDispatch
165
162
  set_header(routes.env_key, name.dup)
166
163
  end
167
164
 
168
- def request_method=(request_method) #:nodoc:
165
+ def request_method=(request_method) # :nodoc:
169
166
  if check_method(request_method)
170
167
  @request_method = set_header("REQUEST_METHOD", request_method)
171
168
  end
@@ -266,7 +263,7 @@ module ActionDispatch
266
263
  # # get "/articles"
267
264
  # request.media_type # => "application/x-www-form-urlencoded"
268
265
  def media_type
269
- content_mime_type.to_s
266
+ content_mime_type&.to_s
270
267
  end
271
268
 
272
269
  # Returns the content length of the request as an integer.
@@ -301,8 +298,8 @@ module ActionDispatch
301
298
  ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc:
302
299
 
303
300
  # Returns the unique request id, which is based on either the X-Request-Id header that can
304
- # be generated by a firewall, load balancer, or web server or by the RequestId middleware
305
- # (which sets the action_dispatch.request_id environment variable).
301
+ # be generated by a firewall, load balancer, or web server, or by the RequestId middleware
302
+ # (which sets the +action_dispatch.request_id+ environment variable).
306
303
  #
307
304
  # This unique ID is useful for tracing a request from end-to-end as part of logging or debugging.
308
305
  # This relies on the Rack variable set by the ActionDispatch::RequestId middleware.
@@ -355,21 +352,15 @@ module ActionDispatch
355
352
  FORM_DATA_MEDIA_TYPES.include?(media_type)
356
353
  end
357
354
 
358
- def body_stream #:nodoc:
355
+ def body_stream # :nodoc:
359
356
  get_header("rack.input")
360
357
  end
361
358
 
362
- # TODO This should be broken apart into AD::Request::Session and probably
363
- # be included by the session middleware.
364
359
  def reset_session
365
- if session && session.respond_to?(:destroy)
366
- session.destroy
367
- else
368
- self.session = {}
369
- end
360
+ session.destroy
370
361
  end
371
362
 
372
- def session=(session) #:nodoc:
363
+ def session=(session) # :nodoc:
373
364
  Session.set self, session
374
365
  end
375
366
 
@@ -434,10 +425,6 @@ module ActionDispatch
434
425
  def commit_flash
435
426
  end
436
427
 
437
- def ssl?
438
- super || scheme == "wss"
439
- end
440
-
441
428
  def inspect # :nodoc:
442
429
  "#<#{self.class.name} #{method} #{original_url.dump} for #{remote_ip}>"
443
430
  end
@@ -447,6 +434,10 @@ module ActionDispatch
447
434
  HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS[0...-1].join(', ')}, and #{HTTP_METHODS[-1]}")
448
435
  name
449
436
  end
437
+
438
+ def default_session
439
+ Session.disabled(self)
440
+ end
450
441
  end
451
442
  end
452
443
 
@@ -21,9 +21,8 @@ module ActionDispatch # :nodoc:
21
21
  # Nevertheless, integration tests may want to inspect controller responses in
22
22
  # more detail, and that's when \Response can be useful for application
23
23
  # developers. Integration test methods such as
24
- # ActionDispatch::Integration::Session#get and
25
- # ActionDispatch::Integration::Session#post return objects of type
26
- # TestResponse (which are of course also of type \Response).
24
+ # Integration::RequestHelpers#get and Integration::RequestHelpers#post return
25
+ # objects of type TestResponse (which are of course also of type \Response).
27
26
  #
28
27
  # For example, the following demo integration test prints the body of the
29
28
  # controller response to the console:
@@ -86,18 +85,6 @@ module ActionDispatch # :nodoc:
86
85
  cattr_accessor :default_charset, default: "utf-8"
87
86
  cattr_accessor :default_headers
88
87
 
89
- def self.return_only_media_type_on_content_type=(*)
90
- ActiveSupport::Deprecation.warn(
91
- ".return_only_media_type_on_content_type= is dreprecated with no replacement and will be removed in 7.0."
92
- )
93
- end
94
-
95
- def self.return_only_media_type_on_content_type
96
- ActiveSupport::Deprecation.warn(
97
- ".return_only_media_type_on_content_type is dreprecated with no replacement and will be removed in 7.0."
98
- )
99
- end
100
-
101
88
  include Rack::Response::Helpers
102
89
  # Aliasing these off because AD::Http::Cache::Response defines them.
103
90
  alias :_cache_control :cache_control
@@ -336,7 +323,7 @@ module ActionDispatch # :nodoc:
336
323
  # Avoid having to pass an open file handle as the response body.
337
324
  # Rack::Sendfile will usually intercept the response and uses
338
325
  # the path directly, so there is no reason to open the file.
339
- class FileBody #:nodoc:
326
+ class FileBody # :nodoc:
340
327
  attr_reader :to_path
341
328
 
342
329
  def initialize(path)
@@ -71,7 +71,8 @@ module ActionDispatch
71
71
  path = options[:script_name].to_s.chomp("/")
72
72
  path << options[:path] if options.key?(:path)
73
73
 
74
- add_trailing_slash(path) if options[:trailing_slash]
74
+ path = "/" if options[:trailing_slash] && path.blank?
75
+
75
76
  add_params(path, options[:params]) if options.key?(:params)
76
77
  add_anchor(path, options[:anchor]) if options.key?(:anchor)
77
78
 
@@ -101,14 +102,6 @@ module ActionDispatch
101
102
  parts[0..-(tld_length + 2)]
102
103
  end
103
104
 
104
- def add_trailing_slash(path)
105
- if path.include?("?")
106
- path.sub!(/\?/, '/\&')
107
- elsif !path.include?(".")
108
- path.sub!(/[^\/]\z|\A\z/, '\&/')
109
- end
110
- end
111
-
112
105
  def build_host_url(host, port, protocol, options, path)
113
106
  if match = host.match(HOST_REGEXP)
114
107
  protocol ||= match[1] unless protocol == false
@@ -222,7 +215,7 @@ module ActionDispatch
222
215
  if forwarded = x_forwarded_host.presence
223
216
  forwarded.split(/,\s?/).last
224
217
  else
225
- get_header("HTTP_HOST") || "#{server_name || server_addr}:#{get_header('SERVER_PORT')}"
218
+ get_header("HTTP_HOST") || "#{server_name}:#{get_header('SERVER_PORT')}"
226
219
  end
227
220
  end
228
221
 
@@ -258,12 +251,10 @@ module ActionDispatch
258
251
  # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
259
252
  # req.port # => 8080
260
253
  def port
261
- @port ||= begin
262
- if raw_host_with_port =~ /:(\d+)$/
263
- $1.to_i
264
- else
265
- standard_port
266
- end
254
+ @port ||= if raw_host_with_port =~ /:(\d+)$/
255
+ $1.to_i
256
+ else
257
+ standard_port
267
258
  end
268
259
  end
269
260
 
@@ -272,9 +263,10 @@ module ActionDispatch
272
263
  # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
273
264
  # req.standard_port # => 80
274
265
  def standard_port
275
- case protocol
276
- when "https://" then 443
277
- else 80
266
+ if "https://" == protocol
267
+ 443
268
+ else
269
+ 80
278
270
  end
279
271
  end
280
272