rack-app 5.11.0 → 5.11.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 070c847ed07e3494ed51e88ebf084c6eb661a30f
4
- data.tar.gz: 4b836fb0a7d4c38491b4d2774b85289d528c1c56
3
+ metadata.gz: 4d2a02f6b4e7653fa9647f92c3aff43878fd64c2
4
+ data.tar.gz: e262d7601e24a4f451ffa43dcabfd1ca0bab0220
5
5
  SHA512:
6
- metadata.gz: 566de7abd739139b8ac5980bcad9079995892d36c1f7213cadedd2451d62ce6ee7f41a2c23327c7174e0576b20ab1b7d71cbfab0b01a79424bb77ae63e35ade3
7
- data.tar.gz: 91ac3f3615722f31dc483aa4cd4845902d8270655cb1a2e96c2fa72d78add151692ed0cc5a6304c6a5ad6f10a06d40e66c589ceb604b188b944d0fda8d18fb38
6
+ metadata.gz: bb38fe1f45db780873148bdf662baa41bc0cf84762204aa3be46ee8ffaa7495b6bfa707dc8a93069ee3f6509271bed3f70734491c331fa9cee5348544a12403c
7
+ data.tar.gz: 3177c3c9643288694a0d8ec3f51ec644cf5e9ee3a9e787e8169952b850e97df51af114dd20f3b02056fa059c02eb6bb1ca9f30d192882835febda8147eb85539
data/README.md CHANGED
@@ -68,10 +68,10 @@ Yes, in fact it's already powering heroku hosted micro-services.
68
68
  * syntax sugar for default header definitions
69
69
  * namespaces for endpoint request path declarations so it can be dry and unified
70
70
  * no Class method bloat, so you can enjoy pure ruby without any surprises
71
- * App mounting so you can crete separated controllers for different task
71
+ * App mounting so you can crete separated controllers for different task
72
72
  * Streaming
73
- * Null time look up routing
74
- * allows as many endpoint registration to you as you want, without impact on route look up speed
73
+ * O(log(n)) lookup routing
74
+ * allows as many endpoint registration to you as you want, without impact on route lookup speed
75
75
  * only basic sets for instance method lvl for the must need tools, such as params, payload
76
76
  * simple to use class level response serializer
77
77
  * so you can choose what type of serialization you want without any enforced convention
@@ -100,7 +100,7 @@ Yes, in fact it's already powering heroku hosted micro-services.
100
100
 
