Class: Rack::Routes
- Inherits:
-
Object
- Object
- Rack::Routes
- Defined in:
- lib/rack/routes.rb
Defined Under Namespace
Classes: LocDirectiveError
Constant Summary collapse
- VERSION =
'0.1.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, opts = {}, &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
120 121 122 123 |
# File 'lib/rack/routes.rb', line 120 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
17 18 19 20 |
# File 'lib/rack/routes.rb', line 17 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.
25 26 27 28 29 30 |
# File 'lib/rack/routes.rb', line 25 def compile! # longest first [:exact, :string, :string_break].each do |type| locations[type].sort_by!{|path, _| -path.length} end end |
.location(path, opts = {}, &blk) ⇒ Object
Description
Main interface method. Reimplementation of nginx location directive.
Args
path
-
The path to match on. Can be String or Regexp.
opts
-
Hash of options. see below.
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:
false
-
prefix match
true
-
literal match
- =
-
literal match
- ^~
-
skip regex matching
yields env
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['routes.location.matchdata']
[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
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/rack/routes.rb', line 92 def location path, opts = {}, &blk 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 LocDirectiveError, "unknown type `#{type}'" unless [:regex, :string, :exact, :string_break].include? type app = blk locations[type] << [path, app, opts] end |
.locations ⇒ Object
accessor for @locations hash
113 114 115 |
# File 'lib/rack/routes.rb', line 113 def locations @locations ||= Hash.new{|h,k| h[k] = []} end |
Instance Method Details
#call(env) ⇒ Object
rack interface
126 127 128 |
# File 'lib/rack/routes.rb', line 126 def call env dup.call! env end |
#call!(env) ⇒ Object
130 131 132 133 134 135 |
# File 'lib/rack/routes.rb', line 130 def call! env @env = env @path = URI.decode @env['PATH_INFO'] (matching_app || @app).call(env) end |
#find_exact ⇒ Object
145 146 147 |
# File 'lib/rack/routes.rb', line 145 def find_exact find_type(:exact){|pth| pth == @path} end |
#find_regex ⇒ Object
157 158 159 160 |
# File 'lib/rack/routes.rb', line 157 def find_regex find_type(:regex){|pth| pth === @path and @env['routes.location.matchdata'] = Regexp.last_match } end |
#find_string ⇒ Object
149 150 151 |
# File 'lib/rack/routes.rb', line 149 def find_string find_type(:string){|pth| @path[0, pth.length] == pth} end |
#find_string_break ⇒ Object
153 154 155 |
# File 'lib/rack/routes.rb', line 153 def find_string_break find_type(:string_break){|pth| @path[0, pth.length] == pth} end |
#find_type(type) ⇒ Object
137 138 139 140 141 142 143 |
# File 'lib/rack/routes.rb', line 137 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
162 163 164 |
# File 'lib/rack/routes.rb', line 162 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.
174 175 176 177 178 179 |
# File 'lib/rack/routes.rb', line 174 def matching_app find_exact || find_string_break || find_regex || find_string end |