Trie-based routing with Mustermann

Correct. The version I’m playing with right now would create one route set and give you the matched pattern, params, and a custom value you can assign to it. I’ve got matching to be fairly performant, and I think I have a way to still match multiple patterns. I think I’ll keep working on it either way and either do a POC with hanami-router, Sinatra, or a custom router to see how it performs on r10k.

Current work in progress API (might not be relevant to Hanami):

set = Mustermann::Set.new(type: :rails)

# Value can be anything, it is optional
set.add("/books/:id", "books.show")
set.add("/authors", "authors.index")
set.add("/books/:book_id/authors", "authors.index")

# matching
match = set.match("/books/1/authors")
match.value # => "authors.index"
match.params # => { "book_id" => "1" }

# expansion
set.expand("authors.index", {}) # => "/authors"
set.expand("authors.index", { books_id: 1 } # => "/books/1/authors"

Not sure what the impact would be compared to the current hanami-router implementation (happy to try it out and leave it be if it isn’t significant).

The trie already accounts for escaped and unescaped characters, which further avoids calls to URI when requests come in.

Where I’m at right now with optimizations is a 2,500x speedup (not missing a percentage sign) on matching of r10k-style routes (10k routes, 4 levels of nesting) compared to looping through an array of patterns, which is what Sinatra does.

My biggest concern is if this will work for complex scenarios, ie where a regular expression would perform backtracking. But maybe not supporting these is a fair-enough trade-off? I also feel like this is more an issue for Sinatra users, where /foo/*/bar/* might actually be in use. Hm… maybe I could just compile everything into one big regexp from the first splat on.