From c8d20afc54d07a53b3a56cb042f95470e11b732d Mon Sep 17 00:00:00 2001 From: Luis Lavena Date: Sat, 12 Nov 2016 12:49:23 -0300 Subject: [PATCH] fix(Tree): allows catch all to be used as optional globbing Catch all parameter was limited to be used *after* a slash (`/`) on a path (ie. `/members/*trailing`). Attempts to use it immediately after the path (ie. `/members*trailing`) was not properly identified or captured. This change ensures catch all can be used as globbing, allowing capture of anything after the matching path. Closes #12 --- CHANGELOG.md | 2 ++ spec/radix/tree_spec.cr | 29 +++++++++++++++++++++++++---- src/radix/tree.cr | 10 ++++++---- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd7c10d..0755fbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project aims to comply with [Semantic Versioning](http://semver.org/), so please check *Changed* and *Removed* notes before upgrading. ## [Unreleased] +### Fixed +- Ensure catch all parameter can be used as optional globbing (@jwoertink) ## [0.3.2] - 2016-11-05 ### Fixed diff --git a/spec/radix/tree_spec.cr b/spec/radix/tree_spec.cr index a01085a..82bdcec 100644 --- a/spec/radix/tree_spec.cr +++ b/spec/radix/tree_spec.cr @@ -279,7 +279,7 @@ module Radix result.found?.should be_false end - it "finds when using matching path" do + it "finds when key and path matches" do tree = Tree(Symbol).new tree.add "/about", :about @@ -290,7 +290,7 @@ module Radix result.payload.should eq(:about) end - it "finds when using path with trailing slash" do + it "finds when path contains trailing slash" do tree = Tree(Symbol).new tree.add "/about", :about @@ -299,7 +299,7 @@ module Radix result.key.should eq("/about") end - it "finds when key has trailing slash" do + it "finds when key contains trailing slash" do tree = Tree(Symbol).new tree.add "/about/", :about @@ -363,7 +363,7 @@ module Radix result.params["filepath"].should eq("src/file.png") end - it "returns optional catch all" do + it "returns optional catch all after slash" do tree = Tree(Symbol).new tree.add "/", :root tree.add "/search/*extra", :extra @@ -375,6 +375,17 @@ module Radix result.params["extra"].empty?.should be_true end + it "returns optional catch all by globbing" do + tree = Tree(Symbol).new + tree.add "/members*trailing", :members_catch_all + + result = tree.find("/members") + result.found?.should be_true + result.key.should eq("/members*trailing") + result.params.has_key?("trailing").should be_true + result.params["trailing"].empty?.should be_true + end + it "does not find when catch all is not full match" do tree = Tree(Symbol).new tree.add "/", :root @@ -383,6 +394,16 @@ module Radix result = tree.find("/search") result.found?.should be_false end + + it "does prefer specific path over catch all if both are present" do + tree = Tree(Symbol).new + tree.add "/members", :members + tree.add "/members*trailing", :members_catch_all + + result = tree.find("/members") + result.found?.should be_true + result.key.should eq("/members") + end end context "dealing with named parameters" do diff --git a/src/radix/tree.cr b/src/radix/tree.cr index 993b08f..8c23e47 100644 --- a/src/radix/tree.cr +++ b/src/radix/tree.cr @@ -336,10 +336,12 @@ module Radix # check if remaining part is catch all if key_reader.pos < node.key.size && - key_reader.current_char == '/' && - key_reader.peek_next_char == '*' - # skip '*' - key_reader.next_char + ((key_reader.current_char == '/' && key_reader.peek_next_char == '*') || + key_reader.current_char == '*') + # skip to '*' only if necessary + unless key_reader.current_char == '*' + key_reader.next_char + end # deal with catch all, but since there is nothing in the path # return parameter as empty