actionpack 6.1.4 → 7.0.0.rc1

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +189 -372
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -3
  5. data/lib/abstract_controller/asset_paths.rb +1 -1
  6. data/lib/abstract_controller/base.rb +7 -21
  7. data/lib/abstract_controller/caching/fragments.rb +2 -2
  8. data/lib/abstract_controller/caching.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +21 -7
  10. data/lib/abstract_controller/collector.rb +4 -2
  11. data/lib/abstract_controller/error.rb +1 -1
  12. data/lib/abstract_controller/helpers.rb +3 -2
  13. data/lib/abstract_controller/logger.rb +1 -1
  14. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  15. data/lib/abstract_controller/translation.rb +3 -2
  16. data/lib/abstract_controller/url_for.rb +4 -6
  17. data/lib/action_controller/api.rb +1 -1
  18. data/lib/action_controller/log_subscriber.rb +4 -3
  19. data/lib/action_controller/metal/conditional_get.rb +38 -1
  20. data/lib/action_controller/metal/content_security_policy.rb +1 -1
  21. data/lib/action_controller/metal/cookies.rb +1 -1
  22. data/lib/action_controller/metal/data_streaming.rb +5 -13
  23. data/lib/action_controller/metal/exceptions.rb +19 -30
  24. data/lib/action_controller/metal/flash.rb +6 -2
  25. data/lib/action_controller/metal/helpers.rb +1 -1
  26. data/lib/action_controller/metal/http_authentication.rb +17 -16
  27. data/lib/action_controller/metal/instrumentation.rb +57 -52
  28. data/lib/action_controller/metal/live.rb +42 -2
  29. data/lib/action_controller/metal/mime_responds.rb +3 -3
  30. data/lib/action_controller/metal/params_wrapper.rb +20 -11
  31. data/lib/action_controller/metal/permissions_policy.rb +1 -1
  32. data/lib/action_controller/metal/redirecting.rb +86 -16
  33. data/lib/action_controller/metal/rendering.rb +7 -7
  34. data/lib/action_controller/metal/request_forgery_protection.rb +64 -24
  35. data/lib/action_controller/metal/rescue.rb +1 -1
  36. data/lib/action_controller/metal/streaming.rb +1 -3
  37. data/lib/action_controller/metal/strong_parameters.rb +84 -47
  38. data/lib/action_controller/metal/testing.rb +0 -2
  39. data/lib/action_controller/metal.rb +7 -10
  40. data/lib/action_controller/railtie.rb +49 -6
  41. data/lib/action_controller/test_case.rb +19 -4
  42. data/lib/action_controller.rb +1 -5
  43. data/lib/action_dispatch/http/cache.rb +13 -6
  44. data/lib/action_dispatch/http/content_security_policy.rb +39 -35
  45. data/lib/action_dispatch/http/filter_parameters.rb +5 -0
  46. data/lib/action_dispatch/http/mime_negotiation.rb +13 -3
  47. data/lib/action_dispatch/http/mime_type.rb +9 -11
  48. data/lib/action_dispatch/http/parameters.rb +4 -4
  49. data/lib/action_dispatch/http/permissions_policy.rb +1 -1
  50. data/lib/action_dispatch/http/request.rb +10 -19
  51. data/lib/action_dispatch/http/response.rb +1 -13
  52. data/lib/action_dispatch/http/url.rb +11 -19
  53. data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
  54. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
  55. data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
  56. data/lib/action_dispatch/journey/nodes/node.rb +70 -5
  57. data/lib/action_dispatch/journey/path/pattern.rb +22 -13
  58. data/lib/action_dispatch/journey/route.rb +6 -13
  59. data/lib/action_dispatch/journey/router/utils.rb +2 -2
  60. data/lib/action_dispatch/journey/router.rb +1 -1
  61. data/lib/action_dispatch/journey/routes.rb +3 -3
  62. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  63. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  64. data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
  65. data/lib/action_dispatch/middleware/cookies.rb +8 -4
  66. data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
  67. data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
  68. data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
  69. data/lib/action_dispatch/middleware/executor.rb +3 -0
  70. data/lib/action_dispatch/middleware/flash.rb +9 -11
  71. data/lib/action_dispatch/middleware/host_authorization.rb +49 -37
  72. data/lib/action_dispatch/middleware/remote_ip.rb +16 -4
  73. data/lib/action_dispatch/middleware/server_timing.rb +33 -0
  74. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
  75. data/lib/action_dispatch/middleware/show_exceptions.rb +17 -9
  76. data/lib/action_dispatch/middleware/stack.rb +27 -9
  77. data/lib/action_dispatch/middleware/static.rb +2 -6
  78. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
  79. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
  80. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
  81. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +4 -3
  82. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +3 -1
  83. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
  84. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
  85. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
  86. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
  87. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
  88. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  89. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  90. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
  91. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +5 -14
  92. data/lib/action_dispatch/railtie.rb +8 -2
  93. data/lib/action_dispatch/request/session.rb +43 -13
  94. data/lib/action_dispatch/routing/inspector.rb +1 -1
  95. data/lib/action_dispatch/routing/mapper.rb +54 -78
  96. data/lib/action_dispatch/routing/redirection.rb +0 -2
  97. data/lib/action_dispatch/routing/route_set.rb +14 -6
  98. data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
  99. data/lib/action_dispatch/routing/url_for.rb +1 -2
  100. data/lib/action_dispatch/routing.rb +2 -2
  101. data/lib/action_dispatch/system_test_case.rb +12 -6
  102. data/lib/action_dispatch/system_testing/browser.rb +2 -12
  103. data/lib/action_dispatch/system_testing/driver.rb +35 -11
  104. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +10 -6
  105. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
  106. data/lib/action_dispatch/testing/assertions.rb +2 -5
  107. data/lib/action_dispatch/testing/integration.rb +6 -8
  108. data/lib/action_dispatch/testing/test_process.rb +3 -26
  109. data/lib/action_dispatch.rb +2 -1
  110. data/lib/action_pack/gem_version.rb +4 -4
  111. data/lib/action_pack.rb +1 -1
  112. metadata +19 -17
