Class: Rack::Routes
- Inherits:
-
Object
- Object
- Rack::Routes
- Defined in:
- lib/rack/routes.rb
Constant Summary collapse
- VERSION =
'0.2.0'
Class Method Summary collapse
-
.call(env) ⇒ Object
convience rack interface Enables the use of either: use Rack::Routes or run Rack::Routes.
-
.compile! ⇒ Object
location directives should be run in a certain order.
-
.location(path, *args, &blk) ⇒ Object
Description.
-
.locations ⇒ Object
accessor for @locations hash.
Instance Method Summary collapse
-
#call(env) ⇒ Object
rack interface.
- #call!(env) ⇒ Object
- #find_exact ⇒ Object
- #find_regex ⇒ Object
- #find_string ⇒ Object
- #find_string_break ⇒ Object
- #find_type(type) ⇒ Object
-
#initialize(app = nil) ⇒ Routes
constructor
rack app.
- #locations ⇒ Object
-
#matching_app ⇒ Object
search exact matches first then ^~ strings (not sure what else to call them) then regex then all the other strings.
Constructor Details
#initialize(app = nil) ⇒ Routes
rack app
125 126 127 128 |
# File 'lib/rack/routes.rb', line 125 def initialize app = nil self.class.compile! @app = app end |
Class Method Details
.call(env) ⇒ Object
convience rack interface Enables the use of either: use Rack::Routes or run Rack::Routes
15 16 17 18 |
# File 'lib/rack/routes.rb', line 15 def call env @app ||= new @app.call env end |
.compile! ⇒ Object
location directives should be run in a certain order. This is needed to establish that order.
23 24 25 26 27 28 |
# File 'lib/rack/routes.rb', line 23 def compile! # longest first [:exact, :string, :string_break].each do |type| locations[type].sort_by!{|path, _| -path.length} end end |
.location(path, *args, &blk) ⇒ Object
Description
Main interface method. Reimplementation of nginx location directive.
Args
pathThe path to match on. Can be String or Regexp.
optsHash of options. see below.
appOptional object which responds to :call
blockrequired if
appis missing
opts keys:
:exact:: Type of string matching. default false
Also can be :prefix (for making '^~' make sense)
:method:: HTTP Request Method matching. defaults nil (all)
:type:: Explicetly set the type of match.
exact values can be:
falseprefix match
trueliteral match
=literal match
^~skip regex matching
yields env
raises ArgumentError if app or block is missing or if type is invalid
Examples
config.ru
matches everything
but longer matches will get applied first
Rack::Routes.location '/' do [200, {}, ['hi']] end
matches everything beginning with /asdf
Rack::Routes.location '/asdf' do [200, {}, ['hi asdf']] end
matches /foo and not /foobar nor /foo/baz etc.
Rack::Routes.location '/foo', :exact => true do [200, {}, ['hi foo']] end
matches anything beginning with /bar
path can be any ruby regex
matchdata is stored in env
Rack::Routes.location //bar(.*)/ do |env| m = env [200, {}, ["hi #m[1]"]] end
matches beginning of path but stops if match is found. Does not
evaluate regexen Rack::Routes.location '/baz', :prefix => '^~' do [200, {}, ['hi baz']] end
run Rack::Routes
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/rack/routes.rb', line 94 def location path, *args, &blk app = args.last.respond_to?(:call) ? args.pop : blk raise ArgumentError, 'must provide either an app or a block' unless app opts = Hash === args.last ? args.pop : {} type = opts.fetch(:type, nil) type = :regex if Regexp === path type ||= case opts.fetch(:exact, opts.fetch(:prefix, false)) when FalseClass :string when TrueClass, '=' :exact when '^~' :string_break end raise ArgumentError, "unknown type `#{type}'" unless [:regex, :string, :exact, :string_break].include? type locations[type] << [path, app, opts] end |
.locations ⇒ Object
accessor for @locations hash
118 119 120 |
# File 'lib/rack/routes.rb', line 118 def locations @locations ||= Hash.new{|h,k| h[k] = []} end |
Instance Method Details
#call(env) ⇒ Object
rack interface
131 132 133 |
# File 'lib/rack/routes.rb', line 131 def call env dup.call! env end |
#call!(env) ⇒ Object
135 136 137 138 139 140 |
# File 'lib/rack/routes.rb', line 135 def call! env @env = env @path = URI.decode_www_form_component @env['PATH_INFO'] (matching_app || @app).call(env) end |
#find_exact ⇒ Object
150 151 152 |
# File 'lib/rack/routes.rb', line 150 def find_exact find_type(:exact){|pth| pth == @path} end |
#find_regex ⇒ Object
162 163 164 165 |
# File 'lib/rack/routes.rb', line 162 def find_regex find_type(:regex){|pth| pth === @path and @env['routes.location.matchdata'] = Regexp.last_match } end |
#find_string ⇒ Object
154 155 156 |
# File 'lib/rack/routes.rb', line 154 def find_string find_type(:string){|pth| @path[0, pth.length] == pth} end |
#find_string_break ⇒ Object
158 159 160 |
# File 'lib/rack/routes.rb', line 158 def find_string_break find_type(:string_break){|pth| @path[0, pth.length] == pth} end |
#find_type(type) ⇒ Object
142 143 144 145 146 147 148 |
# File 'lib/rack/routes.rb', line 142 def find_type type _, app = locations[type].find do |path, _, opts| next if opts[:method] and opts[:method] != @env['REQUEST_METHOD'] yield path end app end |
#locations ⇒ Object
167 168 169 |
# File 'lib/rack/routes.rb', line 167 def locations self.class.locations end |
#matching_app ⇒ Object
search exact matches first then ^~ strings (not sure what else to call them) then regex then all the other strings
NOTE the docs say to run strings before regex but I don't see why it matters as the return logic is the same.
179 180 181 182 183 184 |
# File 'lib/rack/routes.rb', line 179 def matching_app find_exact || find_string_break || find_regex || find_string end |