Pendragon
Pendragon provides an HTTP router for use in Rack and Padrino. As a Rack application, it makes it easy to define complicated routing. As a Padrino plugin, your application uses Pendragon instead of http_router. Therefore, some bugs of http_router will be fixed.
If you want to use in Ruby1.9, you can do it by using mustermann/1.9-support branch.
Pendragon.new do
get("/"){ "hello world" }
get("/foo/:bar", name: :foo) do |params|
"foo is #{params[:bar]}"
end
end
Installation
Depends on rack and mustermann.
gem install pendragon
Usage
Configuration
name | types | default | description |
---|---|---|---|
enable_compiler | boolean | false | The performance will be improved. However, it will increase the first load time. |
auto_rack_format | boolean | true | If disable this param, the block of route should return the response of valid rack format. |
lock | boolean | false | If you enable this option, all requests to synchronize on a mutex lock |
enable_compiler
# Performance will be improved!
Pendragon.new do |config|
config.enable_compiler = true
end
The compiler mode was inspired by rack-multiplexer. Thank you!
auto_rack_format
# Enable the param (default)
Pendragon.new do
get("/"){ "hey" }
end
pendragon = Pendragon.new do |config|
config.auto_rack_format = false
end
# Disable the param
pendragon.get("/"){ [200, {"Content-Type" => "text/html;charset=utf-8"}, ["hey"]] }
lock
pendragon = Pendragon.new do |config|
config.lock = true
end
If you use pendragon in threaded environment, you should enable this option to avoid compiling all routes again and again.
Deprecated
# Global configuration style is deprecated since 0.5.0
Pendragon.configure do |config|
config.enable_compiler = true
end
# Please use new syntax.
pendragon = Pendragon.new do |config|
config.enable_compiler = true
end
Register a route
It has some methods to register a route. For example, #get
, #post
and #delete
are so.
This section introduces all those methods.
add(verb, path, option, &block)
The method is the basis of the registration method of all. In comparison with other registration methods, one argument is increased.
Pendragon.new do
# The two approach have the same meaning.
add(:get, "/"){ "hello world" }
get("/"){ "hello world" }
end
get(path, option, &block)
, post
, delete
, put
and head
Basically the usage is the same with #add
.
You may as well use those methods instead of #add
because those methods are easy to understand.
Pendragon.new do
get("/"){ "hello world" }
post("/"){ "hello world" }
delete("/"){ "hello world" }
put("/"){ "hello world" }
head("/"){ "hello world" }
end
Path
The path must be an instance of String (this must be complied with the Mustermann::Sinatra's rule) or Regexp.
Route options
name | types | description |
---|---|---|
name | symbol | specify the name of route for Pendragon::Router#path method. |
order | integer | specify the order for the prioritized routes. |
capture | hash | specify the capture for matching condition. more information here |
status | integer | specify the status code of response |
header | hash | specify the header of response |
Block Parameters
The block is allowed to pass a parameter. It will be an instance of Hash.
pendragon = Pendragon.new do
get("/:id/:foo/:bar"){|params| params.inspect }
end
request = Rack::MockRequest.env_for("/123/hey/ho")
pendragon.recognize(request).first.call #=> '{id: "123", foo: "hey", bar: "ho"}'
Recognize the route
The route registered can be recognized by several methods.
recognize(request)
This method returns all the routes that match the conditions.
The format of returns will be such as [[Pendragon::Route, params], ...]
.
The request must be an instance of Rack::Request
or Hash created by Rack::MockRequest.env_for
.
pendragon = Pendragon.new
index = pendragon.get("/"){ "hello world" }
foo = pendragon.get("/foo/:bar"){ "foo is bar" }
mock_request = Rack::MockRequest.env_for("/")
route, params = pendragon.recognize(mock_request).first
route.path == index.path #=> true
params #=> {}
mock_request = Rack::MockRequest.env_for("/foo/baz")
route, params = pendragon.recognize(mock_request).first
route.path == foo.path #=> true
params #=> {bar: "baz"}
recognize_path(path_info)
Recognizes a route from path_info
.
The method uses #recognize
, but return value is not same with it.
Maybe this is useful if you set the name to the route.
pendragon = Pendragon.new do
get("/", name: :index){ "hello world" }
get("/:id", name: :foo){ "fooooo" }
end
pendragon.recognize_path("/") #=> [:index, {}]
pendragon.recognize_path("/hey") #=> [:foo, {id: "hey"}]
path(name, *args)
Recognizes a route from route's name, and expands the path from parameters.
If you pass a name that does not exist, Pendragon raises InvalidRouteException
.
The parameters that is not required to expand will be treated as query.
pendragon = Pendragon.new do
get("/", name: :index){ "hello world" }
get("/:id", name: :foo){ "fooooo" }
end
pendragon.path(:index) #=> "/"
pendragon.path(:foo, id: "123") #=> "/123"
pendragon.path(:foo, id: "123", bar: "hey") #=> "/123?bar=hey"
Prioritized Routes
Pendragon supports for respecting route order.
If you want to use this, you should pass the :order
option to the registration method.
pendragon = Pendragon.new do
get("/", order: 1){ "two" }
get("/", order: 0){ "one" }
get("/", order: 2){ "three" }
end
request = Rack::MockRequest.env_for("/")
pendragon.recognize(request).map{|route, _| route.call } #=> ["one", "two", "three"]
Passing
A route can punt processing to the next matching route using throw :pass
pendragon = Pendragon.new do
foo = nil
get("/"){ foo = "yay"; throw :pass }
get("/"){ foo }
end
request = Rack::MockRequest.env_for("/")
pendragon.call(request) #=> [200, {"Content-Type"=>"text/html;charset=utf-8"}, ["yay"]]
With Padrino
Add register Pendragon::Padrino
to your padrino application.
Of course, Pendragon has compatibility with Padrino Routing.
require 'pendragon/padrino'
class App < Padrino::Application
register Pendragon::Padrino
# Also, your app's performance will be improved by using compiler mode.
set :pendragon, enable_compiler: true
get :index do
"hello pendragon!"
end
get :users, :map => "/users/:user_id/", :user_id => /\d+/ do |user_id|
params.inspect
end
get :user_items, :map => "/users/:user_id/:item_id", :user_id => /\d+/, :item_id => /[1-9]+/ do |user_id, item_id|
"Show #{user_id} and #{item_id}"
end
end
Contributing
- fork the project.
- create your feature branch. (
git checkout -b my-feature
) - commit your changes. (
git commit -am 'commit message'
) - push to the branch. (
git push origin my-feature
) - send pull request.
License
the MIT License