@@ -31,7 +31,7 @@ module ActionController
31
31
 
32
32
  # ActionController::TestCase will be deprecated and moved to a gem in the future.
33
33
  # Please use ActionDispatch::IntegrationTest going forward.
34
- class TestRequest < ActionDispatch::TestRequest #:nodoc:
34
+ class TestRequest < ActionDispatch::TestRequest # :nodoc:
35
35
  DEFAULT_ENV = ActionDispatch::TestRequest::DEFAULT_ENV.dup
36
36
  DEFAULT_ENV.delete "PATH_INFO"
37
37
 
@@ -179,7 +179,7 @@ module ActionController
179
179
 
180
180
  # Methods #destroy and #load! are overridden to avoid calling methods on the
181
181
  # @store object, which does not exist for the TestSession class.
182
- class TestSession < Rack::Session::Abstract::PersistedSecure::SecureSessionHash #:nodoc:
182
+ class TestSession < Rack::Session::Abstract::PersistedSecure::SecureSessionHash # :nodoc:
183
183
  DEFAULT_OPTIONS = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS
184
184
 
185
185
  def initialize(session = {})
@@ -214,6 +214,10 @@ module ActionController
214
214
  @data.fetch(key.to_s, *args, &block)
215
215
  end
216
216
 
217
+ def enabled?
218
+ true
219
+ end
220
+
217
221
  private
218
222
  def load!
219
223
  @id
@@ -329,6 +333,8 @@ module ActionController
329
333
  #
330
334
  # assert_redirected_to page_url(title: 'foo')
331
335
  class TestCase < ActiveSupport::TestCase
336
+ singleton_class.attr_accessor :executor_around_each_request
337
+
332
338
  module Behavior
333
339
  extend ActiveSupport::Concern
334
340
  include ActionDispatch::TestProcess
@@ -574,10 +580,19 @@ module ActionController
574
580
  end
575
581
  end
576
582
 
