aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/http/url.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/http/url.rb')
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb105
1 files changed, 58 insertions, 47 deletions
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 4cba4f5f37..6ba2820d09 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -5,45 +5,47 @@ module ActionDispatch
module Http
module URL
IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
- HOST_REGEXP = /(^.*:\/\/)?([^:]+)(?::(\d+$))?/
+ HOST_REGEXP = /(^[^:]+:\/\/)?([^:]+)(?::(\d+$))?/
PROTOCOL_REGEXP = /^([^:]+)(:)?(\/\/)?$/
mattr_accessor :tld_length
self.tld_length = 1
class << self
- def extract_domain(host, tld_length = @@tld_length)
- host.split('.').last(1 + tld_length).join('.') if named_host?(host)
+ def extract_domain(host, tld_length)
+ extract_domain_from(host, tld_length) if named_host?(host)
end
- def extract_subdomains(host, tld_length = @@tld_length)
+ def extract_subdomains(host, tld_length)
if named_host?(host)
- parts = host.split('.')
- parts[0..-(tld_length + 2)]
+ extract_subdomains_from(host, tld_length)
else
[]
end
end
- def extract_subdomain(host, tld_length = @@tld_length)
+ def extract_subdomain(host, tld_length)
extract_subdomains(host, tld_length).join('.')
end
def url_for(options)
- unless options[:host] || options[:only_path]
+ host = options[:host]
+ unless host || options[:only_path]
raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
end
path = options[:script_name].to_s.chomp("/")
path << options[:path].to_s
- add_trailing_slash(path) if options[:trailing_slash]
+ path = add_trailing_slash(path) if options[:trailing_slash]
- result = path
-
- unless options[:only_path]
- result.prepend build_host_url(options)
- end
+ result = if options[:only_path]
+ path
+ else
+ protocol = options[:protocol]
+ port = options[:port]
+ build_host_url(host, port, protocol, options).concat path
+ end
if options.key? :params
params = options[:params].is_a?(Hash) ?
@@ -60,6 +62,15 @@ module ActionDispatch
private
+ def extract_domain_from(host, tld_length)
+ host.split('.').last(1 + tld_length).join('.')
+ end
+
+ def extract_subdomains_from(host, tld_length)
+ parts = host.split('.')
+ parts[0..-(tld_length + 2)]
+ end
+
def add_trailing_slash(path)
# includes querysting
if path.include?('?')
@@ -72,39 +83,36 @@ module ActionDispatch
path
end
- def build_host_url(options)
- if match = options[:host].match(HOST_REGEXP)
- options[:protocol] ||= match[1] unless options[:protocol] == false
- options[:host] = match[2]
- options[:port] = match[3] unless options.key?(:port)
+ def build_host_url(host, port, protocol, options)
+ if match = host.match(HOST_REGEXP)
+ protocol ||= match[1] unless protocol == false
+ host = match[2]
+ port = match[3] unless options.key? :port
end
- options[:protocol] = normalize_protocol(options)
- options[:host] = normalize_host(options)
- options[:port] = normalize_port(options)
+ protocol = normalize_protocol protocol
+ host = normalize_host(host, options)
- result = options[:protocol]
+ result = protocol.dup
if options[:user] && options[:password]
result << "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
end
- result << options[:host]
- result << ":#{options[:port]}" if options[:port]
+ result << host
+ normalize_port(port, protocol) { |normalized_port|
+ result << ":#{normalized_port}"
+ }
result
end
def named_host?(host)
- host && IP_HOST_REGEXP !~ host
- end
-
- def same_host?(options)
- (options[:subdomain] == true || !options.key?(:subdomain)) && options[:domain].nil?
+ IP_HOST_REGEXP !~ host
end
- def normalize_protocol(options)
- case options[:protocol]
+ def normalize_protocol(protocol)
+ case protocol
when nil
"http://"
when false, "//"
@@ -112,36 +120,39 @@ module ActionDispatch
when PROTOCOL_REGEXP
"#{$1}://"
else
- raise ArgumentError, "Invalid :protocol option: #{options[:protocol].inspect}"
+ raise ArgumentError, "Invalid :protocol option: #{protocol.inspect}"
end
end
- def normalize_host(options)
- return options[:host] if !named_host?(options[:host]) || same_host?(options)
+ def normalize_host(_host, options)
+ return _host unless named_host?(_host)
tld_length = options[:tld_length] || @@tld_length
+ subdomain = options.fetch :subdomain, true
+ domain = options[:domain]
host = ""
- if options[:subdomain] == true || !options.key?(:subdomain)
- host << extract_subdomain(options[:host], tld_length).to_param
- elsif options[:subdomain].present?
- host << options[:subdomain].to_param
+ if subdomain == true
+ return _host if domain.nil?
+
+ host << extract_subdomains_from(_host, tld_length).join('.')
+ elsif subdomain
+ host << subdomain.to_param
end
host << "." unless host.empty?
- host << (options[:domain] || extract_domain(options[:host], tld_length))
+ host << (domain || extract_domain_from(_host, tld_length))
host
end
- def normalize_port(options)
- return nil if options[:port].nil? || options[:port] == false
+ def normalize_port(port, protocol)
+ return unless port
- case options[:protocol]
- when "//"
- options[:port]
+ case protocol
+ when "//" then yield port
when "https://"
- options[:port].to_i == 443 ? nil : options[:port]
+ yield port unless port.to_i == 443
else
- options[:port].to_i == 80 ? nil : options[:port]
+ yield port unless port.to_i == 80
end
end
end