|
1 | 1 | require 'cgi' |
2 | 2 | require 'forwardable' |
3 | 3 | require 'webmachine/constants' |
| 4 | +require 'ipaddr' |
4 | 5 |
|
5 | 6 | module Webmachine |
6 | 7 | # Request represents a single HTTP request sent from a client. It |
@@ -33,11 +34,11 @@ def method_missing(m, *args, &block) |
33 | 34 | if m =~ HTTP_HEADERS_MATCH |
34 | 35 | # Access headers more easily as underscored methods. |
35 | 36 | header_name = m.to_s.tr(UNDERSCORE, DASH) |
36 | | - if (header_value = headers[header_name]) |
| 37 | + if (header_value = @headers[header_name]) |
37 | 38 | # Make future lookups faster. |
38 | 39 | self.class.class_eval <<-RUBY, __FILE__, __LINE__ |
39 | 40 | def #{m} |
40 | | - headers["#{header_name}"] |
| 41 | + @headers["#{header_name}"] |
41 | 42 | end |
42 | 43 | RUBY |
43 | 44 | end |
@@ -165,19 +166,34 @@ def options? |
165 | 166 |
|
166 | 167 | private |
167 | 168 |
|
168 | | - def build_uri(uri, headers) |
169 | | - uri = URI(uri) |
170 | | - |
171 | | - host, _, port = headers.fetch(HOST, "").rpartition(COLON) |
172 | | - return uri if host.empty? |
| 169 | + IPV6_MATCH = /\A\[(?<address> .* )\]:(?<port> \d+ )\z/x.freeze # string like "[::1]:80" |
| 170 | + HOST_MATCH = /\A(?<host> [^:]+ ):(?<port> \d+ )\z/x.freeze # string like "www.example.com:80" |
| 171 | + |
| 172 | + def parse_host(uri, host_string) |
| 173 | + # Split host and port number from string. |
| 174 | + case host_string |
| 175 | + when IPV6_MATCH |
| 176 | + uri.host = IPAddr.new($~[:address]).to_s |
| 177 | + uri.port = $~[:port].to_i |
| 178 | + when HOST_MATCH |
| 179 | + uri.host = $~[:host] |
| 180 | + uri.port = $~[:port].to_i |
| 181 | + else # string with no port number |
| 182 | + uri.host = host_string |
| 183 | + end |
173 | 184 |
|
174 | | - host = "[#{host}]" if host.include?(COLON) |
175 | | - port = 80 if port.empty? |
| 185 | + uri |
| 186 | + end |
176 | 187 |
|
177 | | - uri.scheme = HTTP |
178 | | - uri.host, uri.port = host, port.to_i |
| 188 | + def build_uri(uri, headers) |
| 189 | + uri = URI(uri) |
| 190 | + uri.port ||= 80 |
| 191 | + uri.scheme ||= HTTP |
| 192 | + if uri.host |
| 193 | + return uri |
| 194 | + end |
179 | 195 |
|
180 | | - URI.parse(uri.to_s) |
| 196 | + parse_host(uri, headers.fetch(HOST)) |
181 | 197 | end |
182 | 198 |
|
183 | 199 | end # class Request |
|
0 commit comments