583
+ def wrap_execution(&block)
584
+ if ActionController::TestCase.executor_around_each_request && defined?(Rails.application) && Rails.application
585
+ Rails.application.executor.wrap(&block)
586
+ else
587
+ yield
588
+ end
589
+ end
590
+
577
591
  def process_controller_response(action, cookies, xhr)
578
592
  begin
579
593
  @controller.recycle!
580
- @controller.dispatch(action, @request, @response)
594
+
595
+ wrap_execution { @controller.dispatch(action, @request, @response) }
581
596
  ensure
582
597
  @request = @controller.request
583
598
  @response = @controller.response
@@ -623,7 +638,7 @@ module ActionController
623
638
  end
624
639
 
625
640
  def check_required_ivars
626
- # Sanity check for required instance variables so we can give an
641
+ # Check for required instance variables so we can give an
627
642
  # understandable error message.
628
643
  [:@routes, :@controller, :@request, :@response].each do |iv_name|
629
644
  if !instance_variable_defined?(iv_name) || instance_variable_get(iv_name).nil?
@@ -18,10 +18,6 @@ module ActionController
18
18
  end
19
19
 
20
20
  autoload_under "metal" do
21
- eager_autoload do
22
- autoload :Live
23
- end
24
-
25
21
  autoload :ConditionalGet
26
22
  autoload :ContentSecurityPolicy
27
23
  autoload :Cookies
@@ -37,6 +33,7 @@ module ActionController
37
33
  autoload :BasicImplicitRender
38
34
  autoload :ImplicitRender
39
35
  autoload :Instrumentation
36
+ autoload :Live
40
37
  autoload :Logging
41
38
  autoload :MimeResponds
42
39
  autoload :ParamsWrapper
@@ -65,5 +62,4 @@ require "active_support/core_ext/module/attribute_accessors"
65
62
  require "active_support/core_ext/load_error"
66
63
  require "active_support/core_ext/module/attr_internal"
67
64
  require "active_support/core_ext/name_error"
68
- require "active_support/core_ext/uri"
69
65
  require "active_support/inflector"
@@ -187,13 +187,20 @@ module ActionDispatch
187
187
 
188
188
  return if control.empty? && cache_control.empty? # Let middleware handle default behavior
189
189
 
190
- if extras = control.delete(:extras)
191
- cache_control[:extras] ||= []
192
- cache_control[:extras] += extras
193
- cache_control[:extras].uniq!
194
- end
190
+ if cache_control.any?
191
+ # Any caching directive coming from a controller overrides
192
+ # no-cache/no-store in the default Cache-Control header.
193
+ control.delete(:no_cache)
194
+ control.delete(:no_store)
195
195
 
196
- control.merge! cache_control
196
+ if extras = control.delete(:extras)
197
+ cache_control[:extras] ||= []
198
+ cache_control[:extras] += extras
199
+ cache_control[:extras].uniq!
200
+ end
201
+
202
+ control.merge! cache_control
203
+ end
197
204
 
198
205
  options = []
199
206
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "active_support/core_ext/object/deep_dup"
4
4
 
5
- module ActionDispatch #:nodoc:
5
+ module ActionDispatch # :nodoc:
6
6
  class ContentSecurityPolicy
7
7
  class Middleware
8
8
  CONTENT_TYPE = "Content-Type"
@@ -106,43 +106,47 @@ module ActionDispatch #:nodoc:
106
106
  end
107
107
 
108
108
  MAPPINGS = {
109
- self: "'self'",
110
- unsafe_eval: "'unsafe-eval'",
111
- unsafe_inline: "'unsafe-inline'",
112
- none: "'none'",
113
- http: "http:",
114
- https: "https:",
115
- data: "data:",
116
- mediastream: "mediastream:",
117
- blob: "blob:",
118
- filesystem: "filesystem:",
119
- report_sample: "'report-sample'",
120
- strict_dynamic: "'strict-dynamic'",
121
- ws: "ws:",
122
- wss: "wss:"
109
+ self: "'self'",
110
+ unsafe_eval: "'unsafe-eval'",
111
+ unsafe_inline: "'unsafe-inline'",
112
+ none: "'none'",
113
+ http: "http:",
114
+ https: "https:",
115
+ data: "data:",
116
+ mediastream: "mediastream:",
117
+ allow_duplicates: "'allow-duplicates'",
118
+ blob: "blob:",
119
+ filesystem: "filesystem:",
120
+ report_sample: "'report-sample'",
121
+ script: "'script'",
122
+ strict_dynamic: "'strict-dynamic'",
123
+ ws: "ws:",
124
+ wss: "wss:"
123
125
  }.freeze
