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 |