Fix routes don't match with certain forms of URL encoding [#147]

We no longer store routes in URL encoded form and unescape the
PATH_INFO before attempting to match routes. This allows matching
all variations of encoded characters but does not allow matching
encoded "/" characters in the PATH_INFO.

See also:

http://sinatra.lighthouseapp.com/projects/9779/tickets/147
http://groups.google.com/group/sinatrarb/browse_thread/thread/baab6ea877d7c2e4
This commit is contained in:
Ryan Tomayko 2009-02-17 08:07:37 -08:00
parent 1472b6af28
commit d212de6abf
2 changed files with 17 additions and 5 deletions

View File

@ -372,11 +372,11 @@ module Sinatra
# routes
if routes = self.class.routes[@request.request_method]
original_params = @params
path = @request.path_info
path = unescape(@request.path_info)
routes.each do |pattern, keys, conditions, block|
if match = pattern.match(path)
values = match.captures.map{|val| val && unescape(val) }
values = match.captures.to_a
params =
if keys.any?
keys.zip(values).inject({}) do |hash,(k,v)|
@ -673,7 +673,7 @@ module Sinatra
if path.respond_to? :to_str
special_chars = %w{. + ( )}
pattern =
URI.encode(path).gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
path.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
case match
when "*"
keys << 'splat'

View File

@ -158,7 +158,7 @@ describe "Routing" do
it "literally matches + in paths" do
route_def '/te+st/'
get '/te+st/'
get '/te%2Bst/'
assert ok?
get '/teeeeeeest/'
assert not_found?
@ -243,7 +243,7 @@ describe "Routing" do
assert_equal 'looks good', body
end
it "supports paths that include spaces" do
it "matches paths that include spaces encoded with %20" do
mock_app {
get '/path with spaces' do
'looks good'
@ -255,6 +255,18 @@ describe "Routing" do
assert_equal 'looks good', body
end
it "matches paths that include spaces encoded with +" do
mock_app {
get '/path with spaces' do
'looks good'
end
}
get '/path+with+spaces'
assert ok?
assert_equal 'looks good', body
end
it "URL decodes named parameters and splats" do
mock_app {
get '/:foo/*' do