actionpack 7.1.5.1 → 7.2.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.

Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -642
  3. data/lib/abstract_controller/asset_paths.rb +2 -0
  4. data/lib/abstract_controller/base.rb +102 -98
  5. data/lib/abstract_controller/caching/fragments.rb +50 -53
  6. data/lib/abstract_controller/caching.rb +2 -0
  7. data/lib/abstract_controller/callbacks.rb +66 -64
  8. data/lib/abstract_controller/collector.rb +6 -6
  9. data/lib/abstract_controller/deprecator.rb +2 -0
  10. data/lib/abstract_controller/error.rb +2 -0
  11. data/lib/abstract_controller/helpers.rb +70 -85
  12. data/lib/abstract_controller/logger.rb +2 -0
  13. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  14. data/lib/abstract_controller/rendering.rb +13 -12
  15. data/lib/abstract_controller/translation.rb +12 -13
  16. data/lib/abstract_controller/url_for.rb +8 -6
  17. data/lib/abstract_controller.rb +2 -0
  18. data/lib/action_controller/api/api_rendering.rb +2 -0
  19. data/lib/action_controller/api.rb +74 -72
  20. data/lib/action_controller/base.rb +155 -117
  21. data/lib/action_controller/caching.rb +15 -12
  22. data/lib/action_controller/deprecator.rb +2 -0
  23. data/lib/action_controller/form_builder.rb +20 -17
  24. data/lib/action_controller/log_subscriber.rb +3 -1
  25. data/lib/action_controller/metal/allow_browser.rb +119 -0
  26. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  27. data/lib/action_controller/metal/conditional_get.rb +188 -174
  28. data/lib/action_controller/metal/content_security_policy.rb +25 -24
  29. data/lib/action_controller/metal/cookies.rb +4 -2
  30. data/lib/action_controller/metal/data_streaming.rb +64 -55
  31. data/lib/action_controller/metal/default_headers.rb +5 -3
  32. data/lib/action_controller/metal/etag_with_flash.rb +3 -1
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
  34. data/lib/action_controller/metal/exceptions.rb +11 -9
  35. data/lib/action_controller/metal/flash.rb +12 -10
  36. data/lib/action_controller/metal/head.rb +12 -10
  37. data/lib/action_controller/metal/helpers.rb +63 -55
  38. data/lib/action_controller/metal/http_authentication.rb +214 -203
  39. data/lib/action_controller/metal/implicit_render.rb +17 -15
  40. data/lib/action_controller/metal/instrumentation.rb +15 -12
  41. data/lib/action_controller/metal/live.rb +113 -107
  42. data/lib/action_controller/metal/logging.rb +6 -4
  43. data/lib/action_controller/metal/mime_responds.rb +151 -142
  44. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  45. data/lib/action_controller/metal/params_wrapper.rb +57 -59
  46. data/lib/action_controller/metal/permissions_policy.rb +13 -12
  47. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  48. data/lib/action_controller/metal/redirecting.rb +108 -82
  49. data/lib/action_controller/metal/renderers.rb +50 -49
  50. data/lib/action_controller/metal/rendering.rb +103 -75
  51. data/lib/action_controller/metal/request_forgery_protection.rb +162 -133
  52. data/lib/action_controller/metal/rescue.rb +11 -9
  53. data/lib/action_controller/metal/streaming.rb +138 -136
  54. data/lib/action_controller/metal/strong_parameters.rb +483 -478
  55. data/lib/action_controller/metal/testing.rb +2 -0
  56. data/lib/action_controller/metal/url_for.rb +17 -15
  57. data/lib/action_controller/metal.rb +58 -57
  58. data/lib/action_controller/railtie.rb +3 -0
  59. data/lib/action_controller/railties/helpers.rb +2 -0
  60. data/lib/action_controller/renderer.rb +42 -36
  61. data/lib/action_controller/template_assertions.rb +4 -2
  62. data/lib/action_controller/test_case.rb +146 -126
  63. data/lib/action_controller.rb +5 -1
  64. data/lib/action_dispatch/constants.rb +2 -0
  65. data/lib/action_dispatch/deprecator.rb +2 -0
  66. data/lib/action_dispatch/http/cache.rb +27 -26
  67. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  68. data/lib/action_dispatch/http/content_security_policy.rb +48 -59
  69. data/lib/action_dispatch/http/filter_parameters.rb +13 -14
  70. data/lib/action_dispatch/http/filter_redirect.rb +15 -1
  71. data/lib/action_dispatch/http/headers.rb +22 -22
  72. data/lib/action_dispatch/http/mime_negotiation.rb +30 -41
  73. data/lib/action_dispatch/http/mime_type.rb +25 -21
  74. data/lib/action_dispatch/http/mime_types.rb +2 -0
  75. data/lib/action_dispatch/http/parameters.rb +11 -9
  76. data/lib/action_dispatch/http/permissions_policy.rb +26 -36
  77. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  78. data/lib/action_dispatch/http/request.rb +75 -95
  79. data/lib/action_dispatch/http/response.rb +61 -61
  80. data/lib/action_dispatch/http/upload.rb +18 -16
  81. data/lib/action_dispatch/http/url.rb +75 -73
  82. data/lib/action_dispatch/journey/formatter.rb +13 -6
  83. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  84. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  85. data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
  86. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  87. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  88. data/lib/action_dispatch/journey/parser.rb +4 -3
  89. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  90. data/lib/action_dispatch/journey/path/pattern.rb +4 -1
  91. data/lib/action_dispatch/journey/route.rb +9 -7
  92. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  93. data/lib/action_dispatch/journey/router.rb +4 -2
  94. data/lib/action_dispatch/journey/routes.rb +4 -2
  95. data/lib/action_dispatch/journey/scanner.rb +4 -2
  96. data/lib/action_dispatch/journey/visitors.rb +2 -0
  97. data/lib/action_dispatch/journey.rb +2 -0
  98. data/lib/action_dispatch/log_subscriber.rb +2 -0
  99. data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
  100. data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
  101. data/lib/action_dispatch/middleware/callbacks.rb +3 -1
  102. data/lib/action_dispatch/middleware/cookies.rb +119 -104
  103. data/lib/action_dispatch/middleware/debug_exceptions.rb +13 -5
  104. data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
  105. data/lib/action_dispatch/middleware/debug_view.rb +2 -0
  106. data/lib/action_dispatch/middleware/exception_wrapper.rb +6 -11
  107. data/lib/action_dispatch/middleware/executor.rb +2 -0
  108. data/lib/action_dispatch/middleware/flash.rb +63 -51
  109. data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
  110. data/lib/action_dispatch/middleware/public_exceptions.rb +8 -6
  111. data/lib/action_dispatch/middleware/reloader.rb +5 -3
  112. data/lib/action_dispatch/middleware/remote_ip.rb +77 -72
  113. data/lib/action_dispatch/middleware/request_id.rb +14 -9
  114. data/lib/action_dispatch/middleware/server_timing.rb +4 -2
  115. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
  116. data/lib/action_dispatch/middleware/session/cache_store.rb +13 -8
  117. data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
  118. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
  119. data/lib/action_dispatch/middleware/show_exceptions.rb +16 -16
  120. data/lib/action_dispatch/middleware/ssl.rb +43 -40
  121. data/lib/action_dispatch/middleware/stack.rb +11 -10
  122. data/lib/action_dispatch/middleware/static.rb +33 -31
  123. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +1 -1
  124. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
  125. data/lib/action_dispatch/railtie.rb +2 -3
  126. data/lib/action_dispatch/request/session.rb +23 -21
  127. data/lib/action_dispatch/request/utils.rb +2 -0
  128. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  129. data/lib/action_dispatch/routing/inspector.rb +6 -4
  130. data/lib/action_dispatch/routing/mapper.rb +623 -625
  131. data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
  132. data/lib/action_dispatch/routing/redirection.rb +37 -32
  133. data/lib/action_dispatch/routing/route_set.rb +60 -46
  134. data/lib/action_dispatch/routing/routes_proxy.rb +6 -4
  135. data/lib/action_dispatch/routing/url_for.rb +130 -125
  136. data/lib/action_dispatch/routing.rb +150 -148
  137. data/lib/action_dispatch/system_test_case.rb +91 -81
  138. data/lib/action_dispatch/system_testing/browser.rb +4 -2
  139. data/lib/action_dispatch/system_testing/driver.rb +2 -0
  140. data/lib/action_dispatch/system_testing/server.rb +2 -0
  141. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +32 -21
  142. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  143. data/lib/action_dispatch/testing/assertion_response.rb +8 -6
  144. data/lib/action_dispatch/testing/assertions/response.rb +26 -23
  145. data/lib/action_dispatch/testing/assertions/routing.rb +153 -84
  146. data/lib/action_dispatch/testing/assertions.rb +2 -0
  147. data/lib/action_dispatch/testing/integration.rb +223 -222
  148. data/lib/action_dispatch/testing/request_encoder.rb +2 -0
  149. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  150. data/lib/action_dispatch/testing/test_process.rb +12 -8
  151. data/lib/action_dispatch/testing/test_request.rb +3 -1
  152. data/lib/action_dispatch/testing/test_response.rb +27 -26
  153. data/lib/action_dispatch.rb +22 -32
  154. data/lib/action_pack/gem_version.rb +6 -4
  155. data/lib/action_pack/version.rb +3 -1
  156. data/lib/action_pack.rb +17 -16
  157. metadata +33 -16
