Escape '.', '+', '$' and parens in literal paths [#124]

Since Sinatra turns literal paths into a regular expression,
we need to escape dots and pluses, as they have special
meanings inside a regex, but not ?, since we need that
for optional parameters.
This commit is contained in:
Markus Prinz 2009-01-22 22:54:15 +01:00 committed by Ryan Tomayko
parent 2aeaf7ab58
commit 12eced8414
2 changed files with 43 additions and 2 deletions

View File

@ -600,11 +600,15 @@ module Sinatra
def compile(path)
keys = []
if path.respond_to? :to_str
special_chars = %w{. + ( )}
pattern =
URI.encode(path).gsub(/((:\w+)|\*)/) do |match|
if match == "*"
URI.encode(path).gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
case match
when "*"
keys << 'splat'
"(.*?)"
when *special_chars
Regexp.escape(match)
else
keys << $2[1..-1]
"([^/?&#\.]+)"

View File

@ -1,5 +1,10 @@
require File.dirname(__FILE__) + '/helper'
# Helper method for easy route pattern matching testing
def route_def(pattern)
mock_app { get(pattern) { } }
end
describe "Routing" do
%w[get put post delete head].each do |verb|
it "defines #{verb.upcase} request handlers with #{verb}" do
@ -119,6 +124,38 @@ describe "Routing" do
assert ok?
end
it "literally matches . in paths" do
route_def '/test.bar'
get '/test.bar'
assert ok?
get 'test0bar'
assert not_found?
end
it "literally matches $ in paths" do
route_def '/test$/'
get '/test$/'
assert ok?
end
it "literally matches + in paths" do
route_def '/te+st/'
get '/te+st/'
assert ok?
get '/teeeeeeest/'
assert not_found?
end
it "literally matches () in paths" do
route_def '/test(bar)/'
get '/test(bar)/'
assert ok?
end
it "supports basic nested params" do
mock_app {
get '/hi' do