actionpack 5.2.3 → 6.0.1
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 +191 -292
- 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 +5 -1
- 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 +3 -3
- 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 +23 -2
- 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 +18 -14
- data/lib/action_controller/metal/redirecting.rb +5 -5
- data/lib/action_controller/metal/renderers.rb +4 -4
- 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 +4 -6
- data/lib/action_dispatch.rb +4 -2
- 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 +39 -18
- 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 +8 -3
- 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 +52 -74
- 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 +9 -11
- 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 +34 -2
- 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 +7 -2
- 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 +61 -39
- 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 +43 -5
- 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 -6
- 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 +3 -3
- metadata +29 -16
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -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,14 +78,14 @@ 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:
|
86
85
|
|
87
86
|
cattr_accessor :default_charset, default: "utf-8"
|
88
87
|
cattr_accessor :default_headers
|
88
|
+
cattr_accessor :return_only_media_type_on_content_type, default: false
|
89
89
|
|
90
90
|
include Rack::Response::Helpers
|
91
91
|
# Aliasing these off because AD::Http::Cache::Response defines them.
|
@@ -106,7 +106,7 @@ module ActionDispatch # :nodoc:
|
|
106
106
|
|
107
107
|
def body
|
108
108
|
@str_body ||= begin
|
109
|
-
buf = ""
|
109
|
+
buf = +""
|
110
110
|
each { |chunk| buf << chunk }
|
111
111
|
buf
|
112
112
|
end
|
@@ -225,16 +225,6 @@ module ActionDispatch # :nodoc:
|
|
225
225
|
@status = Rack::Utils.status_code(status)
|
226
226
|
end
|
227
227
|
|
228
|
-
# Sets the HTTP content type.
|
229
|
-
def content_type=(content_type)
|
230
|
-
return unless content_type
|
231
|
-
new_header_info = parse_content_type(content_type.to_s)
|
232
|
-
prev_header_info = parsed_content_type_header
|
233
|
-
charset = new_header_info.charset || prev_header_info.charset
|
234
|
-
charset ||= self.class.default_charset unless prev_header_info.mime_type
|
235
|
-
set_content_type new_header_info.mime_type, charset
|
236
|
-
end
|
237
|
-
|
238
228
|
# Sets the HTTP response's content MIME type. For example, in the controller
|
239
229
|
# you could write this:
|
240
230
|
#
|
@@ -243,8 +233,32 @@ module ActionDispatch # :nodoc:
|
|
243
233
|
# If a character set has been defined for this response (see charset=) then
|
244
234
|
# the character set information will also be included in the content type
|
245
235
|
# information.
|
236
|
+
def content_type=(content_type)
|
237
|
+
return unless content_type
|
238
|
+
new_header_info = parse_content_type(content_type.to_s)
|
239
|
+
prev_header_info = parsed_content_type_header
|
240
|
+
charset = new_header_info.charset || prev_header_info.charset
|
241
|
+
charset ||= self.class.default_charset unless prev_header_info.mime_type
|
242
|
+
set_content_type new_header_info.mime_type, charset
|
243
|
+
end
|
246
244
|
|
245
|
+
# Content type of response.
|
247
246
|
def content_type
|
247
|
+
if self.class.return_only_media_type_on_content_type
|
248
|
+
ActiveSupport::Deprecation.warn(
|
249
|
+
"Rails 6.1 will return Content-Type header without modification." \
|
250
|
+
" If you want just the MIME type, please use `#media_type` instead."
|
251
|
+
)
|
252
|
+
|
253
|
+
content_type = super
|
254
|
+
content_type ? content_type.split(/;\s*charset=/)[0].presence : content_type
|
255
|
+
else
|
256
|
+
super.presence
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# Media type of response.
|
261
|
+
def media_type
|
248
262
|
parsed_content_type_header.mime_type
|
249
263
|
end
|
250
264
|
|
@@ -405,13 +419,18 @@ module ActionDispatch # :nodoc:
|
|
405
419
|
end
|
406
420
|
|
407
421
|
private
|
408
|
-
|
409
422
|
ContentTypeHeader = Struct.new :mime_type, :charset
|
410
423
|
NullContentTypeHeader = ContentTypeHeader.new nil, nil
|
411
424
|
|
425
|
+
CONTENT_TYPE_PARSER = /
|
426
|
+
\A
|
427
|
+
(?<mime_type>[^;\s]+\s*(?:;\s*(?:(?!charset)[^;\s])+)*)?
|
428
|
+
(?:;\s*charset=(?<quote>"?)(?<charset>[^;\s]+)\k<quote>)?
|
429
|
+
/x # :nodoc:
|
430
|
+
|
412
431
|
def parse_content_type(content_type)
|
413
432
|
if content_type && match = CONTENT_TYPE_PARSER.match(content_type)
|
414
|
-
ContentTypeHeader.new(match[:
|
433
|
+
ContentTypeHeader.new(match[:mime_type], match[:charset])
|
415
434
|
else
|
416
435
|
NullContentTypeHeader
|
417
436
|
end
|
@@ -458,7 +477,7 @@ module ActionDispatch # :nodoc:
|
|
458
477
|
end
|
459
478
|
|
460
479
|
def assign_default_content_type_and_charset!
|
461
|
-
return if
|
480
|
+
return if media_type
|
462
481
|
|
463
482
|
ct = parsed_content_type_header
|
464
483
|
set_content_type(ct.mime_type || Mime[:html].to_s,
|
@@ -516,4 +535,6 @@ module ActionDispatch # :nodoc:
|
|
516
535
|
end
|
517
536
|
end
|
518
537
|
end
|
538
|
+
|
539
|
+
ActiveSupport.run_load_hooks(:action_dispatch_response, Response)
|
519
540
|
end
|
@@ -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
|