actionpack 7.2.2.1 → 8.0.1

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +123 -109
  3. data/lib/abstract_controller/rendering.rb +0 -1
  4. data/lib/action_controller/base.rb +1 -1
  5. data/lib/action_controller/form_builder.rb +3 -3
  6. data/lib/action_controller/metal/allow_browser.rb +11 -1
  7. data/lib/action_controller/metal/conditional_get.rb +5 -1
  8. data/lib/action_controller/metal/data_streaming.rb +4 -2
  9. data/lib/action_controller/metal/instrumentation.rb +1 -2
  10. data/lib/action_controller/metal/live.rb +13 -4
  11. data/lib/action_controller/metal/rate_limiting.rb +13 -4
  12. data/lib/action_controller/metal/redirecting.rb +2 -1
  13. data/lib/action_controller/metal/renderers.rb +2 -3
  14. data/lib/action_controller/metal/streaming.rb +5 -84
  15. data/lib/action_controller/metal/strong_parameters.rb +277 -89
  16. data/lib/action_controller/railtie.rb +1 -7
  17. data/lib/action_controller/test_case.rb +4 -2
  18. data/lib/action_dispatch/http/cache.rb +27 -10
  19. data/lib/action_dispatch/http/content_security_policy.rb +1 -0
  20. data/lib/action_dispatch/http/param_builder.rb +186 -0
  21. data/lib/action_dispatch/http/param_error.rb +26 -0
  22. data/lib/action_dispatch/http/permissions_policy.rb +2 -0
  23. data/lib/action_dispatch/http/query_parser.rb +53 -0
  24. data/lib/action_dispatch/http/request.rb +60 -16
  25. data/lib/action_dispatch/journey/parser.rb +99 -196
  26. data/lib/action_dispatch/journey/scanner.rb +44 -42
  27. data/lib/action_dispatch/middleware/cookies.rb +4 -2
  28. data/lib/action_dispatch/middleware/debug_exceptions.rb +16 -3
  29. data/lib/action_dispatch/middleware/debug_view.rb +0 -5
  30. data/lib/action_dispatch/middleware/exception_wrapper.rb +0 -6
  31. data/lib/action_dispatch/middleware/request_id.rb +2 -1
  32. data/lib/action_dispatch/middleware/ssl.rb +13 -3
  33. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +0 -3
  34. data/lib/action_dispatch/railtie.rb +8 -0
  35. data/lib/action_dispatch/request/session.rb +1 -0
  36. data/lib/action_dispatch/request/utils.rb +9 -3
  37. data/lib/action_dispatch/routing/inspector.rb +1 -1
  38. data/lib/action_dispatch/routing/mapper.rb +90 -62
  39. data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -2
  40. data/lib/action_dispatch/routing/route_set.rb +20 -8
  41. data/lib/action_dispatch/system_testing/browser.rb +12 -21
  42. data/lib/action_dispatch/testing/assertions/response.rb +12 -2
  43. data/lib/action_dispatch/testing/assertions/routing.rb +4 -4
  44. data/lib/action_dispatch/testing/integration.rb +11 -1
  45. data/lib/action_dispatch/testing/test_process.rb +1 -2
  46. data/lib/action_dispatch.rb +6 -4
  47. data/lib/action_pack/gem_version.rb +4 -4
  48. metadata +15 -34
  49. data/lib/action_dispatch/journey/parser.y +0 -50
  50. data/lib/action_dispatch/journey/parser_extras.rb +0 -33
@@ -375,35 +375,18 @@ module ActionDispatch
375
375
  Routing::RouteSet::Dispatcher.new raise_on_name_error
376
376
  end
377
377
 
378
- if Thread.respond_to?(:each_caller_location)
379
- def route_source_location
380
- if Mapper.route_source_locations
381
- action_dispatch_dir = File.expand_path("..", __dir__)
382
- Thread.each_caller_location do |location|
383
- next if location.path.start_with?(action_dispatch_dir)
378
+ def route_source_location
379
+ if Mapper.route_source_locations
380
+ action_dispatch_dir = File.expand_path("..", __dir__)
381
+ Thread.each_caller_location do |location|
382
+ next if location.path.start_with?(action_dispatch_dir)
384
383
 
385
- cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path)
386
- next if cleaned_path.nil?
384
+ cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path)
385
+ next if cleaned_path.nil?
387
386
 
388
- return "#{cleaned_path}:#{location.lineno}"
389
- end
390
- nil
391
- end
392
- end
393
- else
394
- def route_source_location
395
- if Mapper.route_source_locations
396
- action_dispatch_dir = File.expand_path("..", __dir__)
397
- caller_locations.each do |location|
398
- next if location.path.start_with?(action_dispatch_dir)
399
-
400
- cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path)
401
- next if cleaned_path.nil?
402
-
403
- return "#{cleaned_path}:#{location.lineno}"
404
- end
405
- nil
387
+ return "#{cleaned_path}:#{location.lineno}"
406
388
  end
389
+ nil
407
390
  end
408
391
  end
409
392
  end
@@ -470,7 +453,6 @@ module ActionDispatch
470
453
  # When a pattern points to an internal route, the route's `:action` and
471
454
  # `:controller` should be set in options or hash shorthand. Examples:
472
455
  #
473
- # match 'photos/:id' => 'photos#show', via: :get
474
456
  # match 'photos/:id', to: 'photos#show', via: :get
475
457
  # match 'photos/:id', controller: 'photos', action: 'show', via: :get
476
458
  #
@@ -614,10 +596,6 @@ module ActionDispatch
614
596
  #
615
597
  # mount SomeRackApp, at: "some_route"
616
598
  #
617
- # Alternatively:
618
- #
619
- # mount(SomeRackApp => "some_route")
620
- #
621
599
  # For options, see `match`, as `mount` uses it internally.
622
600
  #
623
601
  # All mounted applications come with routing helpers to access them. These are
@@ -625,7 +603,7 @@ module ActionDispatch
625
603
  # `some_rack_app_path` or `some_rack_app_url`. To customize this helper's name,
626
604
  # use the `:as` option:
627
605
  #
628
- # mount(SomeRackApp => "some_route", as: "exciting")
606
+ # mount(SomeRackApp, at: "some_route", as: "exciting")
629
607
  #
630
608
  # This will generate the `exciting_path` and `exciting_url` helpers which can be
631
609
  # used to navigate to this mounted app.
@@ -773,6 +751,16 @@ module ActionDispatch
773
751
  map_method(:options, args, &block)
774
752
  end
775
753
 
754
+ # Define a route that recognizes HTTP CONNECT (and GET) requests. More
755
+ # specifically this recognizes HTTP/1 protocol upgrade requests and HTTP/2
756
+ # CONNECT requests with the protocol pseudo header. For supported arguments,
757
+ # see [match](rdoc-ref:Base#match)
758
+ #
759
+ # connect 'live', to: 'live#index'
760
+ def connect(*args, &block)
761
+ map_method([:get, :connect], args, &block)
762
+ end
763
+
776
764
  private
777
765
  def map_method(method, args, &block)
778
766
  options = args.extract_options!
@@ -1174,6 +1162,16 @@ module ActionDispatch
1174
1162
  CANONICAL_ACTIONS = %w(index create new show update destroy)
1175
1163
 
1176
1164
  class Resource # :nodoc:
1165
+ class << self
1166
+ def default_actions(api_only)
1167
+ if api_only
1168
+ [:index, :create, :show, :update, :destroy]
1169
+ else
1170
+ [:index, :create, :new, :show, :update, :destroy, :edit]
1171
+ end
1172
+ end
1173
+ end
1174
+
1177
1175
  attr_reader :controller, :path, :param
1178
1176
 
1179
1177
  def initialize(entities, api_only, shallow, options = {})
@@ -1181,6 +1179,11 @@ module ActionDispatch
1181
1179
  raise ArgumentError, ":param option can't contain colons"
1182
1180
  end
1183
1181
 
1182
+ valid_actions = self.class.default_actions(false) # ignore api_only for this validation
1183
+ if invalid_actions = invalid_only_except_options(options, valid_actions).presence
1184
+ raise ArgumentError, ":only and :except must include only #{valid_actions}, but also included #{invalid_actions}"
1185
+ end
1186
+
1184
1187
  @name = entities.to_s
1185
1188
  @path = (options[:path] || @name).to_s
1186
1189
  @controller = (options[:controller] || @name).to_s
@@ -1194,11 +1197,7 @@ module ActionDispatch
1194
1197
  end
1195
1198
 
1196
1199
  def default_actions
1197
- if @api_only
1198
- [:index, :create, :show, :update, :destroy]
1199
- else
1200
- [:index, :create, :new, :show, :update, :destroy, :edit]
1201
- end
1200
+ self.class.default_actions(@api_only)
1202
1201
  end
1203
1202
 
1204
1203
  def actions
@@ -1266,9 +1265,24 @@ module ActionDispatch
1266
1265
  end
1267
1266
 
1268
1267
  def singleton?; false; end
1268
+
1269
+ private
1270
+ def invalid_only_except_options(options, valid_actions)
1271
+ options.values_at(:only, :except).flatten.compact.uniq.map(&:to_sym) - valid_actions
1272
+ end
1269
1273
  end
1270
1274
 
1271
1275
  class SingletonResource < Resource # :nodoc:
1276
+ class << self
1277
+ def default_actions(api_only)
1278
+ if api_only
1279
+ [:show, :create, :update, :destroy]
1280
+ else
1281
+ [:show, :create, :update, :destroy, :new, :edit]
1282
+ end
1283
+ end
1284
+ end
1285
+
1272
1286
  def initialize(entities, api_only, shallow, options)
1273
1287
  super
1274
1288
  @as = nil
@@ -1277,11 +1291,7 @@ module ActionDispatch
1277
1291
  end
1278
1292
 
1279
1293
  def default_actions
1280
- if @api_only
1281
- [:show, :create, :update, :destroy]
1282
- else
1283
- [:show, :create, :update, :destroy, :new, :edit]
1284
- end
1294
+ self.class.default_actions(@api_only)
1285
1295
  end
1286
1296
 
1287
1297
  def plural
@@ -1342,7 +1352,7 @@ module ActionDispatch
1342
1352
  end
1343
1353
 
1344
1354
  with_scope_level(:resource) do
1345
- options = apply_action_options options
1355
+ options = apply_action_options :resource, options
1346
1356
  resource_scope(SingletonResource.new(resources.pop, api_only?, @scope[:shallow], options)) do
1347
1357
  yield if block_given?
1348
1358
 
@@ -1512,7 +1522,7 @@ module ActionDispatch
1512
1522
  end
1513
1523
 
1514
1524
  with_scope_level(:resources) do
1515
- options = apply_action_options options
1525
+ options = apply_action_options :resources, options
1516
1526
  resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], options)) do
1517
1527
  yield if block_given?
1518
1528
 
@@ -1673,7 +1683,6 @@ module ActionDispatch
1673
1683
  # Matches a URL pattern to one or more routes. For more information, see
1674
1684
  # [match](rdoc-ref:Base#match).
1675
1685
  #
1676
- # match 'path' => 'controller#action', via: :patch
1677
1686
  # match 'path', to: 'controller#action', via: :post
1678
1687
  # match 'path', 'otherpath', on: :member, via: :get
1679
1688
  def match(path, *rest, &block)
@@ -1782,17 +1791,32 @@ module ActionDispatch
1782
1791
  false
1783
1792
  end
1784
1793
 
1785
- def apply_action_options(options)
1794
+ def apply_action_options(method, options)
1786
1795
  return options if action_options? options
1787
- options.merge scope_action_options
1796
+ options.merge scope_action_options(method)
1788
1797
  end
1789
1798
 
1790
1799
  def action_options?(options)
1791
1800
  options[:only] || options[:except]
1792
1801
  end
1793
1802
 
