hanami / router

Ruby/Rack HTTP router
http://hanamirb.org
MIT License
362 stars 92 forks source link

Trie routing #199

Closed jodosha closed 4 years ago

jodosha commented 4 years ago

Enhancement

TL;DR: After the first rewriting (v2.0.0-alpha1), I discovered that the performance were terrible. Starting from late August 2019, I rewrote the router again using a trie based mechanism.

Performance

Performance now are astonishing.

framework version req/s
hanami-router v2.0.0-alpha2 8,970.00
roda v3.28.0 6,697.95
sinatra v2.0.8.1 47.68

See the full details of the benchmark.

Fewer dependencies

In order to make hanami-router more efficient and more appealing for adoption, I removed the following dependencies from v2.0.0-alpha1:

Removed features

Endpoint lookup

Previous versions of hanami-router had the ability of loading endpoints starting from strings. A classic example was the integration with hanami-controller (Hanami::Action). Example:

Hanami::Router.new do
  get "/", to: "home#index"
end

The router had to understand that syntax, translate into Home::Index class, and try to lookup it into the right Ruby namespace: root (::Home::Index), or inside an app namespace (Web::Controllers::Home::Index), to pass the proper Hanami::Controller::Configuration, and to store the action.

IMO this was too much responsibility for hanami-router, and it complicated a lot the execution of Hanami::Router#initialize.

Since now on, to: will only accept Rack endpoints.

RESTful resource(s)

For similar reasons, I had to remove RESTful resource(s). This feature was based on endpoint lookup (see previous point), and on inflection rules. Because the first was removed, there was no need to keep dry-inflector around.

IMPORTANT note regarding those features

The features above were moved from hanami-router to hanami. That means final Hanami users will still be able to use these features.

New Feature

I also introduced a new feature called block syntax:

Hanami::Router.new do
  get "/" do
    "Hello, World"
  end
end

The last returning value of the block is used as body of the Rack response.

Note for the reviewers

There are a few details to smooth, a few test cases to make it pass, API documentation to produce, but I wanted to finally present the results of 5 months of work.