124
126
 
125
127
  DIRECTIVES = {
126
- base_uri: "base-uri",
127
- child_src: "child-src",
128
- connect_src: "connect-src",
129
- default_src: "default-src",
130
- font_src: "font-src",
131
- form_action: "form-action",
132
- frame_ancestors: "frame-ancestors",
133
- frame_src: "frame-src",
134
- img_src: "img-src",
135
- manifest_src: "manifest-src",
136
- media_src: "media-src",
137
- object_src: "object-src",
138
- prefetch_src: "prefetch-src",
139
- script_src: "script-src",
140
- script_src_attr: "script-src-attr",
141
- script_src_elem: "script-src-elem",
142
- style_src: "style-src",
143
- style_src_attr: "style-src-attr",
144
- style_src_elem: "style-src-elem",
145
- worker_src: "worker-src"
128
+ base_uri: "base-uri",
129
+ child_src: "child-src",
130
+ connect_src: "connect-src",
131
+ default_src: "default-src",
132
+ font_src: "font-src",
133
+ form_action: "form-action",
134
+ frame_ancestors: "frame-ancestors",
135
+ frame_src: "frame-src",
136
+ img_src: "img-src",
137
+ manifest_src: "manifest-src",
138
+ media_src: "media-src",
139
+ object_src: "object-src",
140
+ prefetch_src: "prefetch-src",
141
+ require_trusted_types_for: "require-trusted-types-for",
142
+ script_src: "script-src",
143
+ script_src_attr: "script-src-attr",
144
+ script_src_elem: "script-src-elem",
145
+ style_src: "style-src",
146
+ style_src_attr: "style-src-attr",
147
+ style_src_elem: "style-src-elem",
148
+ trusted_types: "trusted-types",
149
+ worker_src: "worker-src"
146
150
  }.freeze
147
151
 
148
152
  DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze
@@ -18,6 +18,11 @@ module ActionDispatch
18
18
  # env["action_dispatch.parameter_filter"] = [:foo, "bar"]
19
19
  # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
20
20
  #
21
+ # env["action_dispatch.parameter_filter"] = [ /\Apin\z/i, /\Apin_/i ]
22
+ # => replaces the value for the exact (case-insensitive) key 'pin' and all
23
+ # (case-insensitive) keys beginning with 'pin_', with "[FILTERED]"
24
+ # Does not match keys with 'pin' as a substring, such as 'shipping_id'.
25
+ #
21
26
  # env["action_dispatch.parameter_filter"] = [ "credit_card.code" ]
22
27
  # => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
23
28
  # change { file: { code: "xxxx"} }
@@ -16,12 +16,13 @@ module ActionDispatch
16
16
 
17
17
  included do
18
18
  mattr_accessor :ignore_accept_header, default: false
19
+ cattr_accessor :return_only_media_type_on_content_type, default: false
19
20
  end
20
21
 
21
22
  # The MIME type of the HTTP request, such as Mime[:xml].
22
23
  def content_mime_type
23
24
  fetch_header("action_dispatch.request.content_type") do |k|
24
- v = if get_header("CONTENT_TYPE") =~ /^([^,\;]*)/
25
+ v = if get_header("CONTENT_TYPE") =~ /^([^,;]*)/
25
26
  Mime::Type.lookup($1.strip.downcase)
26
27
  else
27
28
  nil
@@ -33,7 +34,16 @@ module ActionDispatch
33
34
  end
34
35
 
35
36
  def content_type
36
- content_mime_type && content_mime_type.to_s
37
+ if self.class.return_only_media_type_on_content_type
38
+ ActiveSupport::Deprecation.warn(
39
+ "Rails 7.1 will return Content-Type header without modification." \
40
+ " If you want just the MIME type, please use `#media_type` instead."
41
+ )
42
+
43
+ content_mime_type&.to_s
44
+ else
45
+ super
46
+ end
37
47
  end
38
48
 
39
49
  def has_content_type? # :nodoc:
@@ -92,7 +102,7 @@ module ActionDispatch
92
102
  def variant=(variant)
93
103
  variant = Array(variant)
94
104
 
95
- if variant.all? { |v| v.is_a?(Symbol) }
105
+ if variant.all?(Symbol)
96
106
  @variant = ActiveSupport::ArrayInquirer.new(variant)
97
107
  else
98
108
  raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols."
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "singleton"
4
- require "active_support/core_ext/symbol/starts_ends_with"
5
4
 
6
5
  module Mime
7
6
  class Mimes
@@ -14,8 +13,8 @@ module Mime
14
13
  @symbols = []
15
14
  end
16
15
 
17
- def each
18
- @mimes.each { |x| yield x }
16
+ def each(&block)
17
+ @mimes.each(&block)
19
18
  end
20
19
 
21
20
  def <<(type)
@@ -43,9 +42,9 @@ module Mime
43
42
  Type.lookup_by_extension(type)
44
43
  end
45
44
 
46
- def fetch(type)
45
+ def fetch(type, &block)
47
46
  return type if type.is_a?(Type)
48
- EXTENSION_LOOKUP.fetch(type.to_s) { |k| yield k }
47
+ EXTENSION_LOOKUP.fetch(type.to_s, &block)
49
48
  end
50
49
  end
51
50
 
@@ -68,7 +67,7 @@ module Mime
68
67
  @register_callbacks = []
69
68
 
70
69
  # A simple helper class used in parsing the accept header.
71
- class AcceptItem #:nodoc:
70
+ class AcceptItem # :nodoc:
72
71
  attr_accessor :index, :name, :q
73
72
  alias :to_s :name
74
73
 
@@ -86,7 +85,7 @@ module Mime
86
85
  end
87
86
  end
88
87
 
89
- class AcceptList #:nodoc:
88
+ class AcceptList # :nodoc:
90
89
  def self.sort!(list)
91
90
  list.sort!
92
91
 
@@ -226,10 +225,9 @@ module Mime
226
225
  attr_reader :hash
227
226
 
228
227
  MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
229
- MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
230
- MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?"
231
- MIME_PARAMETER = "\s*\;\s*#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
232
- MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>\s*#{MIME_PARAMETER}\s*)*)\z/
228
+ MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?#{MIME_NAME}#{Regexp.escape('"')}?"
229
+ MIME_PARAMETER = "\s*;\s*#{MIME_NAME}(?:=#{MIME_PARAMETER_VALUE})?"
230
+ MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>#{MIME_PARAMETER})*\s*)\z/
233
231
 
234
232
  class InvalidMimeType < StandardError; end
235
233
 
@@ -17,8 +17,8 @@ module ActionDispatch
17
17
  # Raised when raw data from the request cannot be parsed by the parser
18
18
  # defined for request's content MIME type.
19
19
  class ParseError < StandardError
20
- def initialize
21
- super($!.message)
20
+ def initialize(message = $!.message)
21
+ super(message)
22
22
  end
23
23
  end
24
24
 
@@ -62,7 +62,7 @@ module ActionDispatch
62
62
  end
63
63
  alias :params :parameters
64
64
 
65
- def path_parameters=(parameters) #:nodoc:
65
+ def path_parameters=(parameters) # :nodoc:
66
66
  delete_header("action_dispatch.request.parameters")
67
67
 
68
68
  parameters = Request::Utils.set_binary_encoding(self, parameters, parameters[:controller], parameters[:action])
@@ -93,7 +93,7 @@ module ActionDispatch
93
93
  strategy.call(raw_post)
94
94
  rescue # JSON or Ruby code block errors.
