Class: HttpRouter
- Inherits:
-
Object
- Object
- HttpRouter
- Defined in:
- lib/http_router.rb,
lib/http_router/glob.rb,
lib/http_router/node.rb,
lib/http_router/path.rb,
lib/http_router/root.rb,
lib/http_router/route.rb,
lib/http_router/response.rb,
lib/http_router/variable.rb,
lib/http_router/interface/sinatra.rb,
lib/http_router/optional_compiler.rb
Defined Under Namespace
Modules: Interface, Response Classes: ArbitraryNode, Glob, Node, OptionalCompiler, Path, RequestNode, Root, Route, Variable
Constant Summary collapse
- UngeneratableRouteException =
Raised when a Route is not able to be generated.
Class.new(RuntimeError)
- MissingParameterException =
Raised when a Route is not able to be generated due to a missing parameter.
Class.new(RuntimeError)
- InvalidRouteException =
Raised when a Route is generated that isn’t valid.
Class.new(RuntimeError)
- TooManyParametersException =
Raised when a Route is not able to be generated due to too many parameters being passed in.
Class.new(RuntimeError)
- AlreadyCompiledException =
Raised when an already inserted Route has more conditions added.
Class.new(RuntimeError)
- AmbiguousRouteException =
Raised when an ambiguous Route is added. For example, this will be raised if you attempt to add “/foo(/:bar)(/:baz)”.
Class.new(RuntimeError)
- UnsupportedRequestConditionError =
Raised when a request condition is added that is not recognized.
Class.new(RuntimeError)
- AmbiguousVariableException =
Raised when there is a potential conflict of variable names within your Route.
Class.new(RuntimeError)
Instance Attribute Summary collapse
-
#named_routes ⇒ Object
readonly
Returns the value of attribute named_routes.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#routes ⇒ Object
readonly
Returns the value of attribute routes.
Class Method Summary collapse
-
.override_rack_mapper! ⇒ Object
Monkey-patches Rack::Builder to use HttpRouter.
Instance Method Summary collapse
-
#add(path, options = nil) ⇒ Object
Adds a path to be recognized.
-
#add_route(route) ⇒ Object
Adds a route to be recognized.
- #arbitrary_node(*args) ⇒ Object
-
#call(env) ⇒ Object
Rack compatible #call.
-
#clone ⇒ Object
Creates a deep-copy of the router.
-
#default(app) ⇒ Object
Assigns the default application.
-
#delete(path, options = nil) ⇒ Object
Adds a path that only responds to the request method
DELETE. -
#get(path, options = nil) ⇒ Object
Adds a path that only responds to the request methods
GETandHEAD. -
#glob(*args) ⇒ Object
Returns a new glob.
-
#ignore_trailing_slash? ⇒ Boolean
Ignore trailing slash feature enabled? See #initialize for details.
-
#initialize(*args, &block) ⇒ HttpRouter
constructor
Creates a new HttpRouter.
-
#node(*args) ⇒ Object
Returns a new node.
-
#only_get(path, options = nil) ⇒ Object
Adds a path that only responds to the request method
GET. -
#post(path, options = nil) ⇒ Object
Adds a path that only responds to the request method
POST. -
#put(path, options = nil) ⇒ Object
Adds a path that only responds to the request method
PUT. -
#recognize(env) ⇒ Object
Returns the HttpRouter::Response object if the env is matched, otherwise, returns
nil. -
#redirect_trailing_slash? ⇒ Boolean
Redirect trailing slash feature enabled? See #initialize for details.
-
#request_node(*args) ⇒ Object
Returns a new request node.
-
#reset! ⇒ Object
Resets the router to a clean state.
- #split(path) ⇒ Object
-
#url(route, *args) ⇒ Object
Generate a URL for a specified route.
-
#variable(*args) ⇒ Object
Returns a new variable.
Constructor Details
#initialize(*args, &block) ⇒ HttpRouter
Creates a new HttpRouter. Can be called with either HttpRouter.new(proc{|env| ... }, { .. options .. }) or with the first argument omitted. If there is a proc first, then it’s used as the default app in the case of a non-match. Supported options are
-
:default_app – Default application used if there is a non-match on #call. Defaults to 404 generator.
-
:ignore_trailing_slash – Ignore a trailing / when attempting to match. Defaults to
true. -
:redirect_trailing_slash – On trailing /, redirect to the same path without the /. Defaults to
false. -
:middleware – On recognition, store the route Response in env and always call the default app. Defaults to
false.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/http_router.rb', line 48 def initialize(*args, &block) default_app, = args.first.is_a?(Hash) ? [nil, args.first] : [args.first, args[1]] = @default_app = default_app || && [:default_app] || proc{|env| Rack::Response.new("Not Found", 404).finish } @ignore_trailing_slash = && .key?(:ignore_trailing_slash) ? [:ignore_trailing_slash] : true @redirect_trailing_slash = && .key?(:redirect_trailing_slash) ? [:redirect_trailing_slash] : false @middleware = && .key?(:middleware) ? [:middleware] : false @routes = [] @named_routes = {} @init_block = block reset! if block instance_eval(&block) @routes.each {|r| r.compile} end end |
Instance Attribute Details
#named_routes ⇒ Object (readonly)
Returns the value of attribute named_routes.
32 33 34 |
# File 'lib/http_router.rb', line 32 def named_routes @named_routes end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
32 33 34 |
# File 'lib/http_router.rb', line 32 def root @root end |
#routes ⇒ Object (readonly)
Returns the value of attribute routes.
32 33 34 |
# File 'lib/http_router.rb', line 32 def routes @routes end |
Class Method Details
.override_rack_mapper! ⇒ Object
Monkey-patches Rack::Builder to use HttpRouter. See examples/rack_mapper.rb
36 37 38 |
# File 'lib/http_router.rb', line 36 def self.override_rack_mapper! require File.join('ext', 'rack', 'rack_mapper') end |
Instance Method Details
#add(path, options = nil) ⇒ Object
Adds a path to be recognized.
To assign a part of the path to a specific variable, use :variable_name within the route. For example, add('/path/:id') would match /path/test, with the variable :id having the value "test".
You can receive mulitple parts into a single variable by using the glob syntax. For example, add('/path/*id') would match /path/123/456/789, with the variable :id having the value ["123", "456", "789"].
As well, paths can end with two optional parts, * and /?. If it ends with a *, it will match partially, returning the part of the path unmatched in the PATH_INFO value of the env. The part matched to will be returned in the SCRIPT_NAME. If it ends with /?, then a trailing / on the path will be optionally matched for that specific route. As trailing /‘s are ignored by default, you probably don’t actually want to use this option that frequently.
Routes can also contain optional parts. There are surrounded with ( )‘s. If you need to match on a bracket in the route itself, you can escape the parentheses with a backslash.
The second argument, options, is an optional hash that can modify the route in further ways. See HttpRouter::Route#with_options for details. Typically, you want to add further options to the route by calling additional methods on it. See HttpRouter::Route for further details.
Returns the route object.
103 104 105 |
# File 'lib/http_router.rb', line 103 def add(path, = nil) add_route Route.new(self, path.dup).() end |
#add_route(route) ⇒ Object
Adds a route to be recognized. This must be a HttpRouter::Route object. Returns the route just added.
108 109 110 111 |
# File 'lib/http_router.rb', line 108 def add_route(route) @routes << route route end |
#arbitrary_node(*args) ⇒ Object
214 215 216 |
# File 'lib/http_router.rb', line 214 def arbitrary_node(*args) ArbitraryNode.new(self, *args) end |
#call(env) ⇒ Object
Rack compatible #call. If matching route is found, and dest value responds to #call, processing will pass to the matched route. Otherwise, the default application will be called. The router will be available in the env under the key router. And parameters matched will be available under the key router.params. The HttpRouter::Response object will be available under the key router.response if a response is available.
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/http_router.rb', line 182 def call(env) request = Rack::Request.new(env) if redirect_trailing_slash? && (request.head? || request.get?) && request.path_info[-1] == ?/ response = Rack::Response.new response.redirect(request.path_info[0, request.path_info.size - 1], 302) response.finish else env['router'] = self if response = recognize(request) and !@middleware if response.matched? && response.route.dest && response.route.dest.respond_to?(:call) process_params(env, response) consume_path!(request, response) if response.partial_match? return response.route.dest.call(env) elsif !response.matched? return [response.status, response.headers, []] end end env['router.response'] = response @default_app.call(env) end end |
#clone ⇒ Object
Creates a deep-copy of the router.
229 230 231 232 233 234 235 236 |
# File 'lib/http_router.rb', line 229 def clone cloned_router = HttpRouter.new(@default_app, , &@init_block) @routes.each do |route| new_route = route.clone new_route.instance_variable_set(:@router, cloned_router) end cloned_router end |
#default(app) ⇒ Object
Assigns the default application.
84 85 86 |
# File 'lib/http_router.rb', line 84 def default(app) @default_app = app end |
#delete(path, options = nil) ⇒ Object
Adds a path that only responds to the request method DELETE.
Returns the route object.
137 138 139 |
# File 'lib/http_router.rb', line 137 def delete(path, = nil) add(path, ).delete end |
#get(path, options = nil) ⇒ Object
Adds a path that only responds to the request methods GET and HEAD.
Returns the route object.
116 117 118 |
# File 'lib/http_router.rb', line 116 def get(path, = nil) add(path, ).get end |
#glob(*args) ⇒ Object
Returns a new glob
224 225 226 |
# File 'lib/http_router.rb', line 224 def glob(*args) Glob.new(self, *args) end |
#ignore_trailing_slash? ⇒ Boolean
Ignore trailing slash feature enabled? See #initialize for details.
67 68 69 |
# File 'lib/http_router.rb', line 67 def ignore_trailing_slash? @ignore_trailing_slash end |
#node(*args) ⇒ Object
Returns a new node
205 206 207 |
# File 'lib/http_router.rb', line 205 def node(*args) Node.new(self, *args) end |
#only_get(path, options = nil) ⇒ Object
Adds a path that only responds to the request method GET.
Returns the route object.
144 145 146 |
# File 'lib/http_router.rb', line 144 def only_get(path, = nil) add(path, ).only_get end |
#post(path, options = nil) ⇒ Object
Adds a path that only responds to the request method POST.
Returns the route object.
123 124 125 |
# File 'lib/http_router.rb', line 123 def post(path, = nil) add(path, ).post end |
#put(path, options = nil) ⇒ Object
Adds a path that only responds to the request method PUT.
Returns the route object.
130 131 132 |
# File 'lib/http_router.rb', line 130 def put(path, = nil) add(path, ).put end |
#recognize(env) ⇒ Object
Returns the HttpRouter::Response object if the env is matched, otherwise, returns nil.
149 150 151 |
# File 'lib/http_router.rb', line 149 def recognize(env) response = @root.find(env.is_a?(Hash) ? Rack::Request.new(env) : env) end |
#redirect_trailing_slash? ⇒ Boolean
Redirect trailing slash feature enabled? See #initialize for details.
72 73 74 |
# File 'lib/http_router.rb', line 72 def redirect_trailing_slash? @redirect_trailing_slash end |
#request_node(*args) ⇒ Object
Returns a new request node
210 211 212 |
# File 'lib/http_router.rb', line 210 def request_node(*args) RequestNode.new(self, *args) end |
#reset! ⇒ Object
Resets the router to a clean state.
77 78 79 80 81 |
# File 'lib/http_router.rb', line 77 def reset! @root = Root.new(self) @routes.clear @named_routes.clear end |
#split(path) ⇒ Object
238 239 240 |
# File 'lib/http_router.rb', line 238 def split(path) (path[0] == ?/ ? path[1, path.size] : path).split('/') end |
#url(route, *args) ⇒ Object
Generate a URL for a specified route. This will accept a list of variable values plus any other variable names named as a hash. This first value must be either the Route object or the name of the route.
Example:
router = HttpRouter.new
router.add('/:foo.:format).name(:test).compile
router.url(:test, 123, 'html')
# ==> "/123.html"
router.url(:test, 123, :format => 'html')
# ==> "/123.html"
router.url(:test, :foo => 123, :format => 'html')
# ==> "/123.html"
router.url(:test, :foo => 123, :format => 'html', :fun => 'inthesun')
# ==> "/123.html?fun=inthesun"
167 168 169 170 171 172 173 174 175 176 |
# File 'lib/http_router.rb', line 167 def url(route, *args) case route when Symbol url(@named_routes[route], *args) when nil raise UngeneratableRouteException.new else route.url(*args) end end |
#variable(*args) ⇒ Object
Returns a new variable
219 220 221 |
# File 'lib/http_router.rb', line 219 def variable(*args) Variable.new(self, *args) end |