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.rb112
1 files changed, 92 insertions, 20 deletions
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 4da82f958a..796cd8c09b 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -2,6 +2,76 @@ module ActionDispatch
module Http
module URL
mattr_accessor :tld_length
+ self.tld_length = 1
+
+ class << self
+ def extract_domain(host, tld_length = @@tld_length)
+ return nil unless named_host?(host)
+ host.split('.').last(1 + tld_length).join('.')
+ end
+
+ def extract_subdomains(host, tld_length = @@tld_length)
+ return [] unless named_host?(host)
+ parts = host.split('.')
+ parts[0..-(tld_length+2)]
+ end
+
+ def extract_subdomain(host, tld_length = @@tld_length)
+ extract_subdomains(host, tld_length).join('.')
+ end
+
+ def url_for(options = {})
+ unless options[:host].present? || options[:only_path].present?
+ raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
+ end
+
+ rewritten_url = ""
+
+ unless options[:only_path]
+ rewritten_url << (options[:protocol] || "http")
+ rewritten_url << "://" unless rewritten_url.match("://")
+ rewritten_url << rewrite_authentication(options)
+ rewritten_url << host_or_subdomain_and_domain(options)
+ rewritten_url << ":#{options.delete(:port)}" if options[:port]
+ end
+
+ path = options.delete(:path) || ''
+
+ params = options[:params] || {}
+ params.reject! {|k,v| !v }
+
+ rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
+ rewritten_url << "?#{params.to_query}" unless params.empty?
+ rewritten_url << "##{Rack::Mount::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor]
+ rewritten_url
+ end
+
+ private
+
+ def named_host?(host)
+ !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host))
+ end
+
+ def rewrite_authentication(options)
+ if options[:user] && options[:password]
+ "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
+ else
+ ""
+ end
+ end
+
+ def host_or_subdomain_and_domain(options)
+ return options[:host] unless options[:subdomain] || options[:domain]
+
+ tld_length = options[:tld_length] || @@tld_length
+
+ host = ""
+ host << (options[:subdomain] || extract_subdomain(options[:host], tld_length))
+ host << "."
+ host << (options[:domain] || extract_domain(options[:host], tld_length))
+ host
+ end
+ end
# Returns the complete URL used for this request.
def url
@@ -35,10 +105,12 @@ module ActionDispatch
# Returns the port number of this request as an integer.
def port
- if raw_host_with_port =~ /:(\d+)$/
- $1.to_i
- else
- standard_port
+ @port ||= begin
+ if raw_host_with_port =~ /:(\d+)$/
+ $1.to_i
+ else
+ standard_port
+ end
end
end
@@ -55,10 +127,16 @@ module ActionDispatch
port == standard_port
end
- # Returns a \port suffix like ":8080" if the \port number of this request
+ # Returns a number \port suffix like 8080 if the \port number of this request
# is not the default HTTP \port 80 or HTTPS \port 443.
+ def optional_port
+ standard_port? ? nil : port
+ end
+
+ # Returns a string \port suffix, including colon, like ":8080" if the \port
+ # number of this request is not the default HTTP \port 80 or HTTPS \port 443.
def port_string
- port == standard_port ? '' : ":#{port}"
+ standard_port? ? '' : ":#{port}"
end
def server_port
@@ -67,10 +145,8 @@ module ActionDispatch
# Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
# a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
- def domain(tld_length = 1)
- return nil unless named_host?(host)
-
- host.split('.').last(1 + tld_length).join('.')
+ def domain(tld_length = @@tld_length)
+ ActionDispatch::Http::URL.extract_domain(host, tld_length)
end
# Returns all the \subdomains as an array, so <tt>["dev", "www"]</tt> would be
@@ -78,19 +154,15 @@ module ActionDispatch
# such as 2 to catch <tt>["www"]</tt> instead of <tt>["www", "rubyonrails"]</tt>
# in "www.rubyonrails.co.uk".
def subdomains(tld_length = @@tld_length)
- return [] unless named_host?(host)
- parts = host.split('.')
- parts[0..-(tld_length+2)]
+ ActionDispatch::Http::URL.extract_subdomains(host, tld_length)
end
+ # Returns all the \subdomains as a string, so <tt>"dev.www"</tt> would be
+ # returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
+ # such as 2 to catch <tt>["www"]</tt> instead of <tt>"www.rubyonrails"</tt>
+ # in "www.rubyonrails.co.uk".
def subdomain(tld_length = @@tld_length)
- subdomains(tld_length).join('.')
- end
-
- private
-
- def named_host?(host)
- !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host))
+ subdomains(tld_length)
end
end
end