@@ -1,32 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/object/deep_dup"
4
6
  require "active_support/core_ext/array/wrap"
5
7
 
6
8
  module ActionDispatch # :nodoc:
7
- # = Action Dispatch Content Security Policy
9
+ # # Action Dispatch Content Security Policy
8
10
  #
9
- # Configures the HTTP
10
- # {Content-Security-Policy}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy]
11
- # response header to help protect against XSS and injection attacks.
11
+ # Configures the HTTP [Content-Security-Policy]
12
+ # (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy)
13
+ # response header to help protect against XSS and
14
+ # injection attacks.
12
15
  #
13
16
  # Example global policy:
14
17
  #
15
- # Rails.application.config.content_security_policy do |policy|
16
- # policy.default_src :self, :https
17
- # policy.font_src :self, :https, :data
18
- # policy.img_src :self, :https, :data
19
- # policy.object_src :none
20
- # policy.script_src :self, :https
21
- # policy.style_src :self, :https
18
+ # Rails.application.config.content_security_policy do |policy|
19
+ # policy.default_src :self, :https
20
+ # policy.font_src :self, :https, :data
21
+ # policy.img_src :self, :https, :data
22
+ # policy.object_src :none
23
+ # policy.script_src :self, :https
24
+ # policy.style_src :self, :https
22
25
  #
