actionpack 7.1.3.4 → 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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -541
  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 +11 -10
  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 +209 -201
  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 +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 +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 +9 -5
  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 +29 -22
  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 +27 -37
  77. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  78. data/lib/action_dispatch/http/request.rb +71 -71
  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 +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 +670 -635
  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 +30 -13
@@ -1,28 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController
4
- # = Action Controller \Caching
6
+ # # Action Controller Caching
5
7
  #
6
- # \Caching is a cheap way of speeding up slow applications by keeping the result of
7
- # calculations, renderings, and database calls around for subsequent requests.
8
+ # Caching is a cheap way of speeding up slow applications by keeping the result
9
+ # of calculations, renderings, and database calls around for subsequent
10
+ # requests.
8
11
  #
9
12
  # You can read more about each approach by clicking the modules below.
10
13
  #
11
14
  # Note: To turn off all caching provided by Action Controller, set
12
- # config.action_controller.perform_caching = false
15
+ # config.action_controller.perform_caching = false
13
16
  #
14
- # == \Caching stores
17
+ # ## Caching stores
15
18
  #
16
- # All the caching stores from ActiveSupport::Cache are available to be used as backends
17
- # for Action Controller caching.
19
+ # All the caching stores from ActiveSupport::Cache are available to be used as
20
+ # backends for Action Controller caching.
18
21
  #
19
22
  # Configuration examples (FileStore is the default):
20
23
  #
21
- # config.action_controller.cache_store = :memory_store
22
- # config.action_controller.cache_store = :file_store, '/path/to/cache/directory'
23
- # config.action_controller.cache_store = :mem_cache_store, 'localhost'
24
- # config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new('localhost:11211')
25
- # config.action_controller.cache_store = MyOwnStore.new('parameter')
24
+ # config.action_controller.cache_store = :memory_store
25
+ # config.action_controller.cache_store = :file_store, '/path/to/cache/directory'
26
+ # config.action_controller.cache_store = :mem_cache_store, 'localhost'
27
+ # config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new('localhost:11211')
28
+ # config.action_controller.cache_store = MyOwnStore.new('parameter')
26
29
  module Caching
27
30
  extend ActiveSupport::Concern
28
31
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController
4
6
  def self.deprecator # :nodoc:
5
7
  AbstractController.deprecator
@@ -1,31 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController
4
- # = Action Controller Form Builder
6
+ # # Action Controller Form Builder
5
7
  #
6
- # Override the default form builder for all views rendered by this
7
- # controller and any of its descendants. Accepts a subclass of
8
+ # Override the default form builder for all views rendered by this controller
9
+ # and any of its descendants. Accepts a subclass of
8
10
  # ActionView::Helpers::FormBuilder.
9
11
  #
10
12
  # For example, given a form builder:
11
13
  #
12
- # class AdminFormBuilder < ActionView::Helpers::FormBuilder
13
- # def special_field(name)
14
+ # class AdminFormBuilder < ActionView::Helpers::FormBuilder
15
+ # def special_field(name)
16
+ # end
14
17
  # end
15
- # end
16
18
  #
17
19
  # The controller specifies a form builder as its default:
18
20
  #
19
- # class AdminAreaController < ApplicationController
20
- # default_form_builder AdminFormBuilder
21
- # end
21
+ # class AdminAreaController < ApplicationController
22
+ # default_form_builder AdminFormBuilder
23
+ # end
22
24
  #
23
- # Then in the view any form using +form_for+ will be an instance of the
25
+ # Then in the view any form using `form_for` will be an instance of the
24
26
  # specified form builder:
25
27
  #
26
- # <%= form_for(@instance) do |builder| %>
27
- # <%= builder.special_field(:name) %>
28
- # <% end %>
28
+ # <%= form_for(@instance) do |builder| %>
29
+ # <%= builder.special_field(:name) %>
30
+ # <% end %>
29
31
  module FormBuilder
30
32
  extend ActiveSupport::Concern
31
33
 
@@ -34,11 +36,12 @@ module ActionController
34
36
  end
35
37
 
36
38
  module ClassMethods
37
- # Set the form builder to be used as the default for all forms
38
- # in the views rendered by this controller and its subclasses.
39
+ # Set the form builder to be used as the default for all forms in the views
40
+ # rendered by this controller and its subclasses.
39
41
  #
40
- # ==== Parameters
41
- # * <tt>builder</tt> - Default form builder, an instance of ActionView::Helpers::FormBuilder
42
+ # #### Parameters
43
+ # * `builder` - Default form builder, an instance of
44
+ # ActionView::Helpers::FormBuilder
42
45
  def default_form_builder(builder)
43
46
  self._default_form_builder = builder
44
47
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController
4
6
  class LogSubscriber < ActiveSupport::LogSubscriber
5
7
  INTERNAL_PARAMS = %w(controller action format _method only_path)
