actionpack 8.0.3 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +337 -158
  3. data/lib/abstract_controller/asset_paths.rb +4 -2
  4. data/lib/abstract_controller/base.rb +12 -3
  5. data/lib/abstract_controller/caching.rb +6 -3
  6. data/lib/abstract_controller/helpers.rb +1 -1
  7. data/lib/abstract_controller/logger.rb +2 -1
  8. data/lib/action_controller/api.rb +1 -0
  9. data/lib/action_controller/base.rb +2 -1
  10. data/lib/action_controller/caching.rb +1 -2
  11. data/lib/action_controller/form_builder.rb +1 -1
  12. data/lib/action_controller/log_subscriber.rb +18 -3
  13. data/lib/action_controller/metal/allow_browser.rb +1 -1
  14. data/lib/action_controller/metal/conditional_get.rb +25 -0
  15. data/lib/action_controller/metal/data_streaming.rb +1 -3
  16. data/lib/action_controller/metal/exceptions.rb +5 -0
  17. data/lib/action_controller/metal/flash.rb +1 -4
  18. data/lib/action_controller/metal/head.rb +3 -1
  19. data/lib/action_controller/metal/live.rb +9 -18
  20. data/lib/action_controller/metal/permissions_policy.rb +9 -0
  21. data/lib/action_controller/metal/rate_limiting.rb +30 -9
  22. data/lib/action_controller/metal/redirecting.rb +105 -13
  23. data/lib/action_controller/metal/renderers.rb +27 -6
  24. data/lib/action_controller/metal/rendering.rb +7 -1
  25. data/lib/action_controller/metal/request_forgery_protection.rb +18 -10
  26. data/lib/action_controller/metal/rescue.rb +9 -0
  27. data/lib/action_controller/railtie.rb +27 -8
  28. data/lib/action_controller/structured_event_subscriber.rb +112 -0
  29. data/lib/action_dispatch/http/cache.rb +111 -1
  30. data/lib/action_dispatch/http/filter_parameters.rb +5 -3
  31. data/lib/action_dispatch/http/mime_negotiation.rb +55 -1
  32. data/lib/action_dispatch/http/mime_types.rb +1 -0
  33. data/lib/action_dispatch/http/param_builder.rb +28 -27
  34. data/lib/action_dispatch/http/parameters.rb +3 -3
  35. data/lib/action_dispatch/http/permissions_policy.rb +4 -0
  36. data/lib/action_dispatch/http/query_parser.rb +12 -10
  37. data/lib/action_dispatch/http/request.rb +10 -5
  38. data/lib/action_dispatch/http/response.rb +16 -3
  39. data/lib/action_dispatch/http/url.rb +110 -14
  40. data/lib/action_dispatch/journey/gtg/simulator.rb +33 -12
  41. data/lib/action_dispatch/journey/gtg/transition_table.rb +33 -41
  42. data/lib/action_dispatch/journey/nodes/node.rb +2 -1
  43. data/lib/action_dispatch/journey/route.rb +45 -31
  44. data/lib/action_dispatch/journey/router/utils.rb +8 -14
  45. data/lib/action_dispatch/journey/router.rb +59 -81
  46. data/lib/action_dispatch/journey/routes.rb +7 -0
  47. data/lib/action_dispatch/journey/visitors.rb +55 -23
  48. data/lib/action_dispatch/journey/visualizer/fsm.js +4 -6
  49. data/lib/action_dispatch/log_subscriber.rb +7 -3
  50. data/lib/action_dispatch/middleware/cookies.rb +4 -2
  51. data/lib/action_dispatch/middleware/debug_exceptions.rb +7 -1
  52. data/lib/action_dispatch/middleware/debug_view.rb +11 -0
  53. data/lib/action_dispatch/middleware/exception_wrapper.rb +11 -5
  54. data/lib/action_dispatch/middleware/executor.rb +12 -2
  55. data/lib/action_dispatch/middleware/public_exceptions.rb +1 -5
  56. data/lib/action_dispatch/middleware/remote_ip.rb +9 -4
  57. data/lib/action_dispatch/middleware/session/cache_store.rb +17 -0
  58. data/lib/action_dispatch/middleware/templates/rescues/_copy_button.html.erb +1 -0
  59. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +3 -2
  60. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +9 -5
  61. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +1 -0
  62. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +1 -0
  63. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +4 -0
  64. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -0
  65. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +50 -0
  66. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -0
  67. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -0
  68. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -0
  69. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -0
  70. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -0
  71. data/lib/action_dispatch/railtie.rb +14 -2
  72. data/lib/action_dispatch/routing/inspector.rb +79 -56
  73. data/lib/action_dispatch/routing/mapper.rb +324 -172
  74. data/lib/action_dispatch/routing/redirection.rb +10 -7
  75. data/lib/action_dispatch/routing/route_set.rb +2 -4
  76. data/lib/action_dispatch/structured_event_subscriber.rb +20 -0
  77. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +2 -2
  78. data/lib/action_dispatch/testing/assertions/response.rb +14 -0
  79. data/lib/action_dispatch/testing/assertions/routing.rb +11 -3
  80. data/lib/action_dispatch/testing/integration.rb +1 -1
  81. data/lib/action_dispatch/testing/request_encoder.rb +9 -9
  82. data/lib/action_dispatch.rb +8 -0
  83. data/lib/action_pack/gem_version.rb +2 -2
  84. metadata +13 -10
