aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
authorJosh Kalderimis <josh.kalderimis@gmail.com>2010-11-23 00:31:03 +0100
committerJosé Valim <jose.valim@gmail.com>2010-11-23 09:54:42 +0100
commit2fe43b694f36ddb2062a91eebe61a035147265b1 (patch)
treeea99e4fc380ce7b836a3a332337fbdaad4e4f84f /actionpack/lib/action_dispatch
parent9938a3fc78bf8e066d2cdfe17f3710e0e6b85a36 (diff)
downloadrails-2fe43b694f36ddb2062a91eebe61a035147265b1.tar.gz
rails-2fe43b694f36ddb2062a91eebe61a035147265b1.tar.bz2
rails-2fe43b694f36ddb2062a91eebe61a035147265b1.zip
:subdomain, :domain and :tld_length options can now be used in url_for, allowing for easy manipulation of the host during link generation.
Signed-off-by: José Valim <jose.valim@gmail.com>
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb59
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb38
-rw-r--r--actionpack/lib/action_dispatch/routing/url_for.rb6
3 files changed, 77 insertions, 26 deletions
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 9c9eed2c6d..1f7633cbea 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -4,6 +4,27 @@ module ActionDispatch
mattr_accessor :tld_length
self.tld_length = 1
+ def self.extract_domain(host, tld_length = @@tld_length)
+ return nil unless named_host?(host)
+
+ host.split('.').last(1 + tld_length).join('.')
+ end
+
+ def self.extract_subdomains(host, tld_length = @@tld_length)
+ return [] unless named_host?(host)
+ parts = host.split('.')
+ parts[0..-(tld_length+2)]
+ end
+
+ def self.extract_subdomain(host, tld_length = @@tld_length)
+ extract_subdomains(host, tld_length).join('.')
+ end
+
+ def self.named_host?(host)
+ !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host))
+ end
+
+
# Returns the complete URL used for this request.
def url
protocol + host_with_port + fullpath
@@ -31,15 +52,18 @@ module ActionDispatch
# Returns a \host:\port string for this request, such as "example.com" or
# "example.com:8080".
def host_with_port
- "#{host}#{port_string}"
+ opt_port = optional_port ? ":#{optional_port}" : nil
+ "#{host}#{opt_port}"
end
# 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
@@ -56,10 +80,10 @@ module ActionDispatch
port == standard_port
end
- # Returns a \port suffix like ":8080" if the \port number of this request
+ # Returns a \port suffix 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}"
+ def optional_port
+ standard_port? ? nil : port
end
def server_port
@@ -69,9 +93,7 @@ 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 = @@tld_length)
- return nil unless named_host?(host)
-
- host.split('.').last(1 + tld_length).join('.')
+ ActionDispatch::Http::URL.extract_domain(host, tld_length)
end
# Returns all the \subdomains as an array, so <tt>["dev", "www"]</tt> would be
@@ -79,20 +101,17 @@ 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('.')
+ subdomains(tld_length)
end
- private
-
- def named_host?(host)
- !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host))
- end
end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 32f41934f1..d823fd710e 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -485,7 +485,8 @@ module ActionDispatch
Generator.new(options, recall, self, extras).generate
end
- RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :script_name]
+ RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length,
+ :trailing_slash, :script_name, :anchor, :params, :only_path ]
def _generate_prefix(options = {})
nil
@@ -504,11 +505,8 @@ module ActionDispatch
rewritten_url << (options[:protocol] || "http")
rewritten_url << "://" unless rewritten_url.match("://")
rewritten_url << rewrite_authentication(options)
-
- raise "Missing host to link to! Please provide :host parameter or set default_url_options[:host]" unless options[:host]
-
- rewritten_url << options[:host]
- rewritten_url << ":#{options.delete(:port)}" if options.key?(:port)
+ rewritten_url << host_from_options(options)
+ rewritten_url << ":#{options.delete(:port)}" if options[:port]
end
script_name = options.delete(:script_name)
@@ -562,6 +560,34 @@ module ActionDispatch
end
private
+
+ def host_from_options(options)
+ computed_host = subdomain_and_domain(options) || options[:host]
+ unless computed_host
+ raise ArgumentError, "Missing host to link to! Please provide :host parameter or set default_url_options[:host]"
+ end
+ computed_host
+ end
+
+ def subdomain_and_domain(options)
+ tld_length = options[:tld_length] || ActionDispatch::Http::URL.tld_length
+
+ current_domain = ActionDispatch::Http::URL.extract_domain(options[:host], tld_length)
+ current_subdomain = ActionDispatch::Http::URL.extract_subdomain(options[:host], tld_length)
+
+ domain_parts = if options[:subdomain] && options[:domain]
+ [options[:subdomain], options[:domain]]
+ elsif options[:subdomain]
+ [options[:subdomain], current_domain]
+ elsif options[:domain]
+ [current_subdomain, options[:domain]]
+ else
+ nil
+ end
+
+ domain_parts ? domain_parts.join('.') : nil
+ end
+
def handle_positional_args(options)
return unless args = options.delete(:_positional_args)
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index bfdea41f60..6c3fc5126a 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -115,6 +115,12 @@ module ActionDispatch
# * <tt>:host</tt> - Specifies the host the link should be targeted at.
# If <tt>:only_path</tt> is false, this option must be
# provided either explicitly, or via +default_url_options+.
+ # * <tt>:subdomain</tt> - Specifies the subdomain of the link, using the +tld_length+
+ # to split the domain from the host.
+ # * <tt>:domain</tt> - Specifies the domain of the link, using the +tld_length+
+ # to split the subdomain from the host.
+ # * <tt>:tld_length</tt> - Optionally specify the tld length (only used if :subdomain
+ # or :domain are supplied).
# * <tt>:port</tt> - Optionally specify the port to connect to.
# * <tt>:anchor</tt> - An anchor name to be appended to the path.
# * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2009/"