23
- # # Specify URI for violation reports
24
- # policy.report_uri "/csp-violation-report-endpoint"
25
- # end
26
+ # # Specify URI for violation reports
27
+ # policy.report_uri "/csp-violation-report-endpoint"
28
+ # end
26
29
  class ContentSecurityPolicy
27
- class InvalidDirectiveError < StandardError
28
- end
29
-
30
30
  class Middleware
31
31
  def initialize(app)
32
32
  @app = app
@@ -35,8 +35,8 @@ module ActionDispatch # :nodoc:
35
35
  def call(env)
36
36
  status, headers, _ = response = @app.call(env)
37
37
 
38
- # Returning CSP headers with a 304 Not Modified is harmful, since nonces in the new
39
- # CSP headers might not match nonces in the cached HTML.
38
+ # Returning CSP headers with a 304 Not Modified is harmful, since nonces in the
39
+ # new CSP headers might not match nonces in the cached HTML.
40
40
  return response if status == 304
41
41
 
42
42
  return response if policy_present?(headers)
@@ -193,14 +193,14 @@ module ActionDispatch # :nodoc:
193
193
  end
194
194
  end
195
195
 
196
- # Specify whether to prevent the user agent from loading any assets over
197
- # HTTP when the page uses HTTPS:
196
+ # Specify whether to prevent the user agent from loading any assets over HTTP
197
+ # when the page uses HTTPS:
198
198
  #
199
- # policy.block_all_mixed_content
199
+ # policy.block_all_mixed_content
200
200
  #
201
- # Pass +false+ to allow it again:
201
+ # Pass `false` to allow it again:
202
202
  #
203
- # policy.block_all_mixed_content false
203
+ # policy.block_all_mixed_content false
204
204
  #
205
205
  def block_all_mixed_content(enabled = true)
206
206
  if enabled
@@ -212,11 +212,11 @@ module ActionDispatch # :nodoc:
212
212
 
213
213
  # Restricts the set of plugins that can be embedded:
214
214
  #
215
- # policy.plugin_types "application/x-shockwave-flash"
215
+ # policy.plugin_types "application/x-shockwave-flash"
216
216
  #
217
217
  # Leave empty to allow all plugins:
218
218
  #
219
- # policy.plugin_types
219
+ # policy.plugin_types
220
220
  #
221
221
  def plugin_types(*types)
222
222
  if types.first