1794
- def scope_action_options
1795
- @scope[:action_options] || {}
1803
+ def scope_action_options(method)
1804
+ return {} unless @scope[:action_options]
1805
+
1806
+ actions = applicable_actions_for(method)
1807
+ @scope[:action_options].dup.tap do |options|
1808
+ (options[:only] = Array(options[:only]) & actions) if options[:only]
1809
+ (options[:except] = Array(options[:except]) & actions) if options[:except]
1810
+ end
1811
+ end
1812
+
1813
+ def applicable_actions_for(method)
1814
+ case method
1815
+ when :resource
1816
+ SingletonResource.default_actions(api_only?)
1817
+ when :resources
1818
+ Resource.default_actions(api_only?)
1819
+ end
1796
1820
  end
1797
1821
 
1798
1822
  def resource_scope?
@@ -1935,6 +1959,11 @@ module ActionDispatch
1935
1959
  end
1936
1960
 
1937
1961
  def map_match(paths, options)
1962
+ ActionDispatch.deprecator.warn(<<-MSG.squish) if paths.count > 1
1963
+ Mapping a route with multiple paths is deprecated and
1964
+ will be removed in Rails 8.1. Please use multiple method calls instead.
1965
+ MSG
1966
+
1938
1967
  if (on = options[:on]) && !VALID_ON_OPTIONS.include?(on)
1939
1968
  raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
1940
1969
  end
@@ -2025,7 +2054,7 @@ module ActionDispatch
2025
2054
  name_for_action(options.delete(:as), action)
2026
2055
  end
2027
2056
 
2028
- path = Mapping.normalize_path RFC2396_PARSER.escape(path), formatted
2057
+ path = Mapping.normalize_path URI::RFC2396_PARSER.escape(path), formatted
2029
2058
  ast = Journey::Parser.parse path
2030
2059
 
