sort routes for more specific results
This change sorts the routes to get the most specific routes first and avoid hitting a route which is not the most specific match. With this the regex to extract variables is made more strict to avoid matching half of the URI.
This commit is contained in:
parent
c55441f990
commit
defb7703c6
|
@ -20,7 +20,7 @@ module Zero
|
|||
# match for variables in routes
|
||||
VARIABLE_MATCH = %r{:(\w+)[^/]?}
|
||||
# the replacement string to make it an regex
|
||||
VARIABLE_REGEX = '(?<\1>.+?)'
|
||||
VARIABLE_REGEX = '(?<\1>[\w]+?)'
|
||||
# regex part of the beginning of the line
|
||||
REGEX_BEGINNING = '\A'
|
||||
# regex part of the end of the line
|
||||
|
@ -41,7 +41,7 @@ module Zero
|
|||
# @param routes [Hash] a map of URLs to rack compatible applications
|
||||
def initialize(routes)
|
||||
@routes = {}
|
||||
routes.each do |route, target|
|
||||
routes.to_a.sort_by(&:first).reverse.each do |route, target|
|
||||
@routes[
|
||||
Regexp.new(REGEX_BEGINNING +
|
||||
route.gsub(VARIABLE_MATCH, VARIABLE_REGEX) +
|
||||
|
|
|
@ -44,6 +44,22 @@ describe Zero::Router, '#call' do
|
|||
it_behaves_like "a sample app"
|
||||
end
|
||||
|
||||
context 'with nested variable routes' do
|
||||
let(:routes) do
|
||||
{ '/' => wrong_app, '/foo/:id' => app, '/foo/:id/bar' => wrong_app }
|
||||
end
|
||||
let(:env) { EnvGenerator.get('/foo/23') }
|
||||
it_behaves_like "a sample app"
|
||||
end
|
||||
|
||||
context 'with nested routes and variable in the middle' do
|
||||
let(:routes) do
|
||||
{ '/' => wrong_app, '/foo/:id' => wrong_app, '/foo/:id/bar' => app }
|
||||
end
|
||||
let(:env) { EnvGenerator.get('/foo/23/bar') }
|
||||
it_behaves_like "a sample app"
|
||||
end
|
||||
|
||||
context 'with a route not found' do
|
||||
let(:routes) {{ '/foo' => wrong_app, '/foo/bar/baz' => app }}
|
||||
let(:env) { EnvGenerator.get('/foo/bar') }
|
||||
|
@ -72,4 +88,19 @@ describe Zero::Router, '#call' do
|
|||
|
||||
it_behaves_like 'a sample app'
|
||||
end
|
||||
|
||||
context 'with parameters and nested routes' do
|
||||
let(:routes) do
|
||||
{ '/' => wrong_app, '/foo/:id' => app, '/foo/:id/bar' => wrong_app }
|
||||
end
|
||||
let(:env) { EnvGenerator.get('/foo/bar') }
|
||||
let(:app) do
|
||||
lambda do |env|
|
||||
[200, content_type, [Zero::Request.new(env).params['id']]]
|
||||
end
|
||||
end
|
||||
let(:result) { ['bar'] }
|
||||
|
||||
it_behaves_like "a sample app"
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue