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
path-
The path to match on. Can be String or Regexp.
opts-
Hash of options. see below.
app-
Optional object which responds to :call
block-
required 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:
false-
prefix match
true-
literal 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['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
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 |