95
95
  log_parse_error_once
96
- raise ParseError
96
+ raise ParseError, "Error occurred while parsing request parameters"
97
97
  end
98
98
  end
99
99
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "active_support/core_ext/object/deep_dup"
4
4
 
5
- module ActionDispatch #:nodoc:
5
+ module ActionDispatch # :nodoc:
6
6
  class PermissionsPolicy
7
7
  class Middleware
8
8
  CONTENT_TYPE = "Content-Type"
@@ -42,11 +42,8 @@ module ActionDispatch
42
42
  HTTP_NEGOTIATE HTTP_PRAGMA HTTP_CLIENT_IP
43
43
  HTTP_X_FORWARDED_FOR HTTP_ORIGIN HTTP_VERSION
44
44
  HTTP_X_CSRF_TOKEN HTTP_X_REQUEST_ID HTTP_X_FORWARDED_HOST
45
- SERVER_ADDR
46
45
  ].freeze
47
46
 
48
- # TODO: Remove SERVER_ADDR when we remove support to Rack 2.1.
49
- # See https://github.com/rack/rack/commit/c173b188d81ee437b588c1e046a1c9f031dea550
50
47
  ENV_METHODS.each do |env|
51
48
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
52
49
  # frozen_string_literal: true
@@ -90,7 +87,7 @@ module ActionDispatch
90
87
  controller_param = name.underscore
91
88
  const_name = controller_param.camelize << "Controller"
92
89
  begin
93
- ActiveSupport::Dependencies.constantize(const_name)
90
+ const_name.constantize
94
91
  rescue NameError => error
95
92
  if error.missing_name == const_name || const_name.start_with?("#{error.missing_name}::")
96
93
  raise MissingController.new(error.message, error.name)
@@ -165,7 +162,7 @@ module ActionDispatch
165
162
  set_header(routes.env_key, name.dup)
166
163
  end
167
164
 
168
- def request_method=(request_method) #:nodoc:
165
+ def request_method=(request_method) # :nodoc:
169
166
  if check_method(request_method)
170
167
  @request_method = set_header("REQUEST_METHOD", request_method)
171
168
  end
@@ -266,7 +263,7 @@ module ActionDispatch
266
263
  # # get "/articles"
267
264
  # request.media_type # => "application/x-www-form-urlencoded"
268
265
  def media_type
269
- content_mime_type.to_s
266
+ content_mime_type&.to_s
270
267
  end
271
268
 
272
269
  # Returns the content length of the request as an integer.
@@ -355,21 +352,15 @@ module ActionDispatch
355
352
  FORM_DATA_MEDIA_TYPES.include?(media_type)
356
353
  end
357
354
 
358
- def body_stream #:nodoc:
355
+ def body_stream # :nodoc:
359
356
  get_header("rack.input")
360
357
  end
361
358
 
362
- # TODO This should be broken apart into AD::Request::Session and probably
363
- # be included by the session middleware.
364
359
  def reset_session
365
- if session && session.respond_to?(:destroy)
366
- session.destroy
367
- else
368
- self.session = {}
369
- end
360
+ session.destroy
370
361
  end
371
362
 
372
- def session=(session) #:nodoc:
363
+ def session=(session) # :nodoc:
373
364
  Session.set self, session
374
365
  end
375
366
 
@@ -434,10 +425,6 @@ module ActionDispatch
434
425
  def commit_flash
435
426
  end
436
427
 
437
- def ssl?
438
- super || scheme == "wss"
439
- end
440
-
441
428
  def inspect # :nodoc:
442
429
  "#<#{self.class.name} #{method} #{original_url.dump} for #{remote_ip}>"
443
430
  end
@@ -447,6 +434,10 @@ module ActionDispatch
447
434
  HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS[0...-1].join(', ')}, and #{HTTP_METHODS[-1]}")
448
435
  name
449
436
  end
437
+
438
+ def default_session
439
+ Session.disabled(self)
440
+ end
450
441
  end
451
442
  end
452
443
 
