Rack compatible, lightweight and fast HTTP Router for Lotus.
- Home page: http://lotusrb.org
- Mailing List: http://lotusrb.org/mailing-list
- API Doc: http://rdoc.info/gems/lotus-router
- Bugs/Issues: https://github.com/lotus/router/issues
- Support: http://stackoverflow.com/questions/tagged/lotus-ruby
- Chat: https://gitter.im/lotus/chat
Lotus::Router supports Ruby (MRI) 2+ and JRuby 1.7 (with 2.0 mode)
Add this line to your application's Gemfile:
gem 'lotus-router'
And then execute:
$ bundle
Or install it yourself as:
$ gem install lotus-router
require 'lotus/router'
app = Lotus::Router.new do
get '/', to: ->(env) { [200, {}, ['Welcome to Lotus::Router!']] }
end
Rack::Server.start app: app, Port: 2306
Lotus::Router is designed to work as a standalone framework or within a context of a Lotus application.
For the standalone usage, it supports neat features:
Lotus::Router.new do
get '/', to: ->(env) { [200, {}, ['Hi!']] }
get '/dashboard', to: DashboardController::Index
get '/rack-app', to: RackApp.new
get '/flowers', to: 'flowers#index'
get '/flowers/:id', to: 'flowers#show'
redirect '/legacy', to: '/'
mount Api::App, to: '/api'
namespace 'admin' do
get '/users', to: UsersController::Index
end
resource 'identity' do
member do
get '/avatar'
end
collection do
get '/api_keys'
end
end
resources 'robots' do
member do
patch '/activate'
end
collection do
get '/search'
end
end
end
router = Lotus::Router.new
router.get '/lotus', to: ->(env) { [200, {}, ['Hello from Lotus!']] }
router = Lotus::Router.new
router.get '/flowers/:id', to: ->(env) { [200, {}, ["Hello from Flower no. #{ env['router.params'][:id] }!"]] }
router = Lotus::Router.new
router.get '/flowers/:id', id: /\d+/, to: ->(env) { [200, {}, [":id must be a number!"]] }
router = Lotus::Router.new
router.get '/*', to: ->(env) { [200, {}, ["This is catch all: #{ env['router.params'].inspect }!"]] }
router = Lotus::Router.new
router.get '/lotus(.:format)' to: ->(env) { [200, {}, ["You've requested #{ env['router.params'][:format] }!"]] }
router = Lotus::Router.new
endpoint = ->(env) { [200, {}, ['Hello from Lotus!']] }
router.get '/lotus', to: endpoint
router.post '/lotus', to: endpoint
router.put '/lotus', to: endpoint
router.patch '/lotus', to: endpoint
router.delete '/lotus', to: endpoint
router.trace '/lotus', to: endpoint
router = Lotus::Router.new
router.get '/redirect_destination', to: ->(env) { [200, {}, ['Redirect destination!']] }
router.redirect '/legacy', to: '/redirect_destination'
router = Lotus::Router.new(scheme: 'https', host: 'lotusrb.org')
router.get '/lotus', to: ->(env) { [200, {}, ['Hello from Lotus!']] }, as: :lotus
router.path(:lotus) # => "/lotus"
router.url(:lotus) # => "https://lotusrb.org/lotus"
router = Lotus::Router.new
router.namespace 'animals' do
namespace 'mammals' do
get '/cats', to: ->(env) { [200, {}, ['Meow!']] }, as: :cats
end
end
# or
router.get '/cats', prefix: '/animals/mammals', to:->(env) { [200, {}, ['Meow!']] }, as: :cats
# and it generates:
router.path(:animals_mammals_cats) # => "/animals/mammals/cats"
Lotus::Router.new do
mount RackOne, at: '/rack1'
mount RackTwo, at: '/rack2'
mount RackThree.new, at: '/rack3'
mount ->(env) {[200, {}, ['Rack Four']]}, at: '/rack4'
mount 'dashboard#index', at: '/dashboard'
end
RackOne
is used as it is (class), because it respond to.call
RackTwo
is initialized, because it respond to#call
RackThree
is used as it is (object), because it respond to#call
- That Proc is used as it is, because it respond to
#call
- That string is resolved as
DashboardController::Index
(Lotus::Controller integration)
Everything that responds to #call
is invoked as it is:
router = Lotus::Router.new
router.get '/lotus', to: ->(env) { [200, {}, ['Hello from Lotus!']] }
router.get '/middleware', to: Middleware
router.get '/rack-app', to: RackApp.new
router.get '/method', to: ActionControllerSubclass.action(:new)
If it's a string, it tries to instantiate a class from it:
class RackApp
def call(env)
# ...
end
end
router = Lotus::Router.new
router.get '/lotus', to: 'rack_app' # it will map to RackApp.new
It also supports Controller + Action syntax:
class FlowersController
class Index
def call(env)
# ...
end
end
end
router = Lotus::Router.new
router.get '/flowers', to: 'flowers#index' # it will map to FlowersController::Index.new
router = Lotus::Router.new
router.call(Rack::MockRequest.env_for('/unknown')).status # => 404
router = Lotus::Router.new
router.resource 'identity'
It will map:
Verb | Path | Action | Name | Named Route |
---|---|---|---|---|
GET | /identity | IdentityController::Show | :show | :identity |
GET | /identity/new | IdentityController::New | :new | :new_identity |
POST | /identity | IdentityController::Create | :create | :identity |
GET | /identity/edit | IdentityController::Edit | :edit | :edit_identity |
PATCH | /identity | IdentityController::Update | :update | :identity |
DELETE | /identity | IdentityController::Destroy | :destroy | :identity |
If you don't need all the default endpoints, just do:
router = Lotus::Router.new
router.resource 'identity', only: [:edit, :update]
#### which is equivalent to:
router.resource 'identity', except: [:show, :new, :create, :destroy]
If you need extra endpoints:
router = Lotus::Router.new
router.resource 'identity' do
member do
get '/avatar' # maps to IdentityController::Avatar
end
collection do
get '/authorizations' # maps to IdentityController::Authorizations
end
end
router.path(:avatar_identity) # => /identity/avatar
router.path(:authorizations_identity) # => /identity/authorizations
router = Lotus::Router.new
router.resources 'flowers'
It will map:
Verb | Path | Action | Name | Named Route |
---|---|---|---|---|
GET | /flowers | FlowersController::Index | :index | :flowers |
GET | /flowers/:id | FlowersController::Show | :show | :flowers |
GET | /flowers/new | FlowersController::New | :new | :new_flowers |
POST | /flowers | FlowersController::Create | :create | :flowers |
GET | /flowers/:id/edit | FlowersController::Edit | :edit | :edit_flowers |
PATCH | /flowers/:id | FlowersController::Update | :update | :flowers |
DELETE | /flowers/:id | FlowersController::Destroy | :destroy | :flowers |
router.path(:flowers) # => /flowers
router.path(:flowers, id: 23) # => /flowers/23
router.path(:edit_flowers, id: 23) # => /flowers/23/edit
If you don't need all the default endpoints, just do:
router = Lotus::Router.new
router.resources 'flowers', only: [:new, :create, :show]
#### which is equivalent to:
router.resources 'flowers', except: [:index, :edit, :update, :destroy]
If you need extra endpoints:
router = Lotus::Router.new
router.resources 'flowers' do
member do
get '/toggle' # maps to FlowersController::Toggle
end
collection do
get '/search' # maps to FlowersController::Search
end
end
router.path(:toggle_flowers, id: 23) # => /flowers/23/toggle
router.path(:search_flowers) # => /flowers/search
require 'lotus/router'
require 'rack/request'
router = Lotus::Router.new do
get '/', to: ->(env) { [200, {}, ['Hi!']] }
end
app = Rack::MockRequest.new(router)
app.get('/') # => #<Rack::MockResponse:0x007fc4540dc238 ...>
Lotus::Router uses Semantic Versioning 2.0.0
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
Thanks to Joshua Hull (@joshbuddy) for his http_router.
Copyright 2014 Luca Guidi – Released under MIT License