@@ -12,9 +12,10 @@ module ActionDispatch
12
12
  class Redirect < Endpoint # :nodoc:
13
13
  attr_reader :status, :block
14
14
 
15
- def initialize(status, block)
15
+ def initialize(status, block, source_location)
16
16
  @status = status
17
17
  @block = block
18
+ @source_location = source_location
18
19
  end
19
20
 
20
21
  def redirect?; true; end
@@ -27,6 +28,7 @@ module ActionDispatch
27
28
  payload[:status] = @status
28
29
  payload[:location] = response.headers["Location"]
29
30
  payload[:request] = request
31
+ payload[:source_location] = @source_location if @source_location
30
32
 
31
33
  response.to_a
32
34
  end
@@ -202,16 +204,17 @@ module ActionDispatch
202
204
  # get 'accounts/:name' => redirect(SubdomainRedirector.new('api'))
203
205
  #
204
206
  def redirect(*args, &block)
205
- options = args.extract_options!
206
- status = options.delete(:status) || 301
207
- path = args.shift
207
+ options = args.extract_options!
208
+ status = options.delete(:status) || 301
209
+ path = args.shift
210
+ source_location = caller[0] if ActionDispatch.verbose_redirect_logs
208
211
 
209
- return OptionRedirect.new(status, options) if options.any?
210
- return PathRedirect.new(status, path) if String === path
212
+ return OptionRedirect.new(status, options, source_location) if options.any?
213
+ return PathRedirect.new(status, path, source_location) if String === path
211
214
 
212
215
  block = path if path.respond_to? :call
213
216
  raise ArgumentError, "redirection argument not supported" unless block
214
- Redirect.new status, block
217
+ Redirect.new status, block, source_location
215
218
  end
216
219
  end
217
220
  end
@@ -59,8 +59,6 @@ module ActionDispatch
59
59
  private
60
60
  def controller(req)
61
61
  req.controller_class
62
- rescue NameError => e
63
- raise ActionController::RoutingError, e.message, e.backtrace
64
62
  end
65
63
 
66
64
  def dispatch(controller, action, req, res)
@@ -659,14 +657,14 @@ module ActionDispatch
659
657
  if route.segment_keys.include?(:controller)
660
658
  ActionDispatch.deprecator.warn(<<-MSG.squish)
661
659
  Using a dynamic :controller segment in a route is deprecated and
662
- will be removed in Rails 8.1.
660
+ will be removed in Rails 9.0.
663
661
  MSG
664
662
  end
665
663
 
666
664
  if route.segment_keys.include?(:action)
667
665
  ActionDispatch.deprecator.warn(<<-MSG.squish)
668
666
  Using a dynamic :action segment in a route is deprecated and
669
- will be removed in Rails 8.1.
667
+ will be removed in Rails 9.0.
670
668
  MSG
671
669
  end
672
670
 
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ class StructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber # :nodoc:
5
+ def redirect(event)
6
+ payload = event.payload
7
+ status = payload[:status]
8
+
9
+ emit_event("action_dispatch.redirect", {
10
+ location: payload[:location],
11
+ status: status,
12
+ status_name: Rack::Utils::HTTP_STATUS_CODES[status],
13
+ duration_ms: event.duration.round(2),
14
+ source_location: payload[:source_location]
15
+ })
16
+ end
17
+ end
18
+ end
19
+
20
+ ActionDispatch::StructuredEventSubscriber.attach_to :action_dispatch
@@ -132,8 +132,8 @@ module ActionDispatch
132
132
  end
133
133
 
134
134
  def display_image(html:, screenshot_output:)
135
- message = +"[Screenshot Image]: #{image_path}\n"
136
- message << +"[Screenshot HTML]: #{html_path}\n" if html
135
+ message = +"[Screenshot Image]: #{image_path} \n"
136
+ message << +"[Screenshot HTML]: #{html_path} \n" if html
137
137
 
138
138
  case screenshot_output || output_type
139
139
  when "artifact"