@@ -86,18 +86,6 @@ module ActionDispatch # :nodoc:
86
86
  cattr_accessor :default_charset, default: "utf-8"
87
87
  cattr_accessor :default_headers
88
88
 
89
- def self.return_only_media_type_on_content_type=(*)
90
- ActiveSupport::Deprecation.warn(
91
- ".return_only_media_type_on_content_type= is dreprecated with no replacement and will be removed in 6.2."
92
- )
93
- end
94
-
95
- def self.return_only_media_type_on_content_type
96
- ActiveSupport::Deprecation.warn(
97
- ".return_only_media_type_on_content_type is dreprecated with no replacement and will be removed in 6.2."
98
- )
99
- end
100
-
101
89
  include Rack::Response::Helpers
102
90
  # Aliasing these off because AD::Http::Cache::Response defines them.
103
91
  alias :_cache_control :cache_control
@@ -336,7 +324,7 @@ module ActionDispatch # :nodoc:
336
324
  # Avoid having to pass an open file handle as the response body.
337
325
  # Rack::Sendfile will usually intercept the response and uses
338
326
  # the path directly, so there is no reason to open the file.
339
- class FileBody #:nodoc:
327
+ class FileBody # :nodoc:
340
328
  attr_reader :to_path
341
329
 
342
330
  def initialize(path)
@@ -71,7 +71,8 @@ module ActionDispatch
71
71
  path = options[:script_name].to_s.chomp("/")
72
72
  path << options[:path] if options.key?(:path)
73
73
 
74
- add_trailing_slash(path) if options[:trailing_slash]
74
+ path = "/" if options[:trailing_slash] && path.blank?
75
+
75
76
  add_params(path, options[:params]) if options.key?(:params)
76
77
  add_anchor(path, options[:anchor]) if options.key?(:anchor)
77
78
 
@@ -101,14 +102,6 @@ module ActionDispatch
101
102
  parts[0..-(tld_length + 2)]
102
103
  end
103
104
 
104
- def add_trailing_slash(path)
105
- if path.include?("?")
106
- path.sub!(/\?/, '/\&')
107
- elsif !path.include?(".")
108
- path.sub!(/[^\/]\z|\A\z/, '\&/')
109
- end
110
- end
111
-
112
105
  def build_host_url(host, port, protocol, options, path)
113
106
  if match = host.match(HOST_REGEXP)
114
107
  protocol ||= match[1] unless protocol == false
@@ -222,7 +215,7 @@ module ActionDispatch
222
215
  if forwarded = x_forwarded_host.presence
223
216
  forwarded.split(/,\s?/).last
224
217
  else
225
- get_header("HTTP_HOST") || "#{server_name || server_addr}:#{get_header('SERVER_PORT')}"
218
+ get_header("HTTP_HOST") || "#{server_name}:#{get_header('SERVER_PORT')}"
226
219
  end
227
220
  end
228
221
 
@@ -258,12 +251,10 @@ module ActionDispatch
258
251
  # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
259
252
  # req.port # => 8080
260
253
  def port
261
- @port ||= begin
262
- if raw_host_with_port =~ /:(\d+)$/
263
- $1.to_i
264
- else
265
- standard_port
266
- end
254
+ @port ||= if raw_host_with_port =~ /:(\d+)$/
255
+ $1.to_i
256
+ else
257
+ standard_port
267
258
  end
268
259
  end
269
260
 
@@ -272,9 +263,10 @@ module ActionDispatch
272
263
  # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
273
264
  # req.standard_port # => 80
274
265
  def standard_port
275
- case protocol
276
- when "https://" then 443
277
- else 80
266
+ if "https://" == protocol
267
+ 443
268
+ else
269
+ 80
278
270
  end
279
271
  end
280
272
 
@@ -6,13 +6,13 @@ module ActionDispatch
6
6
  module Journey # :nodoc:
7
7
  module GTG # :nodoc:
8
8
  class Builder # :nodoc:
9
- DUMMY = Nodes::Dummy.new
9
+ DUMMY_END_NODE = Nodes::Dummy.new
10
10
 
11
11
  attr_reader :root, :ast, :endpoints
