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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +319 -401
- data/MIT-LICENSE +1 -0
- data/README.rdoc +4 -5
- data/lib/abstract_controller/asset_paths.rb +1 -1
- data/lib/abstract_controller/base.rb +13 -26
- data/lib/abstract_controller/caching/fragments.rb +2 -2
- data/lib/abstract_controller/caching.rb +1 -1
- data/lib/abstract_controller/callbacks.rb +21 -7
- data/lib/abstract_controller/collector.rb +2 -2
- data/lib/abstract_controller/error.rb +1 -1
- data/lib/abstract_controller/helpers.rb +17 -12
- data/lib/abstract_controller/logger.rb +1 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +9 -11
- data/lib/abstract_controller/translation.rb +5 -4
- data/lib/abstract_controller/url_for.rb +4 -6
- data/lib/action_controller/api.rb +7 -7
- data/lib/action_controller/base.rb +5 -4
- data/lib/action_controller/form_builder.rb +2 -2
- data/lib/action_controller/log_subscriber.rb +4 -3
- data/lib/action_controller/metal/basic_implicit_render.rb +3 -1
- data/lib/action_controller/metal/conditional_get.rb +137 -102
- data/lib/action_controller/metal/content_security_policy.rb +36 -2
- data/lib/action_controller/metal/cookies.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +23 -31
- data/lib/action_controller/metal/etag_with_flash.rb +1 -1
- data/lib/action_controller/metal/exceptions.rb +19 -30
- data/lib/action_controller/metal/flash.rb +6 -2
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +2 -2
- data/lib/action_controller/metal/http_authentication.rb +66 -39
- data/lib/action_controller/metal/instrumentation.rb +57 -52
- data/lib/action_controller/metal/live.rb +43 -2
- data/lib/action_controller/metal/mime_responds.rb +3 -3
- data/lib/action_controller/metal/params_wrapper.rb +20 -11
- data/lib/action_controller/metal/permissions_policy.rb +19 -28
- data/lib/action_controller/metal/redirecting.rb +95 -22
- data/lib/action_controller/metal/renderers.rb +12 -13
- data/lib/action_controller/metal/rendering.rb +121 -9
- data/lib/action_controller/metal/request_forgery_protection.rb +83 -32
- data/lib/action_controller/metal/rescue.rb +5 -4
- data/lib/action_controller/metal/streaming.rb +7 -9
- data/lib/action_controller/metal/strong_parameters.rb +138 -115
- data/lib/action_controller/metal/testing.rb +9 -2
- data/lib/action_controller/metal/url_for.rb +3 -5
- data/lib/action_controller/metal.rb +10 -13
- data/lib/action_controller/railtie.rb +50 -6
- data/lib/action_controller/renderer.rb +1 -20
- data/lib/action_controller/test_case.rb +28 -7
- data/lib/action_controller.rb +2 -5
- data/lib/action_dispatch/http/cache.rb +20 -13
- data/lib/action_dispatch/http/content_security_policy.rb +113 -36
- data/lib/action_dispatch/http/filter_parameters.rb +4 -19
- data/lib/action_dispatch/http/headers.rb +1 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +15 -5
- data/lib/action_dispatch/http/mime_type.rb +9 -11
- data/lib/action_dispatch/http/parameters.rb +5 -5
- data/lib/action_dispatch/http/permissions_policy.rb +17 -1
- data/lib/action_dispatch/http/request.rb +27 -37
- data/lib/action_dispatch/http/response.rb +3 -20
- data/lib/action_dispatch/http/upload.rb +13 -2
- data/lib/action_dispatch/http/url.rb +11 -19
- data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
- data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
- data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
- data/lib/action_dispatch/journey/nodes/node.rb +70 -5
- data/lib/action_dispatch/journey/path/pattern.rb +22 -13
- data/lib/action_dispatch/journey/route.rb +6 -13
- data/lib/action_dispatch/journey/router/utils.rb +2 -2
- data/lib/action_dispatch/journey/router.rb +1 -1
- data/lib/action_dispatch/journey/routes.rb +3 -3
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
- data/lib/action_dispatch/middleware/cookies.rb +20 -13
- data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
- data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
- data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
- data/lib/action_dispatch/middleware/executor.rb +3 -0
- data/lib/action_dispatch/middleware/flash.rb +17 -18
- data/lib/action_dispatch/middleware/host_authorization.rb +13 -17
- data/lib/action_dispatch/middleware/remote_ip.rb +20 -8
- data/lib/action_dispatch/middleware/request_id.rb +3 -3
- data/lib/action_dispatch/middleware/server_timing.rb +76 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
- data/lib/action_dispatch/middleware/session/cookie_store.rb +9 -9
- data/lib/action_dispatch/middleware/show_exceptions.rb +17 -16
- data/lib/action_dispatch/middleware/stack.rb +27 -9
- data/lib/action_dispatch/middleware/static.rb +5 -9
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +10 -5
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +7 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +22 -22
- data/lib/action_dispatch/railtie.rb +8 -2
- data/lib/action_dispatch/request/session.rb +43 -13
- data/lib/action_dispatch/routing/inspector.rb +1 -1
- data/lib/action_dispatch/routing/mapper.rb +82 -83
- data/lib/action_dispatch/routing/redirection.rb +5 -2
- data/lib/action_dispatch/routing/route_set.rb +17 -7
- data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
- data/lib/action_dispatch/routing/url_for.rb +24 -25
- data/lib/action_dispatch/routing.rb +5 -6
- data/lib/action_dispatch/system_test_case.rb +5 -5
- data/lib/action_dispatch/system_testing/browser.rb +3 -13
- data/lib/action_dispatch/system_testing/driver.rb +34 -10
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +11 -7
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
- data/lib/action_dispatch/testing/assertions/response.rb +1 -1
- data/lib/action_dispatch/testing/assertions/routing.rb +3 -2
- data/lib/action_dispatch/testing/assertions.rb +2 -5
- data/lib/action_dispatch/testing/integration.rb +6 -8
- data/lib/action_dispatch/testing/test_process.rb +3 -29
- data/lib/action_dispatch/testing/test_response.rb +20 -2
- data/lib/action_dispatch.rb +1 -0
- data/lib/action_pack/gem_version.rb +5 -5
- data/lib/action_pack/version.rb +1 -1
- 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
|
-
|
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?
|
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
|
126
|
-
# to the
|
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
|
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)
|
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
|
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
|
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
|
-
|
230
|
-
|
231
|
-
|
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(
|
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)
|
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
|
-
# {
|
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
|
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
|
-
|
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
|
-
#
|
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)
|
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
|
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
|
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
|
-
#
|
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
|
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
|
-
|
366
|
-
session.destroy
|
367
|
-
else
|
368
|
-
self.session = {}
|
369
|
-
end
|
359
|
+
session.destroy
|
370
360
|
end
|
371
361
|
|
372
|
-
def session=(session)
|
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
|
-
#
|
25
|
-
#
|
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
|
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
|
-
|
44
|
-
|
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
|
-
|
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
|
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 ||=
|
262
|
-
|
263
|
-
|
264
|
-
|
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
|
-
|
276
|
-
|
277
|
-
else
|
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
|
-
|
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,
|
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 ==
|
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?(
|
46
|
+
if u.include?(DUMMY_END_NODE)
|
47
47
|
ps.each do |state|
|
48
|
-
if @followpos[state].include?(
|
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
|
-
|
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
|
-
|
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
|
-
|
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 |
|
34
|
-
|
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
|