@@ -226,23 +226,25 @@ module ActionDispatch # :nodoc:
226
226
  end
227
227
  end
228
228
 
229
- # Enable the {report-uri}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri]
230
- # directive. Violation reports will be sent to the specified URI:
229
+ # Enable the [report-uri]
230
+ # (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri)
231
+ # directive. Violation reports will be sent to the
232
+ # specified URI:
231
233
  #
232
- # policy.report_uri "/csp-violation-report-endpoint"
234
+ # policy.report_uri "/csp-violation-report-endpoint"
233
235
  #
234
236
  def report_uri(uri)
235
237
  @directives["report-uri"] = [uri]
236
238
  end
237
239
 
238
- # Specify asset types for which {Subresource Integrity}[https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity]
239
- # is required:
240
+ # Specify asset types for which [Subresource Integrity]
241
+ # (https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) is required:
240
242
  #
241
- # policy.require_sri_for :script, :style
243
+ # policy.require_sri_for :script, :style
242
244
  #
243
245
  # Leave empty to not require Subresource Integrity:
244
246
  #
245
- # policy.require_sri_for
247
+ # policy.require_sri_for
246
248
  #
247
249
  def require_sri_for(*types)
248
250
  if types.first
@@ -252,18 +254,19 @@ module ActionDispatch # :nodoc:
252
254
  end
253
255
  end
254
256
 
255
- # Specify whether a {sandbox}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox]
257
+ # Specify whether a [sandbox]
258
+ # (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox)
256
259
  # should be enabled for the requested resource:
257
260
  #
258
- # policy.sandbox
261
+ # policy.sandbox
259
262
  #
260
263
  # Values can be passed as arguments:
261
264
  #
262
- # policy.sandbox "allow-scripts", "allow-modals"
265
+ # policy.sandbox "allow-scripts", "allow-modals"
263
266
  #
264
- # Pass +false+ to disable the sandbox:
267
+ # Pass `false` to disable the sandbox:
265
268
  #
266
- # policy.sandbox false
269
+ # policy.sandbox false
267
270
  #
268
271
  def sandbox(*values)
269
272
  if values.empty?
@@ -277,11 +280,11 @@ module ActionDispatch # :nodoc:
277
280
 
278
281
  # Specify whether user agents should treat any assets over HTTP as HTTPS:
279
282
  #
280
- # policy.upgrade_insecure_requests
283
+ # policy.upgrade_insecure_requests
281
284
  #
282
- # Pass +false+ to disable it:
285
+ # Pass `false` to disable it:
283
286
  #
284
- # policy.upgrade_insecure_requests false
287
+ # policy.upgrade_insecure_requests false
285
288
  #
286
289
  def upgrade_insecure_requests(enabled = true)
287
290
  if enabled
@@ -320,9 +323,9 @@ module ActionDispatch # :nodoc:
320
323
  @directives.map do |directive, sources|
321
324
  if sources.is_a?(Array)
322
325
  if nonce && nonce_directive?(directive, nonce_directives)
323
- "#{directive} #{build_directive(directive, sources, context).join(' ')} 'nonce-#{nonce}'"
326
+ "#{directive} #{build_directive(sources, context).join(' ')} 'nonce-#{nonce}'"
324
327
  else
325
- "#{directive} #{build_directive(directive, sources, context).join(' ')}"
328
+ "#{directive} #{build_directive(sources, context).join(' ')}"
326
329
  end
327
330
  elsif sources
328
331
  directive
@@ -332,22 +335,8 @@ module ActionDispatch # :nodoc:
332
335
  end
333
336
  end
334
337
 
335
- def validate(directive, sources)
336
- sources.flatten.each do |source|
337
- if source.include?(";") || source != source.gsub(/[[:space:]]/, "")
338
- raise InvalidDirectiveError, <<~MSG.squish
339
- Invalid Content Security Policy #{directive}: "#{source}".
340
- Directive values must not contain whitespace or semicolons.
341
- Please use multiple arguments or other directive methods instead.
342
- MSG
343
- end
344
- end
345
- end
346
-
347
- def build_directive(directive, sources, context)
348
- resolved_sources = sources.map { |source| resolve_source(source, context) }
349
-
350
- validate(directive, resolved_sources)
338
+ def build_directive(sources, context)
339
+ sources.map { |source| resolve_source(source, context) }
351
340
  end
352
341
 
353
342
  def resolve_source(source, context)
