actionpack 7.1.3 → 7.2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -501
  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 +15 -7
  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 +198 -126
  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 +123 -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 +210 -205
  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 +525 -480
  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 +86 -60
  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 +10 -3
  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 +44 -38
  69. data/lib/action_dispatch/http/filter_parameters.rb +18 -9
  70. data/lib/action_dispatch/http/filter_redirect.rb +22 -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 +31 -24
  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 +20 -44
  77. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  78. data/lib/action_dispatch/http/request.rb +94 -75
  79. data/lib/action_dispatch/http/response.rb +73 -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 +8 -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 +31 -21
  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/rescues/missing_exact_template.html.erb +1 -1
  125. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
  126. data/lib/action_dispatch/railtie.rb +2 -4
  127. data/lib/action_dispatch/request/session.rb +23 -21
  128. data/lib/action_dispatch/request/utils.rb +2 -0
  129. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  130. data/lib/action_dispatch/routing/inspector.rb +5 -3
  131. data/lib/action_dispatch/routing/mapper.rb +671 -636
  132. data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
  133. data/lib/action_dispatch/routing/redirection.rb +37 -32
  134. data/lib/action_dispatch/routing/route_set.rb +59 -45
  135. data/lib/action_dispatch/routing/routes_proxy.rb +6 -4
  136. data/lib/action_dispatch/routing/url_for.rb +130 -125
  137. data/lib/action_dispatch/routing.rb +150 -148
  138. data/lib/action_dispatch/system_test_case.rb +91 -81
  139. data/lib/action_dispatch/system_testing/browser.rb +10 -3
  140. data/lib/action_dispatch/system_testing/driver.rb +3 -1
  141. data/lib/action_dispatch/system_testing/server.rb +2 -0
  142. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +32 -21
  143. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  144. data/lib/action_dispatch/testing/assertion_response.rb +8 -6
  145. data/lib/action_dispatch/testing/assertions/response.rb +26 -23
  146. data/lib/action_dispatch/testing/assertions/routing.rb +153 -84
  147. data/lib/action_dispatch/testing/assertions.rb +2 -0
  148. data/lib/action_dispatch/testing/integration.rb +223 -222
  149. data/lib/action_dispatch/testing/request_encoder.rb +2 -0
  150. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  151. data/lib/action_dispatch/testing/test_process.rb +12 -8
  152. data/lib/action_dispatch/testing/test_request.rb +3 -1
  153. data/lib/action_dispatch/testing/test_response.rb +27 -26
  154. data/lib/action_dispatch.rb +22 -28
  155. data/lib/action_pack/gem_version.rb +6 -4
  156. data/lib/action_pack/version.rb +3 -1
  157. data/lib/action_pack.rb +17 -16
  158. metadata +39 -16
@@ -1,28 +1,31 @@
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
30
  class Middleware
28
31
  def initialize(app)
@@ -32,8 +35,8 @@ module ActionDispatch # :nodoc:
32
35
  def call(env)
33
36
  status, headers, _ = response = @app.call(env)
34
37
 
35
- # Returning CSP headers with a 304 Not Modified is harmful, since nonces in the new
36
- # 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.
37
40
  return response if status == 304
38
41
 
39
42
  return response if policy_present?(headers)
@@ -190,14 +193,14 @@ module ActionDispatch # :nodoc:
190
193
  end
191
194
  end
192
195
 
193
- # Specify whether to prevent the user agent from loading any assets over
194
- # 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:
195
198
  #
196
- # policy.block_all_mixed_content
199
+ # policy.block_all_mixed_content
197
200
  #
198
- # Pass +false+ to allow it again:
201
+ # Pass `false` to allow it again:
199
202
  #
200
- # policy.block_all_mixed_content false
203
+ # policy.block_all_mixed_content false
201
204
  #
202
205
  def block_all_mixed_content(enabled = true)
203
206
  if enabled
@@ -209,11 +212,11 @@ module ActionDispatch # :nodoc:
209
212
 
210
213
  # Restricts the set of plugins that can be embedded:
211
214
  #