101
101
  * **[David Bush](https://github.com/disavowd)**
102
102
 
103
- * [wrote an article](https://www.sitepoint.com/rack-app-a-performant-and-pragmatic-web-microframework/) about the project
103
+ * [wrote an awesome article](https://www.sitepoint.com/rack-app-a-performant-and-pragmatic-web-microframework/) about the project
104
104
 
105
105
  ## [Contributing](CONTRIBUTING.md)
106
106
 
@@ -133,7 +133,7 @@ require 'rack/app'
133
133
 
134
134
  class App < Rack::App
135
135
 
136
- apply_extensions :front_end
136
+ apply_extensions :front_end
137
137
 
138
138
  mount SomeAppClass
139
139
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 5.11.0
1
+ 5.11.1
@@ -54,11 +54,14 @@ module Rack::App::Constants
54
54
  PATH_PARAMS = 'rack-app.path_params'.freeze
55
55
  ORIGINAL_PATH_INFO = 'rack-app.original_path_info'.freeze
56
56
  FORMATTED_PATH_INFO = 'rack-app.formatted_path_info'.freeze
57
+ SPLITTED_PATH_INFO = 'rack-app.splitted_path_info'.freeze
57
58
  METHODOVERRIDE_ORIGINAL_METHOD = 'rack-app.methodoverride.original_method'.freeze
58
59
 
59
60
  end
60
61
 
61
- MOUNTED_DIRECTORY = '[Mounted Directory]'.freeze
62
- RACK_BASED_APPLICATION = '[Mounted Rack Application]'.freeze
62
+ module PATH
63
+ MOUNT_POINT = "[MOUNT_POINT]".freeze
64
+ APPLICATION = "[Mounted Application]".freeze
65
+ end
63
66
 
64
67
  end
@@ -0,0 +1,35 @@
1
+ class Rack::App::Middlewares::SetPathParams
2
+
3
+ def initialize(app, params_lookup_hash)
4
+ @params_lookup_hash = params_lookup_hash
5
+ @app = app
6
+ end
7
+
8
+ E = Rack::App::Constants::ENV
9
+
10
+ def call(env)
11
+ populate_path_params(env)
12
+ correct_last_value_from_extensions(env)
13
+ @app.call(env)
14
+ end
15
+
16
+ protected
17
+
18
+ def populate_path_params(env)
19
+ @params_lookup_hash.each do |index, key|
20
+ env[E::PATH_PARAMS][key] = env[E::SPLITTED_PATH_INFO][index]
21
+ end
22
+ end
23
+
24
+ def correct_last_value_from_extensions(env)
25
+ last_index = env[E::SPLITTED_PATH_INFO].length - 1
26
+ return if @params_lookup_hash[last_index].nil?
27
+ extless(env[E::PATH_PARAMS][@params_lookup_hash[last_index]])
28
+ end
29
+
30
+ def extless(value)
31
+ extname = File.extname(value)
32
+ value.slice!(/#{Regexp.escape(extname)}$/) unless extname.empty?
33
+ end
34
+
35
+ end
@@ -1,5 +1,6 @@
1
1
  module Rack::App::Middlewares
2
2
  require 'rack/app/middlewares/path_info_cutter'
3
+ require 'rack/app/middlewares/set_path_params'
3
4
  require 'rack/app/middlewares/configuration'
4
5
  require 'rack/app/middlewares/header_setter'
5
6
  require 'rack/app/middlewares/payload'
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ class Rack::App::Router::Tree::Branch < ::Hash
3
+
4
+ def set(env)
5
+ if env.branch?
6
+ branch_for(env.save_key).set(env.next)
7
+ else
8
+ leaf.set(env)
9
+ end
10
+ end
11
+
12
+ def call(env, current, *path_info_parts)
13
+ if path_info_parts.empty?
14
+ try_leaf { |l| l.call_endpoint(env, current) || l.call_mount(env) }
15
+ else
16
+ next_branch = self[current] || self[:ANY]
17
+ resp = next_branch && next_branch.call(env, *path_info_parts)
18
+ resp || try_leaf { |l| l.call_mount(env) }
19
+ end
20
+ end
21
+
22
+ protected
23
+
24
+ def try_leaf
25
+ leaf = self[:LEAF]
26
+ leaf && yield(leaf)
27
+ end
28
+
29
+ def branch_for(save_key)
30
+ self[save_key] ||= self.class.new
31
+ end
32
+
33
+ def leaf
34
+ self[:LEAF] ||= Rack::App::Router::Tree::Leaf.new
35
+ end
36
+
37
+ end
@@ -1,13 +1,67 @@
1
1
  # frozen_string_literal: true
2
- module Rack::App::Router::Tree::Env
3
- extend(self)
2
+ class Rack::App::Router::Tree::Env
4
3
 
5
- E = Rack::App::Constants::ENV
4
+ attr_reader :request_path_parts, :endpoint, :params
6
5
 
7
- def configure(env)
8
- env[E::PATH_PARAMS] ||= {}
9
- env[E::FORMATTED_PATH_INFO] = Rack::App::Utils.normalize_path(env[E::PATH_INFO])
10
- env[E::EXTNAME] = File.extname(Rack::App::Utils.split_path_info(env[E::FORMATTED_PATH_INFO]).last)
11
- env[E::FORMATTED_PATH_INFO].slice!(/#{Regexp.escape(env[E::EXTNAME])}$/)
6
+ def current
7
+ @request_path_parts[@index]
12
8
  end
9
+
10
+ def branch?
11
+ !clean_request_path_parts[@index..-2].empty?
12
+ end
13
+
14
+ def type
15
+ case @request_path_parts.last
16
+ when Rack::App::Constants::PATH::APPLICATION
17
+ :APPLICATION
18
+ when Rack::App::Constants::PATH::MOUNT_POINT
19
+ :MOUNT_POINT
20
+ else
21
+ :ENDPOINT
22
+ end
23
+ end
24
+
25
+ def save_key
26
+ if current =~ /^:\w+$/i
27
+ @params[@index]= current.sub(/^:/, '')
28
+ :ANY
29
+ else
30
+ current
31
+ end
32
+ end
33
+
34
+ def next
35
+ env = self.dup
36
+ env.inc_index!
37
+ env
38
+ end
39
+
40
+ protected
41
+
42
+ def initialize(endpoint)
43
+ @index = 0
44
+ @params = {}
45
+ @endpoint = endpoint
46
+ @request_path_parts = request_path_parts_by(endpoint).freeze
47
+ end
48
+
49
+ def request_path_parts_by(endpoint)
50
+ u = Rack::App::Utils
51
+ u.split_path_info(u.normalize_path(endpoint.request_path))
52
+ end
53
+
54
+ def inc_index!
55
+ @index += 1
56
+ end
57
+
58
+ SPECIAL_PATH_ELEMENTS = [
59
+ Rack::App::Constants::PATH::APPLICATION,
60
+ Rack::App::Constants::PATH::MOUNT_POINT
61
+ ].freeze
62
+
63
+ def clean_request_path_parts
64
+ @request_path_parts - SPECIAL_PATH_ELEMENTS
65
+ end
66
+
13
67
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- class Rack::App::Router::Tree::Mounted::Application < Rack::App::Router::Tree::Mounted
2
+ class Rack::App::Router::Tree::Leaf::Mounted::Application < Rack::App::Router::Tree::Leaf::Mounted
3
3
  protected
4
4
 
5
5
  def initialize(endpoint)
@@ -14,7 +14,7 @@ class Rack::App::Router::Tree::Mounted::Application < Rack::App::Router::Tree::M
14
14
  end
15
15
 
16
16
  def mount_path(endpoint)
17
- mount_path_parts = (endpoint.request_path.split('/') - [Rack::App::Constants::RACK_BASED_APPLICATION, ''])
17
+ mount_path_parts = (endpoint.request_path.split('/') - [Rack::App::Constants::PATH::APPLICATION, ''])
18
18
  mount_path_parts.empty? ? '' : Rack::App::Utils.join(mount_path_parts)
19
19
  end
20
20
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
- class Rack::App::Router::Tree::Mounted
2
+ class Rack::App::Router::Tree::Leaf::Mounted
3
3
 
4
- require 'rack/app/router/tree/mounted/application'
4
+ require 'rack/app/router/tree/leaf/mounted/application'
5
5
 
6
- def get(env)
6
+ def call(env)
7
7
  @app.call(env)
8
8
  end
9
9
 
@@ -1,34 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
  class Rack::App::Router::Tree::Leaf < ::Hash
3
- require 'rack/app/router/tree/leaf/vein'
4
3
 
5
- def get(env)
6
- vein = vein_by(env)
7
- vein && vein.get(env)
8
- end
4
+ require 'rack/app/router/tree/leaf/mounted'
5
+
6
+ E = Rack::App::Constants::ENV
9
7
 
10
- def set(endpoint)
11
- endpoint.request_methods.each do |request_method|
12
- vein_for(request_method).set(endpoint)
8
+ def set(env)
9
+ case env.type
10
+ when :APPLICATION
11
+ self[env.type] = Rack::App::Router::Tree::Leaf::Mounted::Application.new(env.endpoint)
12
+ when :MOUNT_POINT
13
+ self[env.type] = Rack::App::Router::Tree::Leaf::Mounted.new(env.endpoint)
14
+ else
15
+ save_endpoint(env)
13
16
  end
14
17
  end
15
18
 
16
- def struct
17
- hash = {}
18
- self.each do |request_method, vein|
19
- hash[request_method] = vein.struct
20
- end
21
- hash
19
+ def call_endpoint(env, current_path)
20
+ app = self[current_path] || self[:ANY]
21
+ (app && app.call(env)) || call_mount(env)
22
+ end
23
+
24
+ def call_mount(env)
25
+ app = self[:MOUNT_POINT] || self[:APPLICATION]
26
+ app && app.call(env)
22
27
  end
23
28
 
24
29
  protected
25
30
 
26
- def vein_by(env)
27
- self[env[Rack::App::Constants::ENV::REQUEST_METHOD].to_sym]
31
+ def save_endpoint(env)
32
+ if env.save_key.is_a?(Symbol)
33
+ vein_for(env.save_key).set(env)
34
+ else
35
+ split_save_to_extnames(env)
36
+ end
28
37
  end
29
38
 
30
- def vein_for(request_method)
31
- self[request_method] ||= Rack::App::Router::Tree::Leaf::Vein.new
39
+ def split_save_to_extnames(env)
40
+ save_key = env.save_key
41
+ env.endpoint.config.serializer.extnames.each do |extname|
42
+ vein_for(save_key + extname).set(env)
43
+ end
44
+ vein_for(save_key).set(env)
32
45
  end
33
46
 
47
+ def vein_for(path_part)
48
+ self[path_part] ||= Rack::App::Router::Tree::Vein.new
49
+ end
50
+
51
+
34
52
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ class Rack::App::Router::Tree::Vein < ::Hash
3
+
4
+ def set(env)
5
+ app = create_app(env)
6
+ env.endpoint.request_methods.each do |request_method|
7
+ self[request_method.to_s.upcase] = app
8
+ end
9
+ end
10
+
11
+ def call(env)
12
+ app = app_by(env)
13
+ app && app.call(env)
14
+ end
15
+
16
+ protected
17
+
18
+ def app_by(env)
19
+ self[env[Rack::App::Constants::ENV::REQUEST_METHOD]]
20
+ end
21
+
22
+ def create_app(env)
23
+ app = env.endpoint.to_app
24
+ env.params.empty? ? app : wrap(app, env.params)
25
+ end
26
+
27
+ def wrap(app, params)
28
+ builder = Rack::Builder.new
29
+ builder.use(Rack::App::Middlewares::SetPathParams, params)
30
+ builder.run(app)
31
+ builder.to_app
32
+ end
33
+
34
+ end
@@ -2,39 +2,49 @@
2
2
  class Rack::App::Router::Tree
3
3
 
4
4
  require 'rack/app/router/tree/env'
5
- require 'rack/app/router/tree/node'
5
+
6
+ require 'rack/app/router/tree/branch'
6
7
  require 'rack/app/router/tree/leaf'
7
- require 'rack/app/router/tree/mounted'
8
+ require 'rack/app/router/tree/vein'
9
+
10
+ attr_reader :root
8
11
 
9
12
  def initialize
10
- @root = self.class::Node.new
13
+ @root = self.class::Branch.new
11
14
  end
12
15
 
13
16
  def add(endpoint)
14
- @root.set(endpoint, *path_info_parts_by(endpoint.request_path))
17
+ @root.set(self.class::Env.new(endpoint))
15
18
  end
16
19
 
17
20
  def call(env)
18
- self.class::Env.configure(env)
19
- @root.get(env, *path_info_parts_by(env[Rack::App::Constants::ENV::FORMATTED_PATH_INFO]))
21
+ configure_request(env)
22
+ @root.call(env, *env[Rack::App::Constants::ENV::SPLITTED_PATH_INFO])
20
23
  end
21
24
 
22
25
  protected
23
26
 
24
- def request_methods(endpoint)
25
- case endpoint.request_method
26
- when ::Rack::App::Constants::HTTP::METHOD::ANY
27
- ::Rack::App::Constants::HTTP::METHODS.each{|m| yield(m) }
28
- else
29
- yield(endpoint.request_method)
30
- end
27
+ E = Rack::App::Constants::ENV
28
+
29
+ def configure_request(env)
30
+ env[E::PATH_PARAMS] ||= {}
31
+ fpi = format_path_info(env).freeze
32
+ env[E::FORMATTED_PATH_INFO] = fpi
33
+ spi = split_path_info(fpi).freeze
34
+ env[E::SPLITTED_PATH_INFO] = spi
35
+ env[E::EXTNAME] = extname(spi)
31
36
  end
32
37
 
33
- def cluster(request_method)
34
- @methods[request_method.to_s.upcase] ||= Rack::App::Router::Tree::Node.new
38
+ def format_path_info(env)
39
+ Rack::App::Utils.normalize_path(env[E::PATH_INFO])
35
40
  end
36
41
 
37
- def path_info_parts_by(path_info)
38
- Rack::App::Utils.split_path_info(Rack::App::Utils.normalize_path(path_info))
42
+ def split_path_info(formatted_path_info)
43
+ Rack::App::Utils.split_path_info(formatted_path_info)
39
44
  end
45
+
46
+ def extname(splitted_path_info)
47
+ File.extname(splitted_path_info.last)
48
+ end
49
+
40
50
  end
@@ -2,6 +2,8 @@ class Rack::App::Router
2
2
 
3
3
  require 'rack/app/router/tree'
4
4
 
5
+ attr_reader :tree
6
+
5
7
  NOT_FOUND_APP = lambda do |env|
6
8
  rack_response = Rack::Response.new
7
9
  rack_response.status = 404
@@ -61,7 +63,6 @@ class Rack::App::Router
61
63
 
62
64
  protected
63
65
 
64
-
65
66
  def initialize
66
67
  reset
67
68
  end
@@ -31,18 +31,14 @@ module Rack::App::SingletonMethods::Mounting
31
31
  directory_full_path = ::Rack::App::Utils.expand_path(directory_path)
32
32
 
33
33
  namespace options[:to] do
34
-
35
34
  Dir.glob(File.join(directory_full_path, '**', '*')).each do |file_path|
36
-
37
35
  request_path = file_path.sub(/^#{Regexp.escape(directory_full_path)}/, '')
38
36
  get(request_path) { serve_file(file_path) }
39
37
  options(request_path) { '' }
40
-
41
38
  end
42
-
43
39
  end
44
- nil
45
40
 
41
+ nil
46
42
  end
47
43
 
48
44
  alias create_endpoints_for_files_in mount_directory
@@ -50,7 +46,7 @@ module Rack::App::SingletonMethods::Mounting
50
46
 
51
47
  def serve_files_from(file_path, options={})
52
48
  file_server = Rack::App::FileServer.new(Rack::App::Utils.expand_path(file_path))
53
- request_path = Rack::App::Utils.join(@namespaces, options[:to], '**', '*')
49
+ request_path = Rack::App::Utils.join(@namespaces, options[:to], Rack::App::Constants::PATH::MOUNT_POINT)
54
50
 
55
51
  endpoint = Rack::App::Endpoint.new(
56
52
  route_registration_properties.merge(
@@ -74,7 +70,7 @@ module Rack::App::SingletonMethods::Mounting
74
70
  :request_path => Rack::App::Utils.join(
75
71
  @namespaces,
76
72
  options[:to],
77
- ::Rack::App::Constants::RACK_BASED_APPLICATION
73
+ Rack::App::Constants::PATH::APPLICATION
78
74
  ),
79
75
  :application => rack_based_app
80
76
  )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-app
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.11.0
4
+ version: 5.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Luzsi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-31 00:00:00.000000000 Z
11
+ date: 2017-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -138,6 +138,7 @@ files:
138
138
  - lib/rack/app/middlewares/path_info_cutter.rb
139
139
  - lib/rack/app/middlewares/payload.rb
140
140
  - lib/rack/app/middlewares/payload/parser_setter.rb
141
+ - lib/rack/app/middlewares/set_path_params.rb
141
142
  - lib/rack/app/params.rb
142
143
  - lib/rack/app/payload.rb
143
144
  - lib/rack/app/payload/builder.rb
@@ -149,12 +150,12 @@ files:
149
150
  - lib/rack/app/router.rb
150
151
  - lib/rack/app/router/base.rb
151
152
  - lib/rack/app/router/tree.rb
153
+ - lib/rack/app/router/tree/branch.rb
152
154
  - lib/rack/app/router/tree/env.rb
153
155
  - lib/rack/app/router/tree/leaf.rb
154
- - lib/rack/app/router/tree/leaf/vein.rb
155
- - lib/rack/app/router/tree/mounted.rb
156
- - lib/rack/app/router/tree/mounted/application.rb
157
- - lib/rack/app/router/tree/node.rb
156
+ - lib/rack/app/router/tree/leaf/mounted.rb
157
+ - lib/rack/app/router/tree/leaf/mounted/application.rb
158
+ - lib/rack/app/router/tree/vein.rb
158
159
  - lib/rack/app/serializer.rb
159
160
  - lib/rack/app/serializer/formats_builder.rb
160
161
  - lib/rack/app/singleton_methods.rb
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
- class Rack::App::Router::Tree::Leaf::Vein < ::Hash
3
-
4
- E = Rack::App::Constants::ENV
5
-
6
- def set(endpoint)
7
- app = endpoint.to_app
8
- endpoint.config.serializer.extnames.each do |extname|
9
- self[extname] = app
10
- end
11
- self[extname_for(endpoint)] = app
12
- end
13
-
14
- def get(env)
15
- app = self[env[E::EXTNAME]]
16
- app && app.call(env)
17
- end
18
-
19
- def struct
20
- self.reduce({}) do |hash, (extname, app)|
21
- hash[extname]= :app
22
- hash
23
- end
24
- end
25
-
26
- protected
27
-
28
- def extname_for(endpoint)
29
- File.extname(Rack::App::Utils.split_path_info(endpoint.request_path).last)
30
- end
31
- end
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
- class Rack::App::Router::Tree::Node < ::Hash
3
-
4
- PARAM = :PARAM
5
-
6
- def set(endpoint, current=nil, *path_info_parts)
7
- case type(current)
8
- when :NODE
9
- node_for(save_key(current)).set(endpoint, *path_info_parts)
10
- when :LEAF
11
- save_to_leaf(endpoint)
12
- when :RACK_BASED_APPLICATION
13
- attach(:RACK_BASED_APPLICATION, Rack::App::Router::Tree::Mounted::Application.new(endpoint))
14
- when :MOUNTED
15
- attach(:MOUNT, Rack::App::Router::Tree::Mounted.new(endpoint))
16
- else
17
- raise('UNKNOWN')
18
- end
19
- end
20
-
21
- def get(env, current=nil, *path_info_parts)
22
- return app_for(env) if current.nil?
23
- node = next_node(env, current)
24
- (node && node.get(env, *path_info_parts)) || mounted(env)
25
- end
26
-
27
- def struct
28
- self.reduce({}) do |hash, (k,v)|
29
- if k == PARAM
30
- hash[k] = v
31
- else
32
- hash[k] = v.struct
33
- end
34
- hash
35
- end
36
- end
37
-
38
- protected
39
-
40
- def app_for(env)
41
- app = self[:LEAF] || mounted_app
42
- app && app.get(env)
43
- end
44
-
45
- def mounted(env)
46
- mounted_app && mounted_app.get(env)
47
- end
48
-
49
- def mounted_app
50
- self[:MOUNT] || self[:RACK_BASED_APPLICATION]
51
- end
52
-
53
- def attach(key, app_or_endpoint)
54
- self[key.to_sym] = app_or_endpoint
55
- end
56
-
57
- def save_to_leaf(endpoint)
58
- self[:LEAF] ||= Rack::App::Router::Tree::Leaf.new
59
- self[:LEAF].set(endpoint)
60
- end
61
-
62
- def next_node(env, current)
63
- self[current] || any_path(env, current)
64
- end
65
-
66
- def any_path(env, current)
67
- if self[:ANY]
68
- env[Rack::App::Constants::ENV::PATH_PARAMS][self[PARAM]] = current
69
- self[:ANY]
70
- end
71
- end
72
-
73
- def node_for(key)
74
- self[key] ||= self.class.new
75
- end
76
-
77
- def type(current)
78
- case current
79
- when Rack::App::Constants::RACK_BASED_APPLICATION
80
- :RACK_BASED_APPLICATION
81
- when '**','*'
82
- :MOUNTED
83
- when NilClass
84
- :LEAF
85
- else
86
- :NODE
87
- end
88
- end
89
-
90
- def save_key(path)
91
- case path
92
- when /^:\w+$/i
93
- self[PARAM] = path.sub(/^:/, '')
94
- :ANY
95
- else
96
- extnameless(path)
97
- end
98
- end
99
-
100
- def extnameless(path)
101
- path.sub(/\.\w+$/,'')
102
- end
103
-
104
- end