actionpack 5.2.4.rc1 → 6.0.0.rc2
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 +179 -335
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -2
- data/lib/abstract_controller/base.rb +4 -2
- data/lib/abstract_controller/caching/fragments.rb +6 -22
- data/lib/abstract_controller/callbacks.rb +12 -0
- data/lib/abstract_controller/collector.rb +1 -1
- data/lib/abstract_controller/helpers.rb +2 -2
- data/lib/abstract_controller/railties/routes_helpers.rb +1 -1
- data/lib/abstract_controller/translation.rb +1 -0
- data/lib/action_controller.rb +1 -0
- data/lib/action_controller/api.rb +2 -1
- data/lib/action_controller/base.rb +2 -7
- data/lib/action_controller/caching.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +8 -5
- data/lib/action_controller/metal.rb +1 -1
- data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
- data/lib/action_controller/metal/conditional_get.rb +9 -3
- data/lib/action_controller/metal/data_streaming.rb +5 -6
- data/lib/action_controller/metal/default_headers.rb +17 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
- data/lib/action_controller/metal/exceptions.rb +22 -1
- data/lib/action_controller/metal/flash.rb +5 -5
- data/lib/action_controller/metal/force_ssl.rb +15 -56
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +3 -4
- data/lib/action_controller/metal/http_authentication.rb +20 -21
- data/lib/action_controller/metal/implicit_render.rb +4 -14
- data/lib/action_controller/metal/instrumentation.rb +3 -5
- data/lib/action_controller/metal/live.rb +29 -27
- data/lib/action_controller/metal/mime_responds.rb +13 -2
- data/lib/action_controller/metal/params_wrapper.rb +17 -13
- data/lib/action_controller/metal/redirecting.rb +5 -5
- data/lib/action_controller/metal/renderers.rb +1 -1
- data/lib/action_controller/metal/rendering.rb +2 -2
- data/lib/action_controller/metal/request_forgery_protection.rb +23 -12
- data/lib/action_controller/metal/strong_parameters.rb +63 -44
- data/lib/action_controller/metal/url_for.rb +1 -1
- data/lib/action_controller/railties/helpers.rb +1 -1
- data/lib/action_controller/renderer.rb +16 -3
- data/lib/action_controller/template_assertions.rb +1 -1
- data/lib/action_controller/test_case.rb +3 -7
- data/lib/action_dispatch.rb +4 -1
- data/lib/action_dispatch/http/cache.rb +14 -10
- data/lib/action_dispatch/http/content_disposition.rb +45 -0
- data/lib/action_dispatch/http/content_security_policy.rb +28 -16
- data/lib/action_dispatch/http/filter_parameters.rb +8 -6
- data/lib/action_dispatch/http/filter_redirect.rb +1 -1
- data/lib/action_dispatch/http/headers.rb +1 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +7 -5
- data/lib/action_dispatch/http/mime_type.rb +14 -6
- data/lib/action_dispatch/http/parameter_filter.rb +5 -79
- data/lib/action_dispatch/http/parameters.rb +13 -3
- data/lib/action_dispatch/http/request.rb +10 -13
- data/lib/action_dispatch/http/response.rb +33 -19
- data/lib/action_dispatch/http/upload.rb +9 -1
- data/lib/action_dispatch/http/url.rb +81 -81
- data/lib/action_dispatch/journey/formatter.rb +2 -2
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -2
- data/lib/action_dispatch/journey/nodes/node.rb +9 -8
- data/lib/action_dispatch/journey/path/pattern.rb +6 -2
- data/lib/action_dispatch/journey/route.rb +5 -4
- data/lib/action_dispatch/journey/router.rb +0 -3
- data/lib/action_dispatch/journey/router/utils.rb +10 -10
- data/lib/action_dispatch/journey/routes.rb +0 -1
- data/lib/action_dispatch/journey/scanner.rb +11 -4
- data/lib/action_dispatch/journey/visitors.rb +1 -1
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -4
- data/lib/action_dispatch/middleware/cookies.rb +46 -72
- data/lib/action_dispatch/middleware/debug_exceptions.rb +39 -59
- data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
- data/lib/action_dispatch/middleware/debug_view.rb +68 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +49 -15
- data/lib/action_dispatch/middleware/flash.rb +1 -1
- data/lib/action_dispatch/middleware/host_authorization.rb +103 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -2
- data/lib/action_dispatch/middleware/remote_ip.rb +6 -8
- data/lib/action_dispatch/middleware/request_id.rb +2 -2
- data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -6
- data/lib/action_dispatch/middleware/show_exceptions.rb +1 -1
- data/lib/action_dispatch/middleware/ssl.rb +8 -8
- data/lib/action_dispatch/middleware/stack.rb +33 -1
- data/lib/action_dispatch/middleware/static.rb +5 -6
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -4
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +3 -0
- data/lib/action_dispatch/railtie.rb +3 -0
- data/lib/action_dispatch/request/session.rb +8 -0
- data/lib/action_dispatch/routing.rb +21 -20
- data/lib/action_dispatch/routing/inspector.rb +99 -50
- data/lib/action_dispatch/routing/mapper.rb +60 -38
- data/lib/action_dispatch/routing/polymorphic_routes.rb +3 -4
- data/lib/action_dispatch/routing/route_set.rb +24 -27
- data/lib/action_dispatch/routing/url_for.rb +1 -0
- data/lib/action_dispatch/system_test_case.rb +23 -2
- data/lib/action_dispatch/system_testing/browser.rb +38 -7
- data/lib/action_dispatch/system_testing/driver.rb +10 -1
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +6 -5
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +7 -5
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +2 -3
- data/lib/action_dispatch/testing/assertions/routing.rb +15 -3
- data/lib/action_dispatch/testing/integration.rb +12 -5
- data/lib/action_dispatch/testing/request_encoder.rb +2 -2
- data/lib/action_dispatch/testing/test_process.rb +2 -2
- data/lib/action_dispatch/testing/test_response.rb +4 -32
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/gem_version.rb +4 -4
- metadata +24 -13
@@ -111,13 +111,23 @@ module ActionDispatch
|
|
111
111
|
begin
|
112
112
|
strategy.call(raw_post)
|
113
113
|
rescue # JSON or Ruby code block errors.
|
114
|
-
|
115
|
-
my_logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{raw_post}"
|
116
|
-
|
114
|
+
log_parse_error_once
|
117
115
|
raise ParseError
|
118
116
|
end
|
119
117
|
end
|
120
118
|
|
119
|
+
def log_parse_error_once
|
120
|
+
@parse_error_logged ||= begin
|
121
|
+
parse_logger = logger || ActiveSupport::Logger.new($stderr)
|
122
|
+
parse_logger.debug <<~MSG.chomp
|
123
|
+
Error occurred while parsing request parameters.
|
124
|
+
Contents:
|
125
|
+
|
126
|
+
#{raw_post}
|
127
|
+
MSG
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
121
131
|
def params_parsers
|
122
132
|
ActionDispatch::Request.parameter_parsers
|
123
133
|
end
|
@@ -136,11 +136,11 @@ module ActionDispatch
|
|
136
136
|
end
|
137
137
|
|
138
138
|
def routes # :nodoc:
|
139
|
-
get_header("action_dispatch.routes"
|
139
|
+
get_header("action_dispatch.routes")
|
140
140
|
end
|
141
141
|
|
142
142
|
def routes=(routes) # :nodoc:
|
143
|
-
set_header("action_dispatch.routes"
|
143
|
+
set_header("action_dispatch.routes", routes)
|
144
144
|
end
|
145
145
|
|
146
146
|
def engine_script_name(_routes) # :nodoc:
|
@@ -158,11 +158,11 @@ module ActionDispatch
|
|
158
158
|
end
|
159
159
|
|
160
160
|
def controller_instance # :nodoc:
|
161
|
-
get_header("action_controller.instance"
|
161
|
+
get_header("action_controller.instance")
|
162
162
|
end
|
163
163
|
|
164
164
|
def controller_instance=(controller) # :nodoc:
|
165
|
-
set_header("action_controller.instance"
|
165
|
+
set_header("action_controller.instance", controller)
|
166
166
|
end
|
167
167
|
|
168
168
|
def http_auth_salt
|
@@ -173,7 +173,7 @@ module ActionDispatch
|
|
173
173
|
# We're treating `nil` as "unset", and we want the default setting to be
|
174
174
|
# `true`. This logic should be extracted to `env_config` and calculated
|
175
175
|
# once.
|
176
|
-
!(get_header("action_dispatch.show_exceptions"
|
176
|
+
!(get_header("action_dispatch.show_exceptions") == false)
|
177
177
|
end
|
178
178
|
|
179
179
|
# Returns a symbol form of the #request_method.
|
@@ -280,10 +280,10 @@ module ActionDispatch
|
|
280
280
|
end
|
281
281
|
|
282
282
|
def remote_ip=(remote_ip)
|
283
|
-
set_header "action_dispatch.remote_ip"
|
283
|
+
set_header "action_dispatch.remote_ip", remote_ip
|
284
284
|
end
|
285
285
|
|
286
|
-
ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id"
|
286
|
+
ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc:
|
287
287
|
|
288
288
|
# Returns the unique request id, which is based on either the X-Request-Id header that can
|
289
289
|
# be generated by a firewall, load balancer, or web server or by the RequestId middleware
|
@@ -383,9 +383,6 @@ module ActionDispatch
|
|
383
383
|
end
|
384
384
|
self.request_parameters = Request::Utils.normalize_encode_params(pr)
|
385
385
|
end
|
386
|
-
rescue Http::Parameters::ParseError # one of the parse strategies blew up
|
387
|
-
self.request_parameters = Request::Utils.normalize_encode_params(super || {})
|
388
|
-
raise
|
389
386
|
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
|
390
387
|
raise ActionController::BadRequest.new("Invalid request parameters: #{e.message}")
|
391
388
|
end
|
@@ -407,18 +404,18 @@ module ActionDispatch
|
|
407
404
|
|
408
405
|
def request_parameters=(params)
|
409
406
|
raise if params.nil?
|
410
|
-
set_header("action_dispatch.request.request_parameters"
|
407
|
+
set_header("action_dispatch.request.request_parameters", params)
|
411
408
|
end
|
412
409
|
|
413
410
|
def logger
|
414
|
-
get_header("action_dispatch.logger"
|
411
|
+
get_header("action_dispatch.logger")
|
415
412
|
end
|
416
413
|
|
417
414
|
def commit_flash
|
418
415
|
end
|
419
416
|
|
420
417
|
def ssl?
|
421
|
-
super || scheme == "wss"
|
418
|
+
super || scheme == "wss"
|
422
419
|
end
|
423
420
|
|
424
421
|
private
|
@@ -78,13 +78,15 @@ module ActionDispatch # :nodoc:
|
|
78
78
|
x
|
79
79
|
end
|
80
80
|
|
81
|
-
CONTENT_TYPE = "Content-Type"
|
82
|
-
SET_COOKIE = "Set-Cookie"
|
83
|
-
LOCATION = "Location"
|
81
|
+
CONTENT_TYPE = "Content-Type"
|
82
|
+
SET_COOKIE = "Set-Cookie"
|
83
|
+
LOCATION = "Location"
|
84
84
|
NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304]
|
85
|
+
CONTENT_TYPE_PARSER = /\A(?<type>[^;\s]+)?(?:.*;\s*charset=(?<quote>"?)(?<charset>[^;\s]+)\k<quote>)?/ # :nodoc:
|
85
86
|
|
86
87
|
cattr_accessor :default_charset, default: "utf-8"
|
87
88
|
cattr_accessor :default_headers
|
89
|
+
cattr_accessor :return_only_media_type_on_content_type, default: false
|
88
90
|
|
89
91
|
include Rack::Response::Helpers
|
90
92
|
# Aliasing these off because AD::Http::Cache::Response defines them.
|
@@ -105,7 +107,7 @@ module ActionDispatch # :nodoc:
|
|
105
107
|
|
106
108
|
def body
|
107
109
|
@str_body ||= begin
|
108
|
-
buf = ""
|
110
|
+
buf = +""
|
109
111
|
each { |chunk| buf << chunk }
|
110
112
|
buf
|
111
113
|
end
|
@@ -224,16 +226,6 @@ module ActionDispatch # :nodoc:
|
|
224
226
|
@status = Rack::Utils.status_code(status)
|
225
227
|
end
|
226
228
|
|
227
|
-
# Sets the HTTP content type.
|
228
|
-
def content_type=(content_type)
|
229
|
-
return unless content_type
|
230
|
-
new_header_info = parse_content_type(content_type.to_s)
|
231
|
-
prev_header_info = parsed_content_type_header
|
232
|
-
charset = new_header_info.charset || prev_header_info.charset
|
233
|
-
charset ||= self.class.default_charset unless prev_header_info.mime_type
|
234
|
-
set_content_type new_header_info.mime_type, charset
|
235
|
-
end
|
236
|
-
|
237
229
|
# Sets the HTTP response's content MIME type. For example, in the controller
|
238
230
|
# you could write this:
|
239
231
|
#
|
@@ -242,8 +234,32 @@ module ActionDispatch # :nodoc:
|
|
242
234
|
# If a character set has been defined for this response (see charset=) then
|
243
235
|
# the character set information will also be included in the content type
|
244
236
|
# information.
|
237
|
+
def content_type=(content_type)
|
238
|
+
return unless content_type
|
239
|
+
new_header_info = parse_content_type(content_type.to_s)
|
240
|
+
prev_header_info = parsed_content_type_header
|
241
|
+
charset = new_header_info.charset || prev_header_info.charset
|
242
|
+
charset ||= self.class.default_charset unless prev_header_info.mime_type
|
243
|
+
set_content_type new_header_info.mime_type, charset
|
244
|
+
end
|
245
245
|
|
246
|
+
# Content type of response.
|
246
247
|
def content_type
|
248
|
+
if self.class.return_only_media_type_on_content_type
|
249
|
+
ActiveSupport::Deprecation.warn(
|
250
|
+
"Rails 6.1 will return Content-Type header without modification." \
|
251
|
+
" If you want just the MIME type, please use `#media_type` instead."
|
252
|
+
)
|
253
|
+
|
254
|
+
content_type = super
|
255
|
+
content_type ? content_type.split(/;\s*charset=/)[0].presence : content_type
|
256
|
+
else
|
257
|
+
super.presence
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# Media type of response.
|
262
|
+
def media_type
|
247
263
|
parsed_content_type_header.mime_type
|
248
264
|
end
|
249
265
|
|
@@ -409,10 +425,8 @@ module ActionDispatch # :nodoc:
|
|
409
425
|
NullContentTypeHeader = ContentTypeHeader.new nil, nil
|
410
426
|
|
411
427
|
def parse_content_type(content_type)
|
412
|
-
if content_type
|
413
|
-
type, charset
|
414
|
-
type = nil if type && type.empty?
|
415
|
-
ContentTypeHeader.new(type, charset)
|
428
|
+
if content_type && match = CONTENT_TYPE_PARSER.match(content_type)
|
429
|
+
ContentTypeHeader.new(match[:type], match[:charset])
|
416
430
|
else
|
417
431
|
NullContentTypeHeader
|
418
432
|
end
|
@@ -459,7 +473,7 @@ module ActionDispatch # :nodoc:
|
|
459
473
|
end
|
460
474
|
|
461
475
|
def assign_default_content_type_and_charset!
|
462
|
-
return if
|
476
|
+
return if media_type
|
463
477
|
|
464
478
|
ct = parsed_content_type_header
|
465
479
|
set_content_type(ct.mime_type || Mime[:html].to_s,
|
@@ -20,7 +20,6 @@ module ActionDispatch
|
|
20
20
|
# A +Tempfile+ object with the actual uploaded file. Note that some of
|
21
21
|
# its interface is available directly.
|
22
22
|
attr_accessor :tempfile
|
23
|
-
alias :to_io :tempfile
|
24
23
|
|
25
24
|
# A string with the headers of the multipart request.
|
26
25
|
attr_accessor :headers
|
@@ -65,6 +64,11 @@ module ActionDispatch
|
|
65
64
|
@tempfile.path
|
66
65
|
end
|
67
66
|
|
67
|
+
# Shortcut for +tempfile.to_path+.
|
68
|
+
def to_path
|
69
|
+
@tempfile.to_path
|
70
|
+
end
|
71
|
+
|
68
72
|
# Shortcut for +tempfile.rewind+.
|
69
73
|
def rewind
|
70
74
|
@tempfile.rewind
|
@@ -79,6 +83,10 @@ module ActionDispatch
|
|
79
83
|
def eof?
|
80
84
|
@tempfile.eof?
|
81
85
|
end
|
86
|
+
|
87
|
+
def to_io
|
88
|
+
@tempfile.to_io
|
89
|
+
end
|
82
90
|
end
|
83
91
|
end
|
84
92
|
end
|
@@ -67,7 +67,7 @@ module ActionDispatch
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def path_for(options)
|
70
|
-
path = options[:script_name].to_s.chomp("/"
|
70
|
+
path = options[:script_name].to_s.chomp("/")
|
71
71
|
path << options[:path] if options.key?(:path)
|
72
72
|
|
73
73
|
add_trailing_slash(path) if options[:trailing_slash]
|
@@ -79,108 +79,108 @@ module ActionDispatch
|
|
79
79
|
|
80
80
|
private
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
def add_anchor(path, anchor)
|
90
|
-
if anchor
|
91
|
-
path << "##{Journey::Router::Utils.escape_fragment(anchor.to_param)}"
|
82
|
+
def add_params(path, params)
|
83
|
+
params = { params: params } unless params.is_a?(Hash)
|
84
|
+
params.reject! { |_, v| v.to_param.nil? }
|
85
|
+
query = params.to_query
|
86
|
+
path << "?#{query}" unless query.empty?
|
92
87
|
end
|
93
|
-
end
|
94
88
|
|
95
|
-
|
96
|
-
|
97
|
-
|
89
|
+
def add_anchor(path, anchor)
|
90
|
+
if anchor
|
91
|
+
path << "##{Journey::Router::Utils.escape_fragment(anchor.to_param)}"
|
92
|
+
end
|
93
|
+
end
|
98
94
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
95
|
+
def extract_domain_from(host, tld_length)
|
96
|
+
host.split(".").last(1 + tld_length).join(".")
|
97
|
+
end
|
103
98
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
elsif !path.include?(".")
|
108
|
-
path.sub!(/[^\/]\z|\A\z/, '\&/')
|
99
|
+
def extract_subdomains_from(host, tld_length)
|
100
|
+
parts = host.split(".")
|
101
|
+
parts[0..-(tld_length + 2)]
|
109
102
|
end
|
110
|
-
end
|
111
103
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
117
110
|
end
|
118
111
|
|
119
|
-
|
120
|
-
|
112
|
+
def build_host_url(host, port, protocol, options, path)
|
113
|
+
if match = host.match(HOST_REGEXP)
|
114
|
+
protocol ||= match[1] unless protocol == false
|
115
|
+
host = match[2]
|
116
|
+
port = match[3] unless options.key? :port
|
117
|
+
end
|
121
118
|
|
122
|
-
|
119
|
+
protocol = normalize_protocol protocol
|
120
|
+
host = normalize_host(host, options)
|
123
121
|
|
124
|
-
|
125
|
-
result << "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
|
126
|
-
end
|
122
|
+
result = protocol.dup
|
127
123
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
}
|
124
|
+
if options[:user] && options[:password]
|
125
|
+
result << "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
|
126
|
+
end
|
132
127
|
|
133
|
-
|
134
|
-
|
128
|
+
result << host
|
129
|
+
normalize_port(port, protocol) { |normalized_port|
|
130
|
+
result << ":#{normalized_port}"
|
131
|
+
}
|
135
132
|
|
136
|
-
|
137
|
-
|
138
|
-
end
|
133
|
+
result.concat path
|
134
|
+
end
|
139
135
|
|
140
|
-
|
141
|
-
|
142
|
-
when nil
|
143
|
-
"http://"
|
144
|
-
when false, "//"
|
145
|
-
"//"
|
146
|
-
when PROTOCOL_REGEXP
|
147
|
-
"#{$1}://"
|
148
|
-
else
|
149
|
-
raise ArgumentError, "Invalid :protocol option: #{protocol.inspect}"
|
136
|
+
def named_host?(host)
|
137
|
+
IP_HOST_REGEXP !~ host
|
150
138
|
end
|
151
|
-
end
|
152
139
|
|
153
|
-
|
154
|
-
|
140
|
+
def normalize_protocol(protocol)
|
141
|
+
case protocol
|
142
|
+
when nil
|
143
|
+
"http://"
|
144
|
+
when false, "//"
|
145
|
+
"//"
|
146
|
+
when PROTOCOL_REGEXP
|
147
|
+
"#{$1}://"
|
148
|
+
else
|
149
|
+
raise ArgumentError, "Invalid :protocol option: #{protocol.inspect}"
|
150
|
+
end
|
151
|
+
end
|
155
152
|
|
156
|
-
|
157
|
-
|
158
|
-
domain = options[:domain]
|
153
|
+
def normalize_host(_host, options)
|
154
|
+
return _host unless named_host?(_host)
|
159
155
|
|
160
|
-
|
161
|
-
|
162
|
-
|
156
|
+
tld_length = options[:tld_length] || @@tld_length
|
157
|
+
subdomain = options.fetch :subdomain, true
|
158
|
+
domain = options[:domain]
|
163
159
|
|
164
|
-
host
|
165
|
-
|
166
|
-
|
160
|
+
host = +""
|
161
|
+
if subdomain == true
|
162
|
+
return _host if domain.nil?
|
163
|
+
|
164
|
+
host << extract_subdomains_from(_host, tld_length).join(".")
|
165
|
+
elsif subdomain
|
166
|
+
host << subdomain.to_param
|
167
|
+
end
|
168
|
+
host << "." unless host.empty?
|
169
|
+
host << (domain || extract_domain_from(_host, tld_length))
|
170
|
+
host
|
167
171
|
end
|
168
|
-
host << "." unless host.empty?
|
169
|
-
host << (domain || extract_domain_from(_host, tld_length))
|
170
|
-
host
|
171
|
-
end
|
172
172
|
|
173
|
-
|
174
|
-
|
173
|
+
def normalize_port(port, protocol)
|
174
|
+
return unless port
|
175
175
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
176
|
+
case protocol
|
177
|
+
when "//" then yield port
|
178
|
+
when "https://"
|
179
|
+
yield port unless port.to_i == 443
|
180
|
+
else
|
181
|
+
yield port unless port.to_i == 80
|
182
|
+
end
|
182
183
|
end
|
183
|
-
end
|
184
184
|
end
|
185
185
|
|
186
186
|
def initialize
|
@@ -231,7 +231,7 @@ module ActionDispatch
|
|
231
231
|
# req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
|
232
232
|
# req.host # => "example.com"
|
233
233
|
def host
|
234
|
-
raw_host_with_port.sub(/:\d+$/, ""
|
234
|
+
raw_host_with_port.sub(/:\d+$/, "")
|
235
235
|
end
|
236
236
|
|
237
237
|
# Returns a \host:\port string for this request, such as "example.com" or
|
@@ -50,7 +50,7 @@ module ActionDispatch
|
|
50
50
|
unmatched_keys = (missing_keys || []) & constraints.keys
|
51
51
|
missing_keys = (missing_keys || []) - unmatched_keys
|
52
52
|
|
53
|
-
message = "No route matches #{Hash[constraints.sort_by { |k, v| k.to_s }].inspect}"
|
53
|
+
message = +"No route matches #{Hash[constraints.sort_by { |k, v| k.to_s }].inspect}"
|
54
54
|
message << ", missing required keys: #{missing_keys.sort.inspect}" if missing_keys && !missing_keys.empty?
|
55
55
|
message << ", possible unmatched constraints: #{unmatched_keys.sort.inspect}" if unmatched_keys && !unmatched_keys.empty?
|
56
56
|
|
@@ -67,7 +67,7 @@ module ActionDispatch
|
|
67
67
|
parameterized_parts = recall.merge(options)
|
68
68
|
|
69
69
|
keys_to_keep = route.parts.reverse_each.drop_while { |part|
|
70
|
-
!options.key?(part) || (options[part] || recall[part]).nil?
|
70
|
+
!(options.key?(part) || route.scope_options.key?(part)) || (options[part] || recall[part]).nil?
|
71
71
|
} | route.required_parts
|
72
72
|
|
73
73
|
parameterized_parts.delete_if do |bad_key, _|
|