actionpack 6.1.7.5 → 7.0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +323 -399
- 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 +27 -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
|