12
12
 
13
13
  def initialize(root)
14
14
  @root = root
15
- @ast = Nodes::Cat.new root, DUMMY
15
+ @ast = Nodes::Cat.new root, DUMMY_END_NODE
16
16
  @followpos = build_followpos
17
17
  end
18
18
 
@@ -28,12 +28,12 @@ module ActionDispatch
28
28
  marked[s] = true # mark s
29
29
 
30
30
  s.group_by { |state| symbol(state) }.each do |sym, ps|
31
- u = ps.flat_map { |l| @followpos[l] }
31
+ u = ps.flat_map { |l| @followpos[l] }.uniq
32
32
  next if u.empty?
33
33
 
34
34
  from = state_id[s]
35
35
 
36
- if u.all? { |pos| pos == DUMMY }
36
+ if u.all? { |pos| pos == DUMMY_END_NODE }
37
37
  to = state_id[Object.new]
38
38
  dtrans[from, to] = sym
39
39
  dtrans.add_accepting(to)
@@ -43,9 +43,9 @@ module ActionDispatch
43
43
  to = state_id[u]
44
44
  dtrans[from, to] = sym
45
45
 
46
- if u.include?(DUMMY)
46
+ if u.include?(DUMMY_END_NODE)
47
47
  ps.each do |state|
48
- if @followpos[state].include?(DUMMY)
48
+ if @followpos[state].include?(DUMMY_END_NODE)
49
49
  dtrans.add_memo(to, state.memo)
50
50
  end
51
51
  end
@@ -66,7 +66,10 @@ module ActionDispatch
66
66
  when Nodes::Group
67
67
  true
68
68
  when Nodes::Star
69
- true
69
+ # the default star regex is /(.+)/ which is NOT nullable
70
+ # but since different constraints can be provided we must
71
+ # actually check if this is the case or not.
72
+ node.regexp.match?("")
70
73
  when Nodes::Or
71
74
  node.children.any? { |c| nullable?(c) }
72
75
  when Nodes::Cat
@@ -104,7 +107,7 @@ module ActionDispatch
104
107
  def lastpos(node)
105
108
  case node
106
109
  when Nodes::Star
107
- firstpos(node.left)
110
+ lastpos(node.left)
108
111
  when Nodes::Or
109
112
  node.children.flat_map { |c| lastpos(c) }.tap(&:uniq!)
110
113
  when Nodes::Cat
@@ -131,10 +134,6 @@ module ActionDispatch
131
134
  lastpos(n.left).each do |i|
132
135
  table[i] += firstpos(n.right)
133
136
  end
134
- when Nodes::Star
135
- lastpos(n).each do |i|
136
- table[i] += firstpos(n)
137
- end
138
137
  end
139
138
  end
140
139
  table
@@ -14,7 +14,7 @@ module ActionDispatch
14
14
  end
15
15
 
16
16
  class Simulator # :nodoc:
17
- INITIAL_STATE = [0].freeze
17
+ INITIAL_STATE = [ [0, nil] ].freeze
18
18
 
19
19
  attr_reader :tt
20
20
 
@@ -25,13 +25,19 @@ module ActionDispatch
25
25
  def memos(string)
26
26
  input = StringScanner.new(string)
27
27
  state = INITIAL_STATE
28
+ start_index = 0
28
29
 
29
30
  while sym = input.scan(%r([/.?]|[^/.?]+))
30
- state = tt.move(state, sym)
31
+ end_index = start_index + sym.length
32
+
33
+ state = tt.move(state, string, start_index, end_index)
34
+
35
+ start_index = end_index
31
36
  end
32
37
 
33
- acceptance_states = state.each_with_object([]) do |s, memos|
34
- memos.concat(tt.memo(s)) if tt.accepting?(s)
38
+ acceptance_states = state.each_with_object([]) do |s_d, memos|
39
+ s, idx = s_d
40
+ memos.concat(tt.memo(s)) if idx.nil? && tt.accepting?(s)
35
41
  end
36
42
 
37
43
  acceptance_states.empty? ? yield : acceptance_states