@@ -31,7 +33,7 @@ module ActionController
31
33
  status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
32
34
  end
33
35
 
34
- additions << "Allocations: #{event.allocations}"
36
+ additions << "GC: #{event.gc_time.round(1)}ms"
35
37
 
36
38
  message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms" \
37
39
  " (#{additions.join(" | ")})"
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module ActionController # :nodoc:
6
+ module AllowBrowser
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ # Specify the browser versions that will be allowed to access all actions (or
11
+ # some, as limited by `only:` or `except:`). Only browsers matched in the hash
12
+ # or named set passed to `versions:` will be blocked if they're below the
13
+ # versions specified. This means that all other browsers, as well as agents that
14
+ # aren't reporting a user-agent header, will be allowed access.
15
+ #
16
+ # A browser that's blocked will by default be served the file in
17
+ # public/406-unsupported-browser.html with a HTTP status code of "406 Not
18
+ # Acceptable".
19
+ #
20
+ # In addition to specifically named browser versions, you can also pass
21
+ # `:modern` as the set to restrict support to browsers natively supporting webp
22
+ # images, web push, badges, import maps, CSS nesting, and CSS :has. This
23
+ # includes Safari 17.2+, Chrome 120+, Firefox 121+, Opera 106+.
24
+ #
25
+ # You can use https://caniuse.com to check for browser versions supporting the
26
+ # features you use.
27
+ #
28
+ # You can use `ActiveSupport::Notifications` to subscribe to events of browsers
29
+ # being blocked using the `browser_block.action_controller` event name.
30
+ #
31
+ # Examples:
32
+ #
33
+ # class ApplicationController < ActionController::Base
34
+ # # Allow only browsers natively supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has
35
+ # allow_browser versions: :modern
36
+ # end
37
+ #
38
+ # class ApplicationController < ActionController::Base
39
+ # # All versions of Chrome and Opera will be allowed, but no versions of "internet explorer" (ie). Safari needs to be 16.4+ and Firefox 121+.
40
+ # allow_browser versions: { safari: 16.4, firefox: 121, ie: false }
41
+ # end
42
+ #
43
+ # class MessagesController < ApplicationController
44
+ # # In addition to the browsers blocked by ApplicationController, also block Opera below 104 and Chrome below 119 for the show action.
45
+ # allow_browser versions: { opera: 104, chrome: 119 }, only: :show
46
+ # end
47
+ def allow_browser(versions:, block: -> { render file: Rails.root.join("public/406-unsupported-browser.html"), layout: false, status: :not_acceptable }, **options)
48
+ before_action -> { allow_browser(versions: versions, block: block) }, **options
49
+ end
50
+ end
51
+
52
+ private
53
+ def allow_browser(versions:, block:)
54
+ require "useragent"
55
+
56
+ if BrowserBlocker.new(request, versions: versions).blocked?
57
+ ActiveSupport::Notifications.instrument("browser_block.action_controller", request: request, versions: versions) do
58
+ instance_exec(&block)
59
+ end
60
+ end
61
+ end
62
+
63
+ class BrowserBlocker
64
+ SETS = {
65
+ modern: { safari: 17.2, chrome: 120, firefox: 121, opera: 106, ie: false }
66
+ }
67
+
68
+ attr_reader :request, :versions
69
+
70
+ def initialize(request, versions:)
71
+ @request, @versions = request, versions
72
+ end
73
+
74
+ def blocked?
75
+ user_agent_version_reported? && unsupported_browser?
76
+ end
77
+
78
+ private
79
+ def parsed_user_agent
80
+ @parsed_user_agent ||= UserAgent.parse(request.user_agent)
81
+ end
82
+
83
+ def user_agent_version_reported?
84
+ request.user_agent.present? && parsed_user_agent.version.to_s.present?
85
+ end
86
+
87
+ def unsupported_browser?
88
+ version_guarded_browser? && version_below_minimum_required?
89
+ end
90
+
91
+ def version_guarded_browser?
92
+ minimum_browser_version_for_browser != nil
93
+ end
94
+
95
+ def version_below_minimum_required?
96
+ if minimum_browser_version_for_browser
97
+ parsed_user_agent.version < UserAgent::Version.new(minimum_browser_version_for_browser.to_s)
98
+ else
99
+ true
100
+ end
101
+ end
102
+
103
+ def minimum_browser_version_for_browser
104
+ expanded_versions[normalized_browser_name]
105
+ end
106
+
107
+ def expanded_versions
108
+ @expanded_versions ||= (SETS[versions] || versions).with_indifferent_access
109
+ end
110
+
111
+ def normalized_browser_name
112
+ case name = parsed_user_agent.browser.downcase
113
+ when "internet explorer" then "ie"
114
+ else name
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController
4
6
  module BasicImplicitRender # :nodoc:
5
7
  def send_action(method, *args)