212
- # policy.plugin_types "application/x-shockwave-flash"
215
+ # policy.plugin_types "application/x-shockwave-flash"
213
216
  #
214
217
  # Leave empty to allow all plugins:
215
218
  #
216
- # policy.plugin_types
219
+ # policy.plugin_types
217
220
  #
218
221
  def plugin_types(*types)
219
222
  if types.first
@@ -223,23 +226,25 @@ module ActionDispatch # :nodoc:
223
226
  end
224
227
  end
225
228
 
226
- # Enable the {report-uri}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri]
227
- # 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:
228
233
  #
229
- # policy.report_uri "/csp-violation-report-endpoint"
234
+ # policy.report_uri "/csp-violation-report-endpoint"
230
235
  #
231
236
  def report_uri(uri)
232
237
  @directives["report-uri"] = [uri]
233
238
  end
234
239
 
235
- # Specify asset types for which {Subresource Integrity}[https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity]
236
- # is required:
240
+ # Specify asset types for which [Subresource Integrity]
241
+ # (https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) is required:
237
242
  #
238
- # policy.require_sri_for :script, :style
243
+ # policy.require_sri_for :script, :style
239
244
  #
240
245
  # Leave empty to not require Subresource Integrity:
241
246
  #
242
- # policy.require_sri_for
247
+ # policy.require_sri_for
243
248
  #
244
249
  def require_sri_for(*types)
245
250
  if types.first
@@ -249,18 +254,19 @@ module ActionDispatch # :nodoc:
249
254
  end
250
255
  end
251
256
 
252
- # 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)
253
259
  # should be enabled for the requested resource:
254
260
  #
255
- # policy.sandbox
261
+ # policy.sandbox
256
262
  #
257
263
  # Values can be passed as arguments:
258
264
  #
259
- # policy.sandbox "allow-scripts", "allow-modals"
265
+ # policy.sandbox "allow-scripts", "allow-modals"
260
266
  #
261
- # Pass +false+ to disable the sandbox:
267
+ # Pass `false` to disable the sandbox:
262
268
  #
263
- # policy.sandbox false
269
+ # policy.sandbox false
264
270
  #
265
271
  def sandbox(*values)
266
272
  if values.empty?
@@ -274,11 +280,11 @@ module ActionDispatch # :nodoc:
274
280
 
275
281
  # Specify whether user agents should treat any assets over HTTP as HTTPS:
276
282
  #
277
- # policy.upgrade_insecure_requests
283
+ # policy.upgrade_insecure_requests
278
284
  #
279
- # Pass +false+ to disable it:
285
+ # Pass `false` to disable it:
280
286
  #
281
- # policy.upgrade_insecure_requests false
287
+ # policy.upgrade_insecure_requests false
282
288
  #
283
289
  def upgrade_insecure_requests(enabled = true)
284
290
  if enabled
@@ -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,12 +68,17 @@ module ActionDispatch
64
68
  ActiveSupport::ParameterFilter.new(filters)
65
69
  end
66
70
 
