Class: Blix::Rest::RequestMapper
- Inherits:
-
Object
- Object
- Blix::Rest::RequestMapper
- Defined in:
- lib/blix/rest/request_mapper.rb
Overview
register routes with this class and then we can match paths to these routes and return an associated block and parameters.
Defined Under Namespace
Classes: TableNode
Constant Summary collapse
- WILD_PLACEHOLDER =
'/'- PATH_SEP =
'/'- STAR_PLACEHOLDER =
'*'
Class Attribute Summary collapse
-
.path_root_length ⇒ Object
readonly
Returns the value of attribute path_root_length.
Class Method Summary collapse
-
.add_path(verb, path, opts = {}, &blk) ⇒ Object
declare a route.
-
.compile ⇒ Object
compile routes into a tree structure for easy lookup.
- .dump ⇒ Object
- .dump_node(item, indent = 0) ⇒ Object
- .full_path(path) ⇒ Object
- .locations ⇒ Object
-
.match(verb, path) ⇒ Object
match a given path to declared route.
- .path_root ⇒ Object
-
.process(verb, path) ⇒ Object
match a path to a route and call any associated block with the extracted parameters.
-
.reset(vals = nil) ⇒ Object
used for testing only !!.
- .routes ⇒ Object
- .set_path_root(root) ⇒ Object
- .table ⇒ Object
Class Attribute Details
.path_root_length ⇒ Object (readonly)
Returns the value of attribute path_root_length.
67 68 69 |
# File 'lib/blix/rest/request_mapper.rb', line 67 def path_root_length @path_root_length end |
Class Method Details
.add_path(verb, path, opts = {}, &blk) ⇒ Object
declare a route
146 147 148 149 150 |
# File 'lib/blix/rest/request_mapper.rb', line 146 def add_path(verb, path, opts = {}, &blk) path = path[1..-1] if path[0, 1] == PATH_SEP RequestMapper.locations[verb] << [verb, path, opts, blk] @table = nil # force recompile end |
.compile ⇒ Object
compile routes into a tree structure for easy lookup
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/blix/rest/request_mapper.rb', line 112 def compile @table = Hash.new { |h, k| h[k] = TableNode.new('') } locations.each do |verb, routes| routes.each do |info| verb, path, opts, blk = info parts = path.split(PATH_SEP) current = @table[verb] parts.each_with_index do |section, idx| node = TableNode.new(section) # check that a wildstar is the last element. if (section[0] == STAR_PLACEHOLDER) && (idx < (parts.length - 1)) raise RequestMapperError, "do not add a path after the * in #{path}" end # check that wild card match in name if current[node.value] if (node.value == WILD_PLACEHOLDER) && (node.parameter != current[node.value].parameter) raise RequestMapperError, "parameter mismatch in route=#{path}, expected #{current[node.value].parameter} but got #{node.parameter}" end else current[node.value] = node end current = current[node.value] end current.blk = blk current.opts = opts || {} current.extract_format = opts[:extension] if opts.key?(:extension) end end @table end |
.dump ⇒ Object
82 83 84 85 86 87 |
# File 'lib/blix/rest/request_mapper.rb', line 82 def dump table.each do |k, v| puts k dump_node(v, 1) end end |
.dump_node(item, indent = 0) ⇒ Object
89 90 91 92 |
# File 'lib/blix/rest/request_mapper.rb', line 89 def dump_node(item, indent = 0) puts "#{' ' * indent} value=#{item.value.inspect} opts=#{item.opts.inspect} params=#{item.parameter.inspect}" item.children.each_value { |c| dump_node(c, indent + 1) } end |
.full_path(path) ⇒ Object
69 70 71 72 |
# File 'lib/blix/rest/request_mapper.rb', line 69 def full_path(path) path = path[1..-1] if path[0, 1] == '/' path_root + path end |
.locations ⇒ Object
74 75 76 |
# File 'lib/blix/rest/request_mapper.rb', line 74 def locations @locations ||= Hash.new { |h, k| h[k] = [] } end |
.match(verb, path) ⇒ Object
match a given path to declared route.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/blix/rest/request_mapper.rb', line 153 def match(verb, path) path = PATH_SEP + path if path[0, 1] != PATH_SEP # ensure a leading slash on path path = path[path_root_length..-1] if (path_root_length.to_i > 0) #&& (path[0,path_root_length] == path_root) if path path = path[1..-1] if path[0, 1] == PATH_SEP # remove the leading slash else return [nil, {}, nil] end parameters = StringHash.new parts = path.split(PATH_SEP) current = table[verb] limit = parts.length - 1 # handle the root node here if path == '' if current.blk return [current.blk, parameters, current.opts] elsif (havewild = current[STAR_PLACEHOLDER]) parameters[havewild.parameter.to_s] = '/' return [havewild.blk, parameters, havewild.opts] else return [nil, {}, nil] end end parts.each_with_index do |section, idx| # first save the last node that we used # before updating the current node. last = current # table nodes # check to see if there is a path which includes a format part # only on the last section if idx == limit if last[section] current = last[section] else format = File.extname(section) base = File.basename(section, format) current = last[base] if current parameters['format'] = format[1..-1].to_sym # !format.empty? section = base end end else current = last[section] end # if current is set here that means that this section matches a fixed # part of the route. if current # if this is the last section then we have to decide here if we # have a valid result.. # .. if we have a block then fine .. # .. if there is a wildpath foloowing then fine .. # .. otherwise an error ! if idx == limit # the last section of request if current.blk return [current.blk, parameters, current.opts] elsif (havewild = current[STAR_PLACEHOLDER]) parameters[havewild.parameter.to_s] = '/' return [havewild.blk, parameters, havewild.opts] else return [nil, {}, nil] end end else # this section is not part of a static path so # check if we have a path variable first .. current = last[WILD_PLACEHOLDER] if current # yes this is a path variable section if idx == limit # the last section of request - if current.extract_format format = File.extname(section) base = File.basename(section, format) parameters[current.parameter.to_s] = base parameters['format'] = format[1..-1].to_sym unless format.empty? else parameters[current.parameter.to_s] = section end # check if we have a valid block otherwise see if # a wild path follows. if current.blk return [current.blk, parameters, current.opts] elsif (havewild = current[STAR_PLACEHOLDER]) parameters[havewild.parameter.to_s] = '/' return [havewild.blk, parameters, havewild.opts] else return [nil, {}, nil] end else parameters[current.parameter.to_s] = section end else current = last[STAR_PLACEHOLDER] if current wildpath = '/' + parts[idx..-1].join('/') wildformat = File.extname(wildpath) unless wildformat.empty? || !current.extract_format wildpath = wildpath[0..-(wildformat.length + 1)] parameters['format'] = wildformat[1..-1].to_sym end parameters[current.parameter.to_s] = wildpath return [current.blk, parameters, current.opts] else return [nil, {}, nil] end end end end [nil, {}, nil] end |
.path_root ⇒ Object
63 64 65 |
# File 'lib/blix/rest/request_mapper.rb', line 63 def path_root @path_root || '/' end |
.process(verb, path) ⇒ Object
match a path to a route and call any associated block with the extracted parameters.
282 283 284 285 |
# File 'lib/blix/rest/request_mapper.rb', line 282 def process(verb, path) blk, params = match(verb, path) blk&.call(params) end |
.reset(vals = nil) ⇒ Object
used for testing only !!
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/blix/rest/request_mapper.rb', line 95 def reset(vals = nil) save = [@table&.dup, @locations&.dup, @path_root&.dup, @path_root_length] if vals @table = vals[0] @locations = vals[1] @path_root = vals[2] @path_root_length = vals[3] else @table = nil @locations = nil @path_root = nil @path_root_length = 0 end save end |
.routes ⇒ Object
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/blix/rest/request_mapper.rb', line 287 def routes hash = {} locations.values.each do |group| group.each do |route| verb = route[0] = route[2] = String.new = ' ' + .inspect.to_s unless .empty? path = '/' + route[1] hash[path] ||= {} hash[path][verb] = end end list = hash.to_a list.sort! { |a, b| a[0] <=> b[0] } str = String.new list.each do |route| #pairs = route[1] (HTTP_VERBS + ['ALL']).each do |verb| if route[1].key? verb str << verb << "\t" << route[0] << route[1][verb] << "\n" end end str << "\n" end str end |
.set_path_root(root) ⇒ Object
55 56 57 58 59 60 61 |
# File 'lib/blix/rest/request_mapper.rb', line 55 def set_path_root(root) root = root.to_s root = '/' + root if root[0, 1] != '/' root += '/' if root[-1, 1] != '/' @path_root = root @path_root_length = @path_root.length - 1 end |
.table ⇒ Object
78 79 80 |
# File 'lib/blix/rest/request_mapper.rb', line 78 def table @table ||= compile end |