diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index <HASH>..<HASH> 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -29,7 +29,8 @@ module ActionDispatch
         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
 
@@ -41,7 +42,9 @@ module ActionDispatch
           result = if options[:only_path]
                      path
                    else
-                     build_host_url(options).concat path
+                     protocol = options[:protocol]
+                     port     = options[:port]
+                     build_host_url(host, port, protocol, options).concat path
                    end
 
           if options.key? :params
@@ -80,10 +83,7 @@ module ActionDispatch
           path
         end
 
-        def build_host_url(options)
-          protocol = options[:protocol]
-          host     = options[:host]
-          port     = options[:port]
+        def build_host_url(host, port, protocol, options)
           if match = host.match(HOST_REGEXP)
             protocol           ||= match[1] unless protocol == false
             host                 = match[2]
push host / port / protocol extraction up

Then we only need to extract host once.