Class: HttpRouter
- Inherits:
-
Object
- Object
- HttpRouter
- Defined in:
- lib/http_router/version.rb,
lib/http_router.rb,
lib/http_router/node.rb,
lib/http_router/rack.rb,
lib/http_router/util.rb,
lib/http_router/route.rb,
lib/http_router/request.rb,
lib/http_router/response.rb,
lib/http_router/node/glob.rb,
lib/http_router/node/path.rb,
lib/http_router/node/root.rb,
lib/http_router/node/regex.rb,
lib/http_router/node/lookup.rb,
lib/http_router/regex_route.rb,
lib/http_router/node/request.rb,
lib/http_router/rack/url_map.rb,
lib/http_router/node/variable.rb,
lib/http_router/node/arbitrary.rb,
lib/http_router/node/free_regex.rb,
lib/http_router/node/glob_regex.rb,
lib/http_router/node/spanning_regex.rb
Overview
:nodoc
Defined Under Namespace
Modules: Rack, Util Classes: Node, RegexRoute, Request, Response, Route
Constant Summary collapse
- InvalidRouteException =
Raised when a url is not able to be generated for the given parameters
Class.new(RuntimeError)
- MissingParameterException =
Raised when a Route is not able to be generated due to a missing parameter.
Class.new(RuntimeError)
- DoubleCompileError =
Raised when a Route is compiled twice
Class.new(RuntimeError)
- InvalidRequestValueError =
Raised an invalid request value is used
Class.new(RuntimeError)
- TooManyParametersException =
Raised when there are extra parameters passed in to #url
Class.new(RuntimeError)
- VERSION =
'0.10.2'
Instance Attribute Summary collapse
-
#default_app ⇒ Object
Returns the value of attribute default_app.
-
#known_methods ⇒ Object
readonly
Returns the value of attribute known_methods.
-
#named_routes ⇒ Object
readonly
Returns the value of attribute named_routes.
-
#nodes ⇒ Object
readonly
Returns the value of attribute nodes.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#routes ⇒ Object
readonly
Returns the value of attribute routes.
-
#url_mount ⇒ Object
Returns the value of attribute url_mount.
Instance Method Summary collapse
-
#add(*args, &app) ⇒ Object
Adds a path to be recognized.
- #add_route(route) ⇒ Object
-
#call(env, perform_call = true) ⇒ Object
Rack compatible #call.
-
#clone(klass = self.class) ⇒ Object
Creates a deep-copy of the router.
-
#default(app) ⇒ Object
Assigns the default application.
-
#delete(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method
DELETE
. -
#get(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method
GET
. -
#head(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method
HEAD
. -
#ignore_trailing_slash? ⇒ Boolean
Ignore trailing slash feature enabled? See #initialize for details.
-
#initialize(*args, &blk) ⇒ HttpRouter
constructor
Creates a new HttpRouter.
- #inspect ⇒ Object
- #no_response(env) ⇒ Object
-
#options(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method
OPTIONS
. -
#pass_on_response(response) ⇒ Object
This method defines what sort of responses are considered “passes”, and thus, route processing will continue.
-
#post(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method
POST
. -
#process_destination_path(path, env) ⇒ Object
This method is invoked when a Path object gets called with an env.
-
#put(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method
PUT
. -
#recognize(env) ⇒ Object
Performs recoginition without actually calling the application and returns an array of all matching routes or nil if no match was found.
-
#redirect_trailing_slash? ⇒ Boolean
Redirect trailing slash feature enabled? See #initialize for details.
-
#reset! ⇒ Object
Resets the router to a clean state.
- #rewrite_partial_path_info(env, request) ⇒ Object
- #rewrite_path_info(env, request) ⇒ Object
- #to_s ⇒ Object
-
#url(route, *args) ⇒ Object
Generate a URL for a specified route.
Constructor Details
#initialize(*args, &blk) ⇒ 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
. -
:known_methods – Array of http methods tested for 405s.
38 39 40 41 42 43 44 45 46 47 |
# File 'lib/http_router.rb', line 38 def initialize(*args, &blk) default_app, = args.first.is_a?(Hash) ? [nil, args.first] : [args.first, args[1]] @options = @default_app = default_app || && [:default_app] || proc{|env| ::Rack::Response.new("Not Found", 404, {'X-Cascade' => 'pass'}).finish } @ignore_trailing_slash = && .key?(:ignore_trailing_slash) ? [:ignore_trailing_slash] : true @redirect_trailing_slash = && .key?(:redirect_trailing_slash) ? [:redirect_trailing_slash] : false @known_methods = Set.new( && [:known_methods] || []) reset! instance_eval(&blk) if blk end |
Instance Attribute Details
#default_app ⇒ Object
Returns the value of attribute default_app.
17 18 19 |
# File 'lib/http_router.rb', line 17 def default_app @default_app end |
#known_methods ⇒ Object (readonly)
Returns the value of attribute known_methods.
16 17 18 |
# File 'lib/http_router.rb', line 16 def known_methods @known_methods end |
#named_routes ⇒ Object (readonly)
Returns the value of attribute named_routes.
16 17 18 |
# File 'lib/http_router.rb', line 16 def named_routes @named_routes end |
#nodes ⇒ Object (readonly)
Returns the value of attribute nodes.
16 17 18 |
# File 'lib/http_router.rb', line 16 def nodes @nodes end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
16 17 18 |
# File 'lib/http_router.rb', line 16 def root @root end |
#routes ⇒ Object (readonly)
Returns the value of attribute routes.
16 17 18 |
# File 'lib/http_router.rb', line 16 def routes @routes end |
#url_mount ⇒ Object
Returns the value of attribute url_mount.
17 18 19 |
# File 'lib/http_router.rb', line 17 def url_mount @url_mount end |
Instance Method Details
#add(*args, &app) ⇒ 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.
As well, options can be passed in that 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.
64 65 66 67 68 69 70 |
# File 'lib/http_router.rb', line 64 def add(*args, &app) opts = args.last.is_a?(Hash) ? args.pop : {} path = args.first route = add_route((Regexp === path ? RegexRoute : Route).new(self, path, opts)) route.to(app) if app route end |
#add_route(route) ⇒ Object
72 73 74 75 |
# File 'lib/http_router.rb', line 72 def add_route(route) @routes << route route end |
#call(env, perform_call = true) ⇒ 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
.
116 117 118 119 120 121 122 123 124 125 |
# File 'lib/http_router.rb', line 116 def call(env, perform_call = true) rack_request = ::Rack::Request.new(env) request = Request.new(rack_request.path_info, rack_request, perform_call) response = catch(:success) { @root[request] } if perform_call response or no_response(env) else request.matches.empty? ? nil : request.matches end end |
#clone(klass = self.class) ⇒ Object
Creates a deep-copy of the router.
182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/http_router.rb', line 182 def clone(klass = self.class) cloned_router = klass.new(@options) @routes.each do |route| new_route = route.clone(cloned_router) cloned_router.add_route(new_route) new_route.name(route.named) if route.named begin new_route.to route.dest.clone rescue new_route.to route.dest end end cloned_router end |
#default(app) ⇒ Object
Assigns the default application.
134 135 136 |
# File 'lib/http_router.rb', line 134 def default(app) @default_app = app end |
#delete(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method DELETE
.
Returns the route object.
95 |
# File 'lib/http_router.rb', line 95 def delete(path, opts = {}, &app); add_with_request_method(path, :delete, opts, &app); end |
#get(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method GET
.
Returns the route object.
80 |
# File 'lib/http_router.rb', line 80 def get(path, opts = {}, &app); add_with_request_method(path, :get, opts, &app); end |
#head(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method HEAD
.
Returns the route object.
90 |
# File 'lib/http_router.rb', line 90 def head(path, opts = {}, &app); add_with_request_method(path, :head, opts, &app); end |
#ignore_trailing_slash? ⇒ Boolean
Ignore trailing slash feature enabled? See #initialize for details.
172 173 174 |
# File 'lib/http_router.rb', line 172 def ignore_trailing_slash? @ignore_trailing_slash end |
#inspect ⇒ Object
224 225 226 227 |
# File 'lib/http_router.rb', line 224 def inspect head = to_s "#{to_s}\n#{'=' * head.size}\n#{@root.inspect}" end |
#no_response(env) ⇒ Object
207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/http_router.rb', line 207 def no_response(env) supported_methods = @known_methods.select do |m| next if m == env['REQUEST_METHOD'] test_env = ::Rack::Request.new(env.clone) test_env.env['REQUEST_METHOD'] = m test_env.env['_HTTP_ROUTER_405_TESTING_ACCEPTANCE'] = true test_request = Request.new(test_env.path_info, test_env, 405) @root[test_request] !test_request.matches.empty? end supported_methods.empty? ? @default_app.call(env) : [405, {'Allow' => supported_methods.sort.join(", ")}, []] end |
#options(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method OPTIONS
.
Returns the route object.
105 |
# File 'lib/http_router.rb', line 105 def (path, opts = {}, &app); add_with_request_method(path, :options, opts, &app); end |
#pass_on_response(response) ⇒ Object
This method defines what sort of responses are considered “passes”, and thus, route processing will continue. Override it to implement custom passing.
167 168 169 |
# File 'lib/http_router.rb', line 167 def pass_on_response(response) response[1]['X-Cascade'] == 'pass' end |
#post(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method POST
.
Returns the route object.
85 |
# File 'lib/http_router.rb', line 85 def post(path, opts = {}, &app); add_with_request_method(path, :post, opts, &app); end |
#process_destination_path(path, env) ⇒ Object
This method is invoked when a Path object gets called with an env. Override it to implement custom path processing.
161 162 163 |
# File 'lib/http_router.rb', line 161 def process_destination_path(path, env) path.route.dest.call(env) end |
#put(path, opts = {}, &app) ⇒ Object
Adds a path that only responds to the request method PUT
.
Returns the route object.
100 |
# File 'lib/http_router.rb', line 100 def put(path, opts = {}, &app); add_with_request_method(path, :put, opts, &app); end |
#recognize(env) ⇒ Object
Performs recoginition without actually calling the application and returns an array of all matching routes or nil if no match was found.
109 110 111 |
# File 'lib/http_router.rb', line 109 def recognize(env) call(env, false) end |
#redirect_trailing_slash? ⇒ Boolean
Redirect trailing slash feature enabled? See #initialize for details.
177 178 179 |
# File 'lib/http_router.rb', line 177 def redirect_trailing_slash? @redirect_trailing_slash end |
#reset! ⇒ Object
Resets the router to a clean state.
128 129 130 131 |
# File 'lib/http_router.rb', line 128 def reset! @routes, @named_routes, @root = [], Hash.new{|h,k| h[k] = []}, Node::Root.new(self) @default_app = Proc.new{ |env| ::Rack::Response.new("Your request couldn't be found", 404).finish } end |
#rewrite_partial_path_info(env, request) ⇒ Object
197 198 199 200 |
# File 'lib/http_router.rb', line 197 def rewrite_partial_path_info(env, request) env['PATH_INFO'] = "/#{request.path.join('/')}" env['SCRIPT_NAME'] += request.rack_request.path_info[0, request.rack_request.path_info.size - env['PATH_INFO'].size] end |
#rewrite_path_info(env, request) ⇒ Object
202 203 204 205 |
# File 'lib/http_router.rb', line 202 def rewrite_path_info(env, request) env['SCRIPT_NAME'] += request.rack_request.path_info env['PATH_INFO'] = '' end |
#to_s ⇒ Object
220 221 222 |
# File 'lib/http_router.rb', line 220 def to_s "#<HttpRouter:0x#{object_id.to_s(16)} number of routes (#{routes.size}) ignore_trailing_slash? (#{ignore_trailing_slash?}) redirect_trailing_slash? (#{redirect_trailing_slash?}) known_methods (#{known_methods.to_a.join(', ')})>" 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).to{|env| [200, {}, []]}
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"
152 153 154 155 156 157 158 |
# File 'lib/http_router.rb', line 152 def url(route, *args) case route when Symbol then @named_routes.key?(route) && @named_routes[route].each{|r| url = r.url(*args); return url if url} when Route then return route.url(*args) end raise(InvalidRouteException) end |