67
- KV_RE = "[^&;=]+"
68
- PAIR_RE = %r{(#{KV_RE})=(#{KV_RE})}
69
71
  def filtered_query_string # :doc:
70
- query_string.gsub(PAIR_RE) do |_|
71
- parameter_filter.filter($1 => $2).first.join("=")
72
+ parts = query_string.split(/([&;])/)
73
+ filtered_parts = parts.map do |part|
74
+ if part.include?("=")
75
+ key, value = part.split("=", 2)
76
+ parameter_filter.filter(key => value).first.join("=")
77
+ else
78
+ part
79
+ end
72
80
  end
81
+ filtered_parts.join("")
73
82
  end
74
83
  end
75
84
  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,25 @@ 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
+ parts = uri.query.split(/([&;])/)
41
+ filtered_parts = parts.map do |part|
42
+ if part.include?("=")
43
+ key, value = part.split("=", 2)
44
+ request.parameter_filter.filter(key => value).first.join("=")
45
+ else
46
+ part
47
+ end
48
+ end
49
+ uri.query = filtered_parts.join("")
50
+ end
51
+ uri.to_s
52
+ rescue URI::Error
53
+ FILTERED
54
+ end
34
55
  end
35
56
  end
36
57
  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
 
@@ -154,7 +157,7 @@ module Mime
154
157
  TRAILING_STAR_REGEXP = /^(text|application)\/\*/
155
158
  # all media-type parameters need to be before the q-parameter
156
159
  # https://www.rfc-editor.org/rfc/rfc7231#section-5.3.2
157
- PARAMETER_SEPARATOR_REGEXP = /\s*;\s*q="?/
160
+ PARAMETER_SEPARATOR_REGEXP = /;\s*q="?/
158
161
  ACCEPT_HEADER_REGEXP = /[^,\s"](?:[^,"]|"[^"]*")*/
159
162
 
160
163
  def register_callback(&block)
@@ -162,16 +165,20 @@ module Mime
162
165
  end
163
166
 
164
167
  def lookup(string)
168
+ return LOOKUP[string] if LOOKUP.key?(string)
169
+
165
170
  # fallback to the media-type without parameters if it was not found
166
- LOOKUP[string] || LOOKUP[string.split(";", 2)[0]&.rstrip] || Type.new(string)
171
+ string = string.split(";", 2)[0]&.rstrip
172
+ LOOKUP[string] || Type.new(string)
167
173
  end
168
174
 
169
175
  def lookup_by_extension(extension)
170
176
  EXTENSION_LOOKUP[extension.to_s]
171
177
  end
172
178
 
173
- # Registers an alias that's not used on MIME type lookup, but can be referenced directly. Especially useful for
174
- # 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.
175
182
  def register_alias(string, symbol, extension_synonyms = [])
176
183
  register(string, symbol, [], extension_synonyms, true)
177
184
  end
@@ -193,7 +200,7 @@ module Mime
193
200
  def parse(accept_header)
194
201
  if !accept_header.include?(",")
195
202
  if (index = accept_header.index(PARAMETER_SEPARATOR_REGEXP))
196
- accept_header = accept_header[0, index]
203
+ accept_header = accept_header[0, index].strip
197
204
  end
198
205
  return [] if accept_header.blank?
199
206
  parse_trailing_star(accept_header) || Array(Mime::Type.lookup(accept_header))
@@ -221,11 +228,11 @@ module Mime
221
228
  parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP
222
229
  end
223
230
 
224
- # For an input of <tt>'text'</tt>, returns <tt>[Mime[:json], Mime[:xml], Mime[:ics],
225
- # 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]]`.
226
233
  #
227
- # For an input of <tt>'application'</tt>, returns <tt>[Mime[:html], Mime[:js],
228
- # 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]]`.
229
236
  def parse_data_with_trailing_star(type)
230
237
  Mime::SET.select { |m| m.match?(type) }
231
238
  end
@@ -234,7 +241,7 @@ module Mime
234
241
  #
235
242
  # To unregister a MIME type:
236
243
  #
237
- # Mime::Type.unregister(:mobile)
244
+ # Mime::Type.unregister(:mobile)
238
245
  def unregister(symbol)
239
246
  symbol = symbol.downcase
240
247
  if mime = Mime[symbol]
@@ -326,7 +333,7 @@ module Mime
326
333
  def to_ary; end
327
334
  def to_a; end
328
335
 
329
- def method_missing(method, *args)
336
+ def method_missing(method, ...)
330
337
  if method.end_with?("?")
331
338
  method[0..-2].downcase.to_sym == to_sym
332
339
  else
@@ -350,9 +357,9 @@ module Mime
350
357
  def html?; true; end
351
358
  end
352
359
 
353
- # ALL isn't a real MIME type, so we don't register it for lookup with the
354
- # other concrete types. It's a wildcard match that we use for +respond_to+
355
- # 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.
356
363
  ALL = AllType.instance
357
364
 
358
365
  class NullType
@@ -373,7 +380,7 @@ module Mime
373
380
  method.end_with?("?")
374
381
  end
375
382
 
376
- def method_missing(method, *args)
383
+ def method_missing(method, ...)
377
384
  false if method.end_with?("?")
378
385
  end
379
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 )