@@ -71,6 +71,20 @@ module ActionDispatch
71
71
  assert_operator redirect_expected, :===, redirect_is, message
72
72
  end
73
73
 
74
+ # Asserts that the given +text+ is present somewhere in the response body.
75
+ #
76
+ # assert_in_body fixture(:name).description
77
+ def assert_in_body(text)
78
+ assert_match(/#{Regexp.escape(text)}/, @response.body)
79
+ end
80
+
81
+ # Asserts that the given +text+ is not present anywhere in the response body.
82
+ #
83
+ # assert_not_in_body fixture(:name).description
84
+ def assert_not_in_body(text)
85
+ assert_no_match(/#{Regexp.escape(text)}/, @response.body)
86
+ end
87
+
74
88
  private
75
89
  # Proxy to to_param if the object will respond to it.
76
90
  def parameterize(value)
@@ -25,7 +25,7 @@ module ActionDispatch
25
25
  old_integration_session = nil
26
26
 
27
27
  setup do
28
- old_routes = app.routes
28
+ old_routes = initialize_lazy_routes(app.routes)
29
29
  old_routes_call_method = old_routes.method(:call)
30
30
  old_integration_session = integration_session
31
31
  create_routes(&block)
@@ -38,7 +38,7 @@ module ActionDispatch
38
38
  end
39
39
 
40
40
  def with_routing(&block)
41
- old_routes = app.routes
41
+ old_routes = initialize_lazy_routes(app.routes)
42
42
  old_routes_call_method = old_routes.method(:call)
43
43
  old_integration_session = integration_session
44
44
  create_routes(&block)
@@ -47,6 +47,14 @@ module ActionDispatch
47
47
  end
48
48
 
49
49
  private
50
+ def initialize_lazy_routes(routes)
51
+ if defined?(Rails::Engine::LazyRouteSet) && routes.is_a?(Rails::Engine::LazyRouteSet)
52
+ routes.tap(&:routes)
53
+ else
54
+ routes
55
+ end
56
+ end
57
+
50
58
  def create_routes
51
59
  app = self.app
52
60
  routes = ActionDispatch::Routing::RouteSet.new
@@ -340,7 +348,7 @@ module ActionDispatch
340
348
  def fail_on(exception_class, message)
341
349
  yield
342
350
  rescue exception_class => e
343
- raise Minitest::Assertion, message || e.message
351
+ flunk(message || e.message)
344
352
  end
345
353
  end
346
354
  end
@@ -621,7 +621,7 @@ module ActionDispatch
621
621
  # end
622
622
  #
623
623
  # assert_response :success
624
- # assert_equal({ id: Article.last.id, title: "Ahoy!" }, response.parsed_body)
624
+ # assert_equal({ "id" => Article.last.id, "title" => "Ahoy!" }, response.parsed_body)
625
625
  # end
626
626
  # end
627
627
  #
@@ -3,6 +3,7 @@
3
3
  # :markup: markdown
4
4
 
5
5
  require "nokogiri"
6
+ require "action_dispatch/http/mime_type"
6
7
 
7
8
  module ActionDispatch
8
9
  class RequestEncoder # :nodoc:
@@ -15,9 +16,9 @@ module ActionDispatch
15
16
 
16
17
  @encoders = { identity: IdentityEncoder.new }
17
18
 
18
- attr_reader :response_parser
19
+ attr_reader :response_parser, :content_type
19
20
 
20
- def initialize(mime_name, param_encoder, response_parser)
21
+ def initialize(mime_name, param_encoder, response_parser, content_type)
21
22
  @mime = Mime[mime_name]
22
23
 
23
24
  unless @mime
@@ -27,10 +28,7 @@ module ActionDispatch
27
28
 
28
29
  @response_parser = response_parser || -> body { body }
29
30
  @param_encoder = param_encoder || :"to_#{@mime.symbol}".to_proc
30
- end
31
-
32
- def content_type
33
- @mime.to_s
31
+ @content_type = content_type || @mime.to_s
34
32
  end
35
33
 
36
34
  def accept_header
@@ -50,11 +48,13 @@ module ActionDispatch
50
48
  @encoders[name] || @encoders[:identity]
51
49
  end
52
50
 
53
- def self.register_encoder(mime_name, param_encoder: nil, response_parser: nil)
54
- @encoders[mime_name] = new(mime_name, param_encoder, response_parser)
51
+ def self.register_encoder(mime_name, param_encoder: nil, response_parser: nil, content_type: nil)
52
+ @encoders[mime_name] = new(mime_name, param_encoder, response_parser, content_type)
55
53
  end
56
54
 
57
- register_encoder :html, response_parser: -> body { Rails::Dom::Testing.html_document.parse(body) }
55
+ register_encoder :html, response_parser: -> body { Rails::Dom::Testing.html_document.parse(body) },
56
+ param_encoder: -> param { param },
57
+ content_type: Mime[:url_encoded_form].to_s
58
58
  register_encoder :json, response_parser: -> body { JSON.parse(body, object_class: ActiveSupport::HashWithIndifferentAccess) }
59
59
  end
60
60
  end
@@ -138,6 +138,14 @@ module ActionDispatch
138
138
 
139
139
  autoload :SystemTestCase, "action_dispatch/system_test_case"
140
140
 
141
+ ##
142
+ # :singleton-method:
143
+ #
144
+ # Specifies if the methods calling redirects in controllers and routes should
145
+ # be logged below their relevant log lines. Defaults to false.
146
+ singleton_class.attr_accessor :verbose_redirect_logs
147
+ self.verbose_redirect_logs = false
148
+
141
149
  def eager_load!
142
150
  super
143
151
  Routing.eager_load!
@@ -10,8 +10,8 @@ module ActionPack
10
10
 
11
11
  module VERSION
12
12
  MAJOR = 8
13
- MINOR = 0
14
- TINY = 3
13
+ MINOR = 1
14
+ TINY = 0
15
15
  PRE = nil
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.3
4
+ version: 8.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 8.0.3
18
+ version: 8.1.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 8.0.3
25
+ version: 8.1.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: nokogiri
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -127,28 +127,28 @@ dependencies:
127
127
  requirements:
128
128
  - - '='
129
129
  - !ruby/object:Gem::Version
130
- version: 8.0.3
130
+ version: 8.1.0
131
131
  type: :runtime
132
132
  prerelease: false
133
133
  version_requirements: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - '='
136
136
  - !ruby/object:Gem::Version
137
- version: 8.0.3
137
+ version: 8.1.0
138
138
  - !ruby/object:Gem::Dependency
139
139
  name: activemodel
140
140
  requirement: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - '='
143
143
  - !ruby/object:Gem::Version
144
- version: 8.0.3
144
+ version: 8.1.0
145
145
  type: :development
146
146
  prerelease: false
147
147
  version_requirements: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - '='
150
150
  - !ruby/object:Gem::Version
151
- version: 8.0.3
151
+ version: 8.1.0
152
152
  description: Web apps on Rails. Simple, battle-tested conventions for building and
153
153
  testing MVC web applications. Works with any Rack-compatible server.
154
154
  email: david@loudthinking.com
@@ -218,6 +218,7 @@ files:
218
218
  - lib/action_controller/railtie.rb
219
219
  - lib/action_controller/railties/helpers.rb
220
220
  - lib/action_controller/renderer.rb
221
+ - lib/action_controller/structured_event_subscriber.rb
221
222
  - lib/action_controller/template_assertions.rb
222
223
  - lib/action_controller/test_case.rb
223
224
  - lib/action_dispatch.rb
@@ -287,6 +288,7 @@ files:
287
288
  - lib/action_dispatch/middleware/static.rb
288
289
  - lib/action_dispatch/middleware/templates/rescues/_actions.html.erb
289
290
  - lib/action_dispatch/middleware/templates/rescues/_actions.text.erb
291
+ - lib/action_dispatch/middleware/templates/rescues/_copy_button.html.erb
290
292
  - lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb
291
293
  - lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
292
294
  - lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb
@@ -325,6 +327,7 @@ files:
325
327
  - lib/action_dispatch/routing/route_set.rb
326
328
  - lib/action_dispatch/routing/routes_proxy.rb
327
329
  - lib/action_dispatch/routing/url_for.rb
330
+ - lib/action_dispatch/structured_event_subscriber.rb
328
331
  - lib/action_dispatch/system_test_case.rb
329
332
  - lib/action_dispatch/system_testing/browser.rb
330
333
  - lib/action_dispatch/system_testing/driver.rb
@@ -349,10 +352,10 @@ licenses:
349
352
  - MIT
350
353
  metadata:
351
354
  bug_tracker_uri: https://github.com/rails/rails/issues
352
- changelog_uri: https://github.com/rails/rails/blob/v8.0.3/actionpack/CHANGELOG.md
353
- documentation_uri: https://api.rubyonrails.org/v8.0.3/
355
+ changelog_uri: https://github.com/rails/rails/blob/v8.1.0/actionpack/CHANGELOG.md
356
+ documentation_uri: https://api.rubyonrails.org/v8.1.0/
354
357
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
355
- source_code_uri: https://github.com/rails/rails/tree/v8.0.3/actionpack
358
+ source_code_uri: https://github.com/rails/rails/tree/v8.1.0/actionpack
356
359
  rubygems_mfa_required: 'true'
357
360
  rdoc_options: []
358
361
  require_paths: