actionpack 6.1.7.5 → 7.0.8

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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +319 -401
  3. data/MIT-LICENSE +1 -0
  4. data/README.rdoc +4 -5
  5. data/lib/abstract_controller/asset_paths.rb +1 -1
  6. data/lib/abstract_controller/base.rb +13 -26
  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 +2 -2
  11. data/lib/abstract_controller/error.rb +1 -1
  12. data/lib/abstract_controller/helpers.rb +17 -12
  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/rendering.rb +9 -11
  16. data/lib/abstract_controller/translation.rb +5 -4
  17. data/lib/abstract_controller/url_for.rb +4 -6
  18. data/lib/action_controller/api.rb +7 -7
  19. data/lib/action_controller/base.rb +5 -4
  20. data/lib/action_controller/form_builder.rb +2 -2
  21. data/lib/action_controller/log_subscriber.rb +4 -3
  22. data/lib/action_controller/metal/basic_implicit_render.rb +3 -1
  23. data/lib/action_controller/metal/conditional_get.rb +137 -102
  24. data/lib/action_controller/metal/content_security_policy.rb +36 -2
  25. data/lib/action_controller/metal/cookies.rb +1 -1
  26. data/lib/action_controller/metal/data_streaming.rb +23 -31
  27. data/lib/action_controller/metal/etag_with_flash.rb +1 -1
  28. data/lib/action_controller/metal/exceptions.rb +19 -30
  29. data/lib/action_controller/metal/flash.rb +6 -2
  30. data/lib/action_controller/metal/head.rb +1 -1
  31. data/lib/action_controller/metal/helpers.rb +2 -2
  32. data/lib/action_controller/metal/http_authentication.rb +66 -39
  33. data/lib/action_controller/metal/instrumentation.rb +57 -52
  34. data/lib/action_controller/metal/live.rb +43 -2
  35. data/lib/action_controller/metal/mime_responds.rb +3 -3
  36. data/lib/action_controller/metal/params_wrapper.rb +20 -11
  37. data/lib/action_controller/metal/permissions_policy.rb +19 -28
  38. data/lib/action_controller/metal/redirecting.rb +95 -22
  39. data/lib/action_controller/metal/renderers.rb +12 -13
  40. data/lib/action_controller/metal/rendering.rb +121 -9
  41. data/lib/action_controller/metal/request_forgery_protection.rb +83 -32
  42. data/lib/action_controller/metal/rescue.rb +5 -4
  43. data/lib/action_controller/metal/streaming.rb +7 -9
  44. data/lib/action_controller/metal/strong_parameters.rb +138 -115
  45. data/lib/action_controller/metal/testing.rb +9 -2
  46. data/lib/action_controller/metal/url_for.rb +3 -5
  47. data/lib/action_controller/metal.rb +10 -13
  48. data/lib/action_controller/railtie.rb +50 -6
  49. data/lib/action_controller/renderer.rb +1 -20
  50. data/lib/action_controller/test_case.rb +28 -7
  51. data/lib/action_controller.rb +2 -5
  52. data/lib/action_dispatch/http/cache.rb +20 -13
  53. data/lib/action_dispatch/http/content_security_policy.rb +113 -36
  54. data/lib/action_dispatch/http/filter_parameters.rb +4 -19
  55. data/lib/action_dispatch/http/headers.rb +1 -1
  56. data/lib/action_dispatch/http/mime_negotiation.rb +15 -5
  57. data/lib/action_dispatch/http/mime_type.rb +9 -11
  58. data/lib/action_dispatch/http/parameters.rb +5 -5
  59. data/lib/action_dispatch/http/permissions_policy.rb +17 -1
  60. data/lib/action_dispatch/http/request.rb +27 -37
  61. data/lib/action_dispatch/http/response.rb +3 -20
  62. data/lib/action_dispatch/http/upload.rb +13 -2
  63. data/lib/action_dispatch/http/url.rb +11 -19
  64. data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
  65. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
  66. data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
  67. data/lib/action_dispatch/journey/nodes/node.rb +70 -5
  68. data/lib/action_dispatch/journey/path/pattern.rb +22 -13
  69. data/lib/action_dispatch/journey/route.rb +6 -13
  70. data/lib/action_dispatch/journey/router/utils.rb +2 -2
  71. data/lib/action_dispatch/journey/router.rb +1 -1
  72. data/lib/action_dispatch/journey/routes.rb +3 -3
  73. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  74. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  75. data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
  76. data/lib/action_dispatch/middleware/cookies.rb +20 -13
  77. data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
  78. data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
  79. data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
  80. data/lib/action_dispatch/middleware/executor.rb +3 -0
  81. data/lib/action_dispatch/middleware/flash.rb +17 -18
  82. data/lib/action_dispatch/middleware/host_authorization.rb +13 -17
  83. data/lib/action_dispatch/middleware/remote_ip.rb +20 -8
  84. data/lib/action_dispatch/middleware/request_id.rb +3 -3
  85. data/lib/action_dispatch/middleware/server_timing.rb +76 -0
  86. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
  87. data/lib/action_dispatch/middleware/session/cookie_store.rb +9 -9
  88. data/lib/action_dispatch/middleware/show_exceptions.rb +17 -16
  89. data/lib/action_dispatch/middleware/stack.rb +27 -9
  90. data/lib/action_dispatch/middleware/static.rb +5 -9
  91. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
  92. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
  93. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
  94. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +10 -5
  95. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +7 -3
  96. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
  97. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
  98. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
  99. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
  100. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
  101. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  102. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  103. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
  104. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +22 -22
  105. data/lib/action_dispatch/railtie.rb +8 -2
  106. data/lib/action_dispatch/request/session.rb +43 -13
  107. data/lib/action_dispatch/routing/inspector.rb +1 -1
  108. data/lib/action_dispatch/routing/mapper.rb +82 -83
  109. data/lib/action_dispatch/routing/redirection.rb +5 -2
  110. data/lib/action_dispatch/routing/route_set.rb +17 -7
  111. data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
  112. data/lib/action_dispatch/routing/url_for.rb +24 -25
  113. data/lib/action_dispatch/routing.rb +5 -6
  114. data/lib/action_dispatch/system_test_case.rb +5 -5
  115. data/lib/action_dispatch/system_testing/browser.rb +3 -13
  116. data/lib/action_dispatch/system_testing/driver.rb +34 -10
  117. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +11 -7
  118. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
  119. data/lib/action_dispatch/testing/assertions/response.rb +1 -1
  120. data/lib/action_dispatch/testing/assertions/routing.rb +3 -2
  121. data/lib/action_dispatch/testing/assertions.rb +2 -5
  122. data/lib/action_dispatch/testing/integration.rb +6 -8
  123. data/lib/action_dispatch/testing/test_process.rb +3 -29
  124. data/lib/action_dispatch/testing/test_response.rb +20 -2
  125. data/lib/action_dispatch.rb +1 -0
  126. data/lib/action_pack/gem_version.rb +5 -5
  127. data/lib/action_pack/version.rb +1 -1
  128. metadata +16 -15
@@ -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."
@@ -122,8 +132,8 @@ module ActionDispatch
122
132
  # Sets the \formats by string extensions. This differs from #format= by allowing you
123
133
  # to set multiple, ordered formats, which is useful when you want to have a fallback.
124
134
  #
125
- # In this example, the :iphone format will be used if it's available, otherwise it'll fallback
126
- # to the :html format.
135
+ # In this example, the +:iphone+ format will be used if it's available, otherwise it'll fallback
136
+ # to the +:html+ format.
127
137
  #
128
138
  # class ApplicationController < ActionController::Base
129
139
  # before_action :adjust_format_for_iphone_with_html_fallback
@@ -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])
@@ -78,7 +78,7 @@ module ActionDispatch
78
78
  # Returns a hash with the \parameters used to form the \path of the request.
79
79
  # Returned hash keys are strings:
80
80
  #
81
- # {'action' => 'my_action', 'controller' => 'my_controller'}
81
+ # { action: "my_action", controller: "my_controller" }
82
82
  def path_parameters
83
83
  get_header(PARAMETERS_KEY) || set_header(PARAMETERS_KEY, {})
84
84
  end
@@ -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,23 @@
2
2
 
3
3
  require "active_support/core_ext/object/deep_dup"
4
4
 
5
- module ActionDispatch #:nodoc:
5
+ module ActionDispatch # :nodoc:
6
+ # Configures the HTTP
7
+ # {Feature-Policy}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy]
8
+ # response header to specify which browser features the current document and
9
+ # its iframes can use.
10
+ #
11
+ # Example global policy:
12
+ #
13
+ # Rails.application.config.permissions_policy do |policy|
14
+ # policy.camera :none
15
+ # policy.gyroscope :none
16
+ # policy.microphone :none
17
+ # policy.usb :none
18
+ # policy.fullscreen :self
19
+ # policy.payment :self, "https://secure.example.com"
20
+ # end
21
+ #
6
22
  class PermissionsPolicy
7
23
  class Middleware
8
24
  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)
@@ -110,22 +107,21 @@ module ActionDispatch
110
107
  has_header? key
111
108
  end
112
109
 
113
- # List of HTTP request methods from the following RFCs:
114
- # Hypertext Transfer Protocol -- HTTP/1.1 (https://www.ietf.org/rfc/rfc2616.txt)
115
- # HTTP Extensions for Distributed Authoring -- WEBDAV (https://www.ietf.org/rfc/rfc2518.txt)
116
- # Versioning Extensions to WebDAV (https://www.ietf.org/rfc/rfc3253.txt)
117
- # Ordered Collections Protocol (WebDAV) (https://www.ietf.org/rfc/rfc3648.txt)
118
- # Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol (https://www.ietf.org/rfc/rfc3744.txt)
119
- # Web Distributed Authoring and Versioning (WebDAV) SEARCH (https://www.ietf.org/rfc/rfc5323.txt)
120
- # Calendar Extensions to WebDAV (https://www.ietf.org/rfc/rfc4791.txt)
121
- # PATCH Method for HTTP (https://www.ietf.org/rfc/rfc5789.txt)
110
+ # HTTP methods from {RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1}[https://www.ietf.org/rfc/rfc2616.txt]
122
111
  RFC2616 = %w(OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT)
112
+ # HTTP methods from {RFC 2518: HTTP Extensions for Distributed Authoring -- WEBDAV}[https://www.ietf.org/rfc/rfc2518.txt]
123
113
  RFC2518 = %w(PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK)
114
+ # HTTP methods from {RFC 3253: Versioning Extensions to WebDAV}[https://www.ietf.org/rfc/rfc3253.txt]
124
115
  RFC3253 = %w(VERSION-CONTROL REPORT CHECKOUT CHECKIN UNCHECKOUT MKWORKSPACE UPDATE LABEL MERGE BASELINE-CONTROL MKACTIVITY)
116
+ # HTTP methods from {RFC 3648: WebDAV Ordered Collections Protocol}[https://www.ietf.org/rfc/rfc3648.txt]
125
117
  RFC3648 = %w(ORDERPATCH)
118
+ # HTTP methods from {RFC 3744: WebDAV Access Control Protocol}[https://www.ietf.org/rfc/rfc3744.txt]
126
119
  RFC3744 = %w(ACL)
120
+ # HTTP methods from {RFC 5323: WebDAV SEARCH}[https://www.ietf.org/rfc/rfc5323.txt]
127
121
  RFC5323 = %w(SEARCH)
122
+ # HTTP methods from {RFC 4791: Calendaring Extensions to WebDAV}[https://www.ietf.org/rfc/rfc4791.txt]
128
123
  RFC4791 = %w(MKCALENDAR)
124
+ # HTTP methods from {RFC 5789: PATCH Method for HTTP}[https://www.ietf.org/rfc/rfc5789.txt]
129
125
  RFC5789 = %w(PATCH)
130
126
 
131
127
  HTTP_METHODS = RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC4791 + RFC5789
@@ -165,7 +161,7 @@ module ActionDispatch
165
161
  set_header(routes.env_key, name.dup)
166
162
  end
167
163
 
168
- def request_method=(request_method) #:nodoc:
164
+ def request_method=(request_method) # :nodoc:
169
165
  if check_method(request_method)
170
166
  @request_method = set_header("REQUEST_METHOD", request_method)
171
167
  end
@@ -266,7 +262,7 @@ module ActionDispatch
266
262
  # # get "/articles"
267
263
  # request.media_type # => "application/x-www-form-urlencoded"
268
264
  def media_type
269
- content_mime_type.to_s
265
+ content_mime_type&.to_s
270
266
  end
271
267
 
272
268
  # Returns the content length of the request as an integer.
@@ -274,7 +270,7 @@ module ActionDispatch
274
270
  super.to_i
275
271
  end
276
272
 
277
- # Returns true if the "X-Requested-With" header contains "XMLHttpRequest"
273
+ # Returns true if the +X-Requested-With+ header contains "XMLHttpRequest"
278
274
  # (case-insensitive), which may need to be manually added depending on the
279
275
  # choice of JavaScript libraries and frameworks.
280
276
  def xml_http_request?
@@ -300,9 +296,9 @@ module ActionDispatch
300
296
 
301
297
  ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc:
302
298
 
303
- # Returns the unique request id, which is based on either the X-Request-Id header that can
304
- # be generated by a firewall, load balancer, or web server or by the RequestId middleware
305
- # (which sets the action_dispatch.request_id environment variable).
299
+ # Returns the unique request id, which is based on either the +X-Request-Id+ header that can
300
+ # be generated by a firewall, load balancer, or web server, or by the RequestId middleware
301
+ # (which sets the +action_dispatch.request_id+ environment variable).
306
302
  #
307
303
  # This unique ID is useful for tracing a request from end-to-end as part of logging or debugging.
308
304
  # This relies on the Rack variable set by the ActionDispatch::RequestId middleware.
@@ -344,32 +340,26 @@ module ActionDispatch
344
340
  end
345
341
 
346
342
  # Determine whether the request body contains form-data by checking
347
- # the request Content-Type for one of the media-types:
348
- # "application/x-www-form-urlencoded" or "multipart/form-data". The
343
+ # the request +Content-Type+ for one of the media-types:
344
+ # +application/x-www-form-urlencoded+ or +multipart/form-data+. The
349
345
  # list of form-data media types can be modified through the
350
346
  # +FORM_DATA_MEDIA_TYPES+ array.
351
347
  #
352
348
  # A request body is not assumed to contain form-data when no
353
- # Content-Type header is provided and the request_method is POST.
349
+ # +Content-Type+ header is provided and the request_method is POST.
354
350
  def form_data?
355
351
  FORM_DATA_MEDIA_TYPES.include?(media_type)
356
352
  end
357
353
 
358
- def body_stream #:nodoc:
354
+ def body_stream # :nodoc:
359
355
  get_header("rack.input")
360
356
  end
361
357
 
362
- # TODO This should be broken apart into AD::Request::Session and probably
363
- # be included by the session middleware.
364
358
  def reset_session
365
- if session && session.respond_to?(:destroy)
366
- session.destroy
367
- else
368
- self.session = {}
369
- end
359
+ session.destroy
370
360
  end
371
361
 
372
- def session=(session) #:nodoc:
362
+ def session=(session) # :nodoc:
373
363
  Session.set self, session
374
364
  end
375
365
 
@@ -388,7 +378,7 @@ module ActionDispatch
388
378
  Request::Utils.check_param_encoding(rack_query_params)
389
379
  set_header k, Request::Utils.normalize_encode_params(rack_query_params)
390
380
  end
391
- rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
381
+ rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError, Rack::QueryParser::ParamsTooDeepError => e
392
382
  raise ActionController::BadRequest.new("Invalid query parameters: #{e.message}")
393
383
  end
394
384
  alias :query_parameters :GET