2031
2060
  mapping = Mapping.build(@scope, @set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
@@ -2200,8 +2229,8 @@ module ActionDispatch
2200
2229
  end
2201
2230
 
2202
2231
  # Define custom polymorphic mappings of models to URLs. This alters the behavior
2203
- # of `polymorphic_url` and consequently the behavior of `link_to` and `form_for`
2204
- # when passed a model instance, e.g:
2232
+ # of `polymorphic_url` and consequently the behavior of `link_to`, `form_with`
2233
+ # and `form_for` when passed a model instance, e.g:
2205
2234
  #
2206
2235
  # resource :basket
2207
2236
  #
@@ -2210,7 +2239,7 @@ module ActionDispatch
2210
2239
  # end
2211
2240
  #
2212
2241
  # This will now generate "/basket" when a `Basket` instance is passed to
2213
- # `link_to` or `form_for` instead of the standard "/baskets/:id".
2242
+ # `link_to`, `form_with` or `form_for` instead of the standard "/baskets/:id".
2214
2243
  #
2215
2244
  # NOTE: This custom behavior only applies to simple polymorphic URLs where a
2216
2245
  # single model instance is passed and not more complicated forms, e.g:
@@ -2267,9 +2296,9 @@ module ActionDispatch
2267
2296
 
2268
2297
  attr_reader :parent, :scope_level
2269
2298
 
2270
- def initialize(hash, parent = NULL, scope_level = nil)
2271
- @hash = hash
2299
+ def initialize(hash, parent = ROOT, scope_level = nil)
2272
2300
  @parent = parent
2301
+ @hash = parent ? parent.frame.merge(hash) : hash
2273
2302
  @scope_level = scope_level
2274
2303
  end
2275
2304
 
@@ -2282,7 +2311,7 @@ module ActionDispatch
2282
2311
  end
2283
2312
 
2284
2313
  def root?
2285
- @parent.null?
2314
+ @parent == ROOT
2286
2315
  end
2287
2316
 
2288
2317
  def resources?
@@ -2327,23 +2356,22 @@ module ActionDispatch
2327
2356
  end
2328
2357
 
2329
2358
  def [](key)
2330
- scope = find { |node| node.frame.key? key }
2331
- scope && scope.frame[key]
2359
+ frame[key]
2332
2360
  end
2333
2361
 
2362
+ def frame; @hash; end
2363
+
2334
2364
  include Enumerable
2335
2365
 
2336
2366
  def each
2337
2367
  node = self
2338
- until node.equal? NULL
2368
+ until node.equal? ROOT
2339
2369
  yield node
2340
2370
  node = node.parent
2341
2371
  end
2342
2372
  end
2343
2373
 
2344
- def frame; @hash; end
2345
-
2346
- NULL = Scope.new(nil, nil)
2374
+ ROOT = Scope.new({}, nil)
2347
2375
  end
2348
2376
 
2349
2377
  def initialize(set) # :nodoc:
@@ -31,7 +31,7 @@ module ActionDispatch
31
31
  # * `url_for`, so you can use it with a record as the argument, e.g.
32
32
  # `url_for(@article)`;
33
33
  # * ActionView::Helpers::FormHelper uses `polymorphic_path`, so you can write
34
- # `form_for(@article)` without having to specify `:url` parameter for the
34
+ # `form_with(model: @article)` without having to specify `:url` parameter for the
35
35
  # form action;
36
36
  # * `redirect_to` (which, in fact, uses `url_for`) so you can write
37
37
  # `redirect_to(post)` in your controllers;
@@ -61,7 +61,7 @@ module ActionDispatch
61
61
  # argument to the method. For example:
62
62
  #
63
63
  # polymorphic_url([blog, @post]) # calls blog.post_path(@post)
64
- # form_for([blog, @post]) # => "/blog/posts/1"
64
+ # form_with(model: [blog, @post]) # => "/blog/posts/1"
65
65
  #
66
66
  module PolymorphicRoutes
67
67
  # Constructs a call to a named RESTful route for the given record and returns
@@ -351,7 +351,7 @@ module ActionDispatch
351
351
  PATH = ->(options) { ActionDispatch::Http::URL.path_for(options) }
352
352
  UNKNOWN = ->(options) { ActionDispatch::Http::URL.url_for(options) }
353
353
 
354
- attr_accessor :formatter, :set, :named_routes, :default_scope, :router
354
+ attr_accessor :formatter, :set, :named_routes, :router
355
355
  attr_accessor :disable_clear_and_finalize, :resources_path_names
356
356
  attr_accessor :default_url_options, :draw_paths
357
357
  attr_reader :env_key, :polymorphic_mappings
@@ -363,7 +363,7 @@ module ActionDispatch
363
363
  end
364
364
 
365
365
  def self.new_with_config(config)
366
- route_set_config = DEFAULT_CONFIG
366
+ route_set_config = DEFAULT_CONFIG.dup
367
367
 
368
368
  # engines apparently don't have this set
369
369
  if config.respond_to? :relative_url_root
@@ -374,14 +374,18 @@ module ActionDispatch
374
374
  route_set_config.api_only = config.api_only
375
375
  end
376
376
 
377
+ if config.respond_to? :default_scope
378
+ route_set_config.default_scope = config.default_scope
379
+ end
380
+
377
381
  new route_set_config
378
382
  end
379
383
 
380
- Config = Struct.new :relative_url_root, :api_only
384
+ Config = Struct.new :relative_url_root, :api_only, :default_scope
381
385
 
382
- DEFAULT_CONFIG = Config.new(nil, false)
386
+ DEFAULT_CONFIG = Config.new(nil, false, nil)
383
387
 
384
- def initialize(config = DEFAULT_CONFIG)
388
+ def initialize(config = DEFAULT_CONFIG.dup)
385
389
  self.named_routes = NamedRouteCollection.new
386
390
  self.resources_path_names = self.class.default_resources_path_names
387
391
  self.default_url_options = {}
@@ -416,6 +420,14 @@ module ActionDispatch
416
420
  @config.api_only
417
421
  end
418
422
 
423
+ def default_scope
424
+ @config.default_scope
425
+ end
426
+
427
+ def default_scope=(new_default_scope)
428
+ @config.default_scope = new_default_scope
429
+ end
430
+
419
431
  def request_class
420
432
  ActionDispatch::Request
421
433
  end
@@ -647,14 +659,14 @@ module ActionDispatch
647
659
  if route.segment_keys.include?(:controller)
648
660
  ActionDispatch.deprecator.warn(<<-MSG.squish)
649
661
  Using a dynamic :controller segment in a route is deprecated and
650
- will be removed in Rails 7.2.
662
+ will be removed in Rails 8.1.
651
663
  MSG
652
664
  end
653
665
 
654
666
  if route.segment_keys.include?(:action)
655
667
  ActionDispatch.deprecator.warn(<<-MSG.squish)
656
668
  Using a dynamic :action segment in a route is deprecated and
657
- will be removed in Rails 7.2.
669
+ will be removed in Rails 8.1.
658
670
  MSG
659
671
  end
660
672
 
@@ -917,7 +929,7 @@ module ActionDispatch
917
929
  params.each do |key, value|
918
930
  if value.is_a?(String)
919
931
  value = value.dup.force_encoding(Encoding::BINARY)
920
- params[key] = RFC2396_PARSER.unescape(value)
932
+ params[key] = URI::RFC2396_PARSER.unescape(value)
921
933
  end
922
934
  end
923
935
  req.path_parameters = params
@@ -9,7 +9,6 @@ module ActionDispatch
9
9
 
10
10
  def initialize(name)
11
11
  @name = name
12
- set_default_options
13
12
  end
14
13
 
15
14
  def type
@@ -27,9 +26,9 @@ module ActionDispatch
27
26
  @options ||=
28
27
  case type
29
28
  when :chrome
30
- ::Selenium::WebDriver::Chrome::Options.new
29
+ default_chrome_options
31
30
  when :firefox
32
- ::Selenium::WebDriver::Firefox::Options.new
31
+ default_firefox_options
33
32
  end
34
33
  end
35
34
 
@@ -49,26 +48,18 @@ module ActionDispatch
49
48
  end
50
49
 
51
50
  private
52
- def set_default_options
53
- case name
54
- when :headless_chrome
55
- set_headless_chrome_browser_options
56
- when :headless_firefox
57
- set_headless_firefox_browser_options
58
- end
51
+ def default_chrome_options
52
+ options = ::Selenium::WebDriver::Chrome::Options.new
53
+ options.add_argument("--disable-search-engine-choice-screen")
54
+ options.add_argument("--headless") if name == :headless_chrome
55
+ options.add_argument("--disable-gpu") if Gem.win_platform?
56
+ options
59
57
  end
60
58
 
61
- def set_headless_chrome_browser_options
62
- configure do |capabilities|
63
- capabilities.add_argument("--headless")
64
- capabilities.add_argument("--disable-gpu") if Gem.win_platform?
65
- end
66
- end
67
-
68
- def set_headless_firefox_browser_options
69
- configure do |capabilities|
70
- capabilities.add_argument("-headless")
71
- end
59
+ def default_firefox_options
60
+ options = ::Selenium::WebDriver::Firefox::Options.new
61
+ options.add_argument("-headless") if name == :headless_firefox
62
+ options
72
63
  end
73
64
 
74
65
  def resolve_driver_path(namespace)
@@ -87,8 +87,13 @@ module ActionDispatch
87
87
  end
88
88
 
89
89
  def generate_response_message(expected, actual = @response.response_code)
90
- (+"Expected response to be a <#{code_with_name(expected)}>,"\
91
- " but was a <#{code_with_name(actual)}>").concat(location_if_redirected).concat(response_body_if_short)
90
+ lambda do
91
+ (+"Expected response to be a <#{code_with_name(expected)}>,"\
92
+ " but was a <#{code_with_name(actual)}>").
93
+ concat(location_if_redirected).
94
+ concat(exception_if_present).
95
+ concat(response_body_if_short)
96
+ end
92
97
  end
93
98
 
94
99
  def response_body_if_short
@@ -96,6 +101,11 @@ module ActionDispatch
96
101
  "\nResponse body: #{@response.body}"
97
102
  end
98
103
 
104
+ def exception_if_present
105
+ return "" unless ex = @request&.env&.[]("action_dispatch.exception")
106
+ "\n\nException while processing request: #{Minitest::UnexpectedError.new(ex).message}\n"
107
+ end
108
+
99
109
  def location_if_redirected
100
110
  return "" unless @response.redirection? && @response.location.present?
101
111
  location = normalize_argument_to_redirection(@response.location)
@@ -118,9 +118,9 @@ module ActionDispatch
118
118
  # assert_equal "/users", users_path
119
119
  # end
120
120
  #
121
- def with_routing(&block)
121
+ def with_routing(config = nil, &block)
122
122
  old_routes, old_controller = @routes, @controller
123
- create_routes(&block)
123
+ create_routes(config, &block)
124
124
  ensure
125
125
  reset_routes(old_routes, old_controller)
126
126
  end
@@ -267,8 +267,8 @@ module ActionDispatch
267
267
  end
268
268
 
269
269
  private
270
- def create_routes
271
- @routes = ActionDispatch::Routing::RouteSet.new
270
+ def create_routes(config = nil)
271
+ @routes = ActionDispatch::Routing::RouteSet.new(config || ActionDispatch::Routing::RouteSet::DEFAULT_CONFIG)
272
272
  if @controller
273
273
  @controller = @controller.clone
274
274
  _routes = @routes
@@ -284,7 +284,17 @@ module ActionDispatch
284
284
 
285
285
  # NOTE: rack-test v0.5 doesn't build a default uri correctly Make sure requested
286
286
  # path is always a full URI.
287
- session.request(build_full_uri(path, request_env), request_env)
287
+ uri = build_full_uri(path, request_env)
288
+
289
+ if method == :get && String === request_env[:params]
290
+ # rack-test will needlessly parse and rebuild a :params
291
+ # querystring, using Rack's query parser. At best that's a
292
+ # waste of time; at worst it can change the value.
293
+
294
+ uri << "?" << request_env.delete(:params)
295
+ end
296
+
297
+ session.request(uri, request_env)
288
298
 
289
299
  @request_count += 1
290
300
  @request = ActionDispatch::Request.new(session.last_request.env)
@@ -9,8 +9,7 @@ module ActionDispatch
9
9
  module TestProcess
10
10
  module FixtureFile
11
11
  # Shortcut for
12
- # `Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.file_f
13
- # ixture_path, path), type)`:
12
+ # `Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.file_fixture_path, path), type)`:
14
13
  #
15
14
  # post :change_avatar, params: { avatar: file_fixture_upload('david.png', 'image/png') }
16
15
  #
@@ -30,7 +30,6 @@ require "active_support/core_ext/module/attribute_accessors"
30
30
 
31
31
  require "action_pack"
32
32
  require "rack"
33
- require "uri"
34
33
  require "action_dispatch/deprecator"
35
34
 
36
35
  module Rack # :nodoc:
@@ -48,16 +47,19 @@ end
48
47
  module ActionDispatch
49
48
  extend ActiveSupport::Autoload
50
49
 
51
- RFC2396_PARSER = defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::RFC2396_Parser.new
52
- private_constant :RFC2396_PARSER
53
-
54
50
  class MissingController < NameError
55
51
  end
56
52
 
57
53
  eager_autoload do
58
54
  autoload_under "http" do
59
55
  autoload :ContentSecurityPolicy
56
+ autoload :InvalidParameterError, "action_dispatch/http/param_error"
57
+ autoload :ParamBuilder
58
+ autoload :ParamError
59
+ autoload :ParameterTypeError, "action_dispatch/http/param_error"
60
+ autoload :ParamsTooDeepError, "action_dispatch/http/param_error"
60
61
  autoload :PermissionsPolicy
62
+ autoload :QueryParser
61
63
  autoload :Request
62
64
  autoload :Response
63
65
  end
@@ -9,10 +9,10 @@ module ActionPack
9
9
  end
10
10
 
11
11
  module VERSION
12
- MAJOR = 7
13
- MINOR = 2
14
- TINY = 2
15
- PRE = "1"
12
+ MAJOR = 8
13
+ MINOR = 0
14
+ TINY = 1
15
+ PRE = nil
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
18
18
  end