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)
- VERSION =
'0.10.1'
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.
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/http_router.rb', line 36 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.
62 63 64 65 66 67 68 |
# File 'lib/http_router.rb', line 62 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
70 71 72 73 |
# File 'lib/http_router.rb', line 70 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.
114 115 116 117 118 119 120 121 122 123 |
# File 'lib/http_router.rb', line 114 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.
180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/http_router.rb', line 180 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.
132 133 134 |
# File 'lib/http_router.rb', line 132 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.
93 |
# File 'lib/http_router.rb', line 93 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.
78 |
# File 'lib/http_router.rb', line 78 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.
88 |
# File 'lib/http_router.rb', line 88 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.
170 171 172 |
# File 'lib/http_router.rb', line 170 def ignore_trailing_slash? @ignore_trailing_slash end |
#inspect ⇒ Object
222 223 224 225 |
# File 'lib/http_router.rb', line 222 def inspect head = to_s "#{to_s}\n#{'=' * head.size}\n#{@root.inspect}" end |
#no_response(env) ⇒ Object
205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/http_router.rb', line 205 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.
103 |
# File 'lib/http_router.rb', line 103 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.
165 166 167 |
# File 'lib/http_router.rb', line 165 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.
83 |
# File 'lib/http_router.rb', line 83 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.
159 160 161 |
# File 'lib/http_router.rb', line 159 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.
98 |
# File 'lib/http_router.rb', line 98 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.
107 108 109 |
# File 'lib/http_router.rb', line 107 def recognize(env) call(env, false) end |
#redirect_trailing_slash? ⇒ Boolean
Redirect trailing slash feature enabled? See #initialize for details.
175 176 177 |
# File 'lib/http_router.rb', line 175 def redirect_trailing_slash? @redirect_trailing_slash end |
#reset! ⇒ Object
Resets the router to a clean state.
126 127 128 129 |
# File 'lib/http_router.rb', line 126 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
195 196 197 198 |
# File 'lib/http_router.rb', line 195 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
200 201 202 203 |
# File 'lib/http_router.rb', line 200 def rewrite_path_info(env, request) env['SCRIPT_NAME'] += request.rack_request.path_info env['PATH_INFO'] = '' end |
#to_s ⇒ Object
218 219 220 |
# File 'lib/http_router.rb', line 218 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"
150 151 152 153 154 155 156 |
# File 'lib/http_router.rb', line 150 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 |