Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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.
  • Loading branch information...
commit 12eced84140ce5d1418d7f21f49826ddf4b75c40 1 parent 2aeaf7a
@cypher cypher authored rtomayko committed
Showing with 43 additions and 2 deletions.
  1. +6 −2 lib/sinatra/base.rb
  2. +37 −0 test/routing_test.rb
View
8 lib/sinatra/base.rb
@@ -600,11 +600,15 @@ def route(verb, path, opts={}, &block)
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
37 test/routing_test.rb
@@ -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 @@
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
Please sign in to comment.
Something went wrong with that request. Please try again.