@@ -403,7 +393,7 @@ module ActionDispatch
403
393
  Request::Utils.check_param_encoding(pr)
404
394
  self.request_parameters = Request::Utils.normalize_encode_params(pr)
405
395
  end
406
- rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
396
+ rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError, Rack::QueryParser::ParamsTooDeepError, EOFError => e
407
397
  raise ActionController::BadRequest.new("Invalid request parameters: #{e.message}")
408
398
  end
409
399
  alias :request_parameters :POST
@@ -434,10 +424,6 @@ module ActionDispatch
434
424
  def commit_flash
435
425
  end
436
426
 
437
- def ssl?
438
- super || scheme == "wss"
439
- end
440
-
441
427
  def inspect # :nodoc:
442
428
  "#<#{self.class.name} #{method} #{original_url.dump} for #{remote_ip}>"
443
429
  end
@@ -447,6 +433,10 @@ module ActionDispatch
447
433
  HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS[0...-1].join(', ')}, and #{HTTP_METHODS[-1]}")
448
434
  name
449
435
  end
436
+
437
+ def default_session
438
+ Session.disabled(self)
439
+ end
450
440
  end
451
441
  end
452
442
 
@@ -21,9 +21,8 @@ module ActionDispatch # :nodoc:
21
21
  # Nevertheless, integration tests may want to inspect controller responses in
22
22
  # more detail, and that's when \Response can be useful for application
23
23
  # developers. Integration test methods such as
24
- # ActionDispatch::Integration::Session#get and
25
- # ActionDispatch::Integration::Session#post return objects of type
26
- # TestResponse (which are of course also of type \Response).
24
+ # Integration::RequestHelpers#get and Integration::RequestHelpers#post return
25
+ # objects of type TestResponse (which are of course also of type \Response).
27
26
  #
28
27
  # For example, the following demo integration test prints the body of the
29
28
  # controller response to the console:
@@ -86,18 +85,6 @@ module ActionDispatch # :nodoc:
86
85
  cattr_accessor :default_charset, default: "utf-8"
87
86
  cattr_accessor :default_headers
88
87
 
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 7.0."
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 7.0."
98
- )
99
- end
100
-
101
88
  include Rack::Response::Helpers
102
89
  # Aliasing these off because AD::Http::Cache::Response defines them.
103
90
  alias :_cache_control :cache_control
@@ -336,7 +323,7 @@ module ActionDispatch # :nodoc:
336
323
  # Avoid having to pass an open file handle as the response body.
337
324
  # Rack::Sendfile will usually intercept the response and uses
338
325
  # the path directly, so there is no reason to open the file.
339
- class FileBody #:nodoc:
326
+ class FileBody # :nodoc:
340
327
  attr_reader :to_path
341
328
 
342
329
  def initialize(path)
@@ -514,10 +501,6 @@ module ActionDispatch # :nodoc:
514
501
  def to_path
515
502
  @response.stream.to_path
516
503
  end
517
-
518
- def to_ary
519
- nil
520
- end
521
504
  end
522
505
 
523
506
  def handle_no_content!
@@ -28,6 +28,8 @@ module ActionDispatch
28
28
  @tempfile = hash[:tempfile]
29
29
  raise(ArgumentError, ":tempfile is required") unless @tempfile
30
30
 
31
+ @content_type = hash[:type]
32
+
31
33
  if hash[:filename]
32
34
  @original_filename = hash[:filename].dup
33
35
 
@@ -40,8 +42,17 @@ module ActionDispatch
40
42
  @original_filename = nil
41
43
  end
42
44
 
43
- @content_type = hash[:type]
44
- @headers = hash[:head]
45
+ if hash[:head]
46
+ @headers = hash[:head].dup
47
+
48
+ begin
49
+ @headers.encode!(Encoding::UTF_8)
50
+ rescue EncodingError
51
+ @headers.force_encoding(Encoding::UTF_8)
52
+ end
53
+ else
54
+ @headers = nil
55
+ end
45
56
  end
46
57
 
47
58
  # Shortcut for +tempfile.read+.
@@ -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