diff --git a/lib/sinatra/base.rb b/lib/sinatra/base.rb index b41e2cac..f2d60fb4 100644 --- a/lib/sinatra/base.rb +++ b/lib/sinatra/base.rb @@ -109,6 +109,23 @@ module Sinatra halt(*args) end + # Generates the absolute URI for a given path in the app. + # Takes Rack routers and reverse proxies into account. + def uri(addr = nil, absolute = true, add_script_name = true) + return addr if addr =~ /^https?:\/\// + uri = [host = ""] + if absolute + host << "#{request.scheme}://#{request.host}" + host << ":#{request.port}" unless request.port == (request.secure? ? 443 : 80) + end + uri << request.script_name.to_s if add_script_name + uri << (addr ? addr : request.path_info).to_s + File.join uri + end + + alias url uri + alias to uri + # Halt processing and return the error status provided. def error(code, body=nil) code, body = 500, code.to_str if code.respond_to? :to_str diff --git a/test/helpers_test.rb b/test/helpers_test.rb index 612a9996..935cc2ab 100644 --- a/test/helpers_test.rb +++ b/test/helpers_test.rb @@ -694,6 +694,44 @@ class HelpersTest < Test::Unit::TestCase end end + describe 'uri' do + it 'generates absolute urls' do + mock_app { get('/') { uri }} + get '/' + assert_equal 'http://example.org/', body + end + + it 'includes path_info' do + mock_app { get('/:name') { uri }} + get '/foo' + assert_equal 'http://example.org/foo', body + end + + it 'allows passing an alternative to path_info' do + mock_app { get('/:name') { uri '/bar' }} + get '/foo' + assert_equal 'http://example.org/bar', body + end + + it 'includes script_name' do + mock_app { get('/:name') { uri '/bar' }} + get '/foo', {}, { "SCRIPT_NAME" => '/foo' } + assert_equal 'http://example.org/foo/bar', body + end + + it 'is aliased to #url' do + mock_app { get('/') { url }} + get '/' + assert_equal 'http://example.org/', body + end + + it 'is aliased to #to' do + mock_app { get('/') { to }} + get '/' + assert_equal 'http://example.org/', body + end + end + module ::HelperOne; def one; '1'; end; end module ::HelperTwo; def two; '2'; end; end