@@ -1,18 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/parameter_filter"
4
6
 
5
7
  module ActionDispatch
6
8
  module Http
7
- # = Action Dispatch HTTP Filter Parameters
9
+ # # Action Dispatch HTTP Filter Parameters
8
10
  #
9
11
  # Allows you to specify sensitive query string and POST parameters to filter
10
12
  # from the request log.
11
13
  #
12
- # # Replaces values with "[FILTERED]" for keys that match /foo|bar/i.
13
- # env["action_dispatch.parameter_filter"] = [:foo, "bar"]
14
+ # # Replaces values with "[FILTERED]" for keys that match /foo|bar/i.
15
+ # env["action_dispatch.parameter_filter"] = [:foo, "bar"]
14
16
  #
15
- # For more information about filter behavior, see ActiveSupport::ParameterFilter.
17
+ # For more information about filter behavior, see
18
+ # ActiveSupport::ParameterFilter.
16
19
  module FilterParameters
17
20
  ENV_MATCH = [/RAW_POST_DATA/, "rack.request.form_vars"] # :nodoc:
18
21
  NULL_PARAM_FILTER = ActiveSupport::ParameterFilter.new # :nodoc:
@@ -43,7 +46,8 @@ module ActionDispatch
43
46
  @filtered_path ||= query_string.empty? ? path : "#{path}?#{filtered_query_string}"
44
47
  end
45
48
 
46
- # Returns the +ActiveSupport::ParameterFilter+ object used to filter in this request.
49
+ # Returns the `ActiveSupport::ParameterFilter` object used to filter in this
50
+ # request.
47
51
  def parameter_filter
48
52
  @parameter_filter ||= if has_header?("action_dispatch.parameter_filter")
49
53
  parameter_filter_for get_header("action_dispatch.parameter_filter")
@@ -64,17 +68,12 @@ module ActionDispatch
64
68
  ActiveSupport::ParameterFilter.new(filters)
65
69
  end
66
70
 
