Fix redirects when using non-standard ports.

Commit 507972ee introduced a change to the redirect method in order to
be compliant with RFC 2616's requirement that the Location header use an
"absoluteURI". However, the change relied on an undefined "port"
variable. This commit fixes that omission by using the port from the
request.

The formatting of the redirect method has also been adjusted to wrap at
approx. 78-80 characters and use "&&" and "||", like the rest of Sinatra.

Specs included.
This commit is contained in:
Anthony Williams 2010-09-01 16:03:50 +01:00 committed by Konstantin Haase
parent 4cab214ca6
commit 1e755d5d9b
2 changed files with 35 additions and 6 deletions

View File

@ -97,13 +97,18 @@ module Sinatra
# Halt processing and redirect to the URI provided.
def redirect(uri, *args)
if not uri =~ /^https?:\/\//
# According to RFC 2616 section 14.30, “the field value consists of a single absolute URI”
abs_uri = request.scheme + "://"
abs_uri << request.host
abs_uri << ":#{port}" if request.scheme == "https" and request.port != 443 or request.scheme == "http" and request.port != 80
abs_uri << uri
uri = abs_uri
# According to RFC 2616 section 14.30, "the field value consists of a
# single absolute URI"
abs_uri = "#{request.scheme}://#{request.host}"
if request.scheme == 'https' && request.port != 443 ||
request.scheme == 'http' && request.port != 80
abs_uri << ":#{request.port}"
end
uri = (abs_uri << uri)
end
status 302
response['Location'] = uri
halt(*args)

View File

@ -87,6 +87,30 @@ class HelpersTest < Test::Unit::TestCase
assert_equal 302, response.status
assert_equal 'http://example.org/foo', response['Location']
end
it 'redirects using a non-standard HTTP port' do
mock_app {
get '/' do
redirect '/foo'
end
}
request = Rack::MockRequest.new(@app)
response = request.get('/', 'SERVER_PORT' => '81')
assert_equal 'http://example.org:81/foo', response['Location']
end
it 'redirects using a non-standard HTTPS port' do
mock_app {
get '/' do
redirect '/foo'
end
}
request = Rack::MockRequest.new(@app)
response = request.get('/', 'SERVER_PORT' => '444')
assert_equal 'http://example.org:444/foo', response['Location']
end
end
describe 'error' do