71
+ KV_RE = "[^&;=]+"
72
+ PAIR_RE = %r{(#{KV_RE})=(#{KV_RE})}
67
73
  def filtered_query_string # :doc:
68
- parts = query_string.split(/([&;])/)
69
- filtered_parts = parts.map do |part|
70
- if part.include?("=")
71
- key, value = part.split("=", 2)
72
- parameter_filter.filter(key => value).first.join("=")
73
- else
74
- part
75
- end
74
+ query_string.gsub(PAIR_RE) do |_|
75
+ parameter_filter.filter($1 => $2).first.join("=")
76
76
  end
77
- filtered_parts.join("")
78
77
  end
79
78
  end
80
79
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module Http
5
7
  module FilterRedirect
@@ -9,7 +11,7 @@ module ActionDispatch
9
11
  if location_filter_match?
10
12
  FILTERED
11
13
  else
12
- location
14
+ parameter_filtered_location
13
15
  end
14
16
  end
15
17
 
@@ -31,6 +33,18 @@ module ActionDispatch
31
33
  end
32
34
  end
33
35
  end
36
+
37
+ def parameter_filtered_location
38
+ uri = URI.parse(location)
39
+ unless uri.query.nil? || uri.query.empty?
40
+ uri.query.gsub!(FilterParameters::PAIR_RE) do
41
+ request.parameter_filter.filter($1 => $2).first.join("=")
42
+ end
43
+ end
44
+ uri.to_s
45
+ rescue URI::Error
46
+ FILTERED
47
+ end
34
48
  end
35
49
  end
36
50
  end
@@ -1,28 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module Http
5
- # = Action Dispatch HTTP \Headers
7
+ # # Action Dispatch HTTP Headers
6
8
  #
7
9
  # Provides access to the request's HTTP headers from the environment.
8
10
  #
9
- # env = { "CONTENT_TYPE" => "text/plain", "HTTP_USER_AGENT" => "curl/7.43.0" }
10
- # headers = ActionDispatch::Http::Headers.from_hash(env)
11
- # headers["Content-Type"] # => "text/plain"
12
- # headers["User-Agent"] # => "curl/7.43.0"
11
+ # env = { "CONTENT_TYPE" => "text/plain", "HTTP_USER_AGENT" => "curl/7.43.0" }
12
+ # headers = ActionDispatch::Http::Headers.from_hash(env)
13
+ # headers["Content-Type"] # => "text/plain"
14
+ # headers["User-Agent"] # => "curl/7.43.0"
13
15
  #
14
16
  # Also note that when headers are mapped to CGI-like variables by the Rack
15
17
  # server, both dashes and underscores are converted to underscores. This
16
18
  # ambiguity cannot be resolved at this stage anymore. Both underscores and
17
19
  # dashes have to be interpreted as if they were originally sent as dashes.
18
20
  #
19
- # # GET / HTTP/1.1
20
- # # ...
21
- # # User-Agent: curl/7.43.0
22
- # # X_Custom_Header: token
21
+ # # GET / HTTP/1.1
22
+ # # ...
23
+ # # User-Agent: curl/7.43.0
24
+ # # X_Custom_Header: token
23
25
  #
24
- # headers["X_Custom_Header"] # => nil
25
- # headers["X-Custom-Header"] # => "token"
26
+ # headers["X_Custom_Header"] # => nil
27
+ # headers["X-Custom-Header"] # => "token"
26
28
  class Headers
27
29
  CGI_VARIABLES = Set.new(%W[
28
30
  AUTH_TYPE
@@ -67,7 +69,7 @@ module ActionDispatch
67
69
  @req.set_header env_name(key), value
68
70
  end
69
71
 
70
- # Add a value to a multivalued header like +Vary+ or +Accept-Encoding+.
72
+ # Add a value to a multivalued header like `Vary` or `Accept-Encoding`.
71
73
  def add(key, value)
72
74
  @req.add_header env_name(key), value
73
75
  end
@@ -81,11 +83,10 @@ module ActionDispatch
81
83
 
82
84
  # Returns the value for the given key mapped to @env.
83
85
  #
84
- # If the key is not found and an optional code block is not provided,
85
- # raises a <tt>KeyError</tt> exception.
86
+ # If the key is not found and an optional code block is not provided, raises a
87
+ # `KeyError` exception.
86
88
  #
87
- # If the code block is provided, then it will be run and
88
- # its result returned.
89
+ # If the code block is provided, then it will be run and its result returned.
89
90
  def fetch(key, default = DEFAULT)
90
91
  @req.fetch_header(env_name(key)) do
91
92
  return default unless default == DEFAULT
@@ -99,16 +100,15 @@ module ActionDispatch
99
100
  end
100
101
 
101
102
  # Returns a new Http::Headers instance containing the contents of
102
- # <tt>headers_or_env</tt> and the original instance.
103
+ # `headers_or_env` and the original instance.
103
104
  def merge(headers_or_env)
104
105
  headers = @req.dup.headers
105
106
  headers.merge!(headers_or_env)
106
107
  headers
107
108
  end
108
109
 
109
- # Adds the contents of <tt>headers_or_env</tt> to original instance
110
- # entries; duplicate keys are overwritten with the values from
111
- # <tt>headers_or_env</tt>.
110
+ # Adds the contents of `headers_or_env` to original instance entries; duplicate
111
+ # keys are overwritten with the values from `headers_or_env`.
112
112
  def merge!(headers_or_env)
113
113
  headers_or_env.each do |key, value|
114
114
  @req.set_header env_name(key), value
@@ -118,8 +118,8 @@ module ActionDispatch
118
118
  def env; @req.env.dup; end
119
119
 
120
120
  private
121
- # Converts an HTTP header name to an environment variable name if it is
122
- # not contained within the headers hash.
121
+ # Converts an HTTP header name to an environment variable name if it is not
122
+ # contained within the headers hash.
123
123
  def env_name(key)
124
124
  key = key.to_s
125
125
  if HTTP_HEADER.match?(key)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/module/attribute_accessors"
4
6
 
5
7
  module ActionDispatch
@@ -16,23 +18,9 @@ module ActionDispatch
16
18
 
17
19
  included do
18
20
  mattr_accessor :ignore_accept_header, default: false
19
-
20
- def return_only_media_type_on_content_type=(value)
21
- ActionDispatch.deprecator.warn(
22
- "`config.action_dispatch.return_only_request_media_type_on_content_type` is deprecated and will" \
23
- " be removed in Rails 7.2."
24
- )
25
- end
26
-
27
- def return_only_media_type_on_content_type
28
- ActionDispatch.deprecator.warn(
29
- "`config.action_dispatch.return_only_request_media_type_on_content_type` is deprecated and will" \
30
- " be removed in Rails 7.2."
31
- )
32
- end
33
21
  end
34
22
 
35
- # The MIME type of the HTTP request, such as Mime[:xml].
23
+ # The MIME type of the HTTP request, such as [Mime](:xml).
36
24
  def content_mime_type
37
25
  fetch_header("action_dispatch.request.content_type") do |k|
38
26
  v = if get_header("CONTENT_TYPE") =~ /^([^,;]*)/
@@ -66,11 +54,11 @@ module ActionDispatch
66
54
  end
67
55
  end
68
56
 
69
- # Returns the MIME type for the \format used in the request.
57
+ # Returns the MIME type for the format used in the request.
70
58
  #
71
- # GET /posts/5.xml | request.format => Mime[:xml]
72
- # GET /posts/5.xhtml | request.format => Mime[:html]
73
- # GET /posts/5 | request.format => Mime[:html] or Mime[:js], or request.accepts.first
59
+ # GET /posts/5.xml | request.format => Mime[:xml]
60
+ # GET /posts/5.xhtml | request.format => Mime[:html]
61
+ # GET /posts/5 | request.format => Mime[:html] or Mime[:js], or request.accepts.first
74
62
  #
75
63
  def format(_view_path = nil)
76
64
  formats.first || Mime::NullType.instance
@@ -98,7 +86,7 @@ module ActionDispatch
98
86
  end
99
87
  end
100
88
 
101
- # Sets the \variant for template.
89
+ # Sets the variant for template.
102
90
  def variant=(variant)
103
91
  variant = Array(variant)
104
92
 
@@ -113,36 +101,37 @@ module ActionDispatch
113
101
  @variant ||= ActiveSupport::ArrayInquirer.new
114
102
  end
115
103
 
116
- # Sets the \format by string extension, which can be used to force custom formats
104
+ # Sets the format by string extension, which can be used to force custom formats
117
105
  # that are not controlled by the extension.
118
106
  #
119
- # class ApplicationController < ActionController::Base
120
- # before_action :adjust_format_for_iphone
107
+ # class ApplicationController < ActionController::Base
108
+ # before_action :adjust_format_for_iphone
121
109
  #
122
- # private
123
- # def adjust_format_for_iphone
124
- # request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
125
- # end
126
- # end
110
+ # private
111
+ # def adjust_format_for_iphone
112
+ # request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
113
+ # end
114
+ # end
127
115
  def format=(extension)
128
116
  parameters[:format] = extension.to_s
129
117
  set_header "action_dispatch.request.formats", [Mime::Type.lookup_by_extension(parameters[:format])]
130
118
  end
131
119
 
132
- # Sets the \formats by string extensions. This differs from #format= by allowing you
133
- # to set multiple, ordered formats, which is useful when you want to have a fallback.
120
+ # Sets the formats by string extensions. This differs from #format= by allowing
121
+ # you to set multiple, ordered formats, which is useful when you want to have a
122
+ # fallback.
134
123
  #
135
- # In this example, the +:iphone+ format will be used if it's available, otherwise it'll fall back
136
- # to the +:html+ format.
124
+ # In this example, the `:iphone` format will be used if it's available,
125
+ # otherwise it'll fall back to the `:html` format.
137
126
  #
138
- # class ApplicationController < ActionController::Base
139
- # before_action :adjust_format_for_iphone_with_html_fallback
127
+ # class ApplicationController < ActionController::Base
128
+ # before_action :adjust_format_for_iphone_with_html_fallback
140
129
  #
141
- # private
142
- # def adjust_format_for_iphone_with_html_fallback
143
- # request.formats = [ :iphone, :html ] if request.env["HTTP_USER_AGENT"][/iPhone/]
144
- # end
145
- # end
130
+ # private
131
+ # def adjust_format_for_iphone_with_html_fallback
132
+ # request.formats = [ :iphone, :html ] if request.env["HTTP_USER_AGENT"][/iPhone/]
133
+ # end
134
+ # end
146
135
  def formats=(extensions)
147
136
  parameters[:format] = extensions.first.to_s
148
137
  set_header "action_dispatch.request.formats", extensions.collect { |extension|
@@ -168,8 +157,8 @@ module ActionDispatch
168
157
  end
169
158
 
170
159
  private
171
- # We use normal content negotiation unless you include */* in your list,
172
- # in which case we assume you're a browser and send HTML.
160
+ # We use normal content negotiation unless you include **/** in your list, in
161
+ # which case we assume you're a browser and send HTML.
173
162
  BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
174
163
 
175
164
  def params_readable?
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "singleton"
4
6
 
5
7
  module Mime
@@ -65,19 +67,20 @@ module Mime
65
67
  end
66
68
  end
67
69
 
68
- # Encapsulates the notion of a MIME type. Can be used at render time, for example, with:
70
+ # Encapsulates the notion of a MIME type. Can be used at render time, for
71
+ # example, with:
69
72
  #
70
- # class PostsController < ActionController::Base
71
- # def show
72
- # @post = Post.find(params[:id])
73
+ # class PostsController < ActionController::Base
74
+ # def show
75
+ # @post = Post.find(params[:id])
73
76
  #
74
- # respond_to do |format|
75
- # format.html
76
- # format.ics { render body: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar") }
77
- # format.xml { render xml: @post }
77
+ # respond_to do |format|
78
+ # format.html
79
+ # format.ics { render body: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar") }
80
+ # format.xml { render xml: @post }
81
+ # end
78
82
  # end
79
83
  # end
80
- # end
81
84
  class Type
82
85
  attr_reader :symbol
83
86
 
@@ -173,8 +176,9 @@ module Mime
173
176
  EXTENSION_LOOKUP[extension.to_s]
174
177
  end
175
178
 
176
- # Registers an alias that's not used on MIME type lookup, but can be referenced directly. Especially useful for
177
- # rendering different HTML versions depending on the user agent, like an iPhone.
179
+ # Registers an alias that's not used on MIME type lookup, but can be referenced
180
+ # directly. Especially useful for rendering different HTML versions depending on
181
+ # the user agent, like an iPhone.
178
182
  def register_alias(string, symbol, extension_synonyms = [])
179
183
  register(string, symbol, [], extension_synonyms, true)
180
184
  end
@@ -224,11 +228,11 @@ module Mime
224
228
  parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP
225
229
  end
226
230
 
227
- # For an input of <tt>'text'</tt>, returns <tt>[Mime[:json], Mime[:xml], Mime[:ics],
228
- # Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]]</tt>.
231
+ # For an input of `'text'`, returns `[Mime[:json], Mime[:xml], Mime[:ics],
232
+ # Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]]`.
229
233
  #
230
- # For an input of <tt>'application'</tt>, returns <tt>[Mime[:html], Mime[:js],
231
- # Mime[:xml], Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]]</tt>.
234
+ # For an input of `'application'`, returns `[Mime[:html], Mime[:js], Mime[:xml],
235
+ # Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]]`.
232
236
  def parse_data_with_trailing_star(type)
233
237
  Mime::SET.select { |m| m.match?(type) }
234
238
  end
@@ -237,7 +241,7 @@ module Mime
237
241
  #
238
242
  # To unregister a MIME type:
239
243
  #
240
- # Mime::Type.unregister(:mobile)
244
+ # Mime::Type.unregister(:mobile)
241
245
  def unregister(symbol)
242
246
  symbol = symbol.downcase
243
247
  if mime = Mime[symbol]
@@ -329,7 +333,7 @@ module Mime
329
333
  def to_ary; end
330
334
  def to_a; end
331
335
 
332
- def method_missing(method, *args)
336
+ def method_missing(method, ...)
333
337
  if method.end_with?("?")
334
338
  method[0..-2].downcase.to_sym == to_sym
335
339
  else
@@ -353,9 +357,9 @@ module Mime
353
357
  def html?; true; end
354
358
  end
355
359
 
356
- # ALL isn't a real MIME type, so we don't register it for lookup with the
357
- # other concrete types. It's a wildcard match that we use for +respond_to+
358
- # negotiation internals.
360
+ # ALL isn't a real MIME type, so we don't register it for lookup with the other
361
+ # concrete types. It's a wildcard match that we use for `respond_to` negotiation
362
+ # internals.
359
363
  ALL = AllType.instance
360
364
 
361
365
  class NullType
@@ -376,7 +380,7 @@ module Mime
376
380
  method.end_with?("?")
377
381
  end
378
382
 
379
- def method_missing(method, *args)
383
+ def method_missing(method, ...)
380
384
  false if method.end_with?("?")
381
385
  end
382
386
  end
@@ -3,6 +3,8 @@
3
3
  # Build list of Mime types for HTTP responses
4
4
  # https://www.iana.org/assignments/media-types/
5
5
 
6
+ # :markup: markdown
7
+
6
8
  Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
7
9
  Mime::Type.register "text/plain", :text, [], %w(txt)
8
10
  Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript )