http_router 0.8.11 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,136 @@
1
+ require.paths.push("#{__dirname}/../lib")
2
+ fs = require('fs')
3
+ util = require('util')
4
+ sys = require('sys')
5
+ http_router = require('http_router')
6
+ assert = require('assert')
7
+
8
+ class Example
9
+ constructor: (@routes, @tests) ->
10
+
11
+ class Test
12
+ constructor: (file)->
13
+ @examples = []
14
+ contents = fs.readFileSync(file, 'utf8')
15
+ lines = contents.split(/\n/m)
16
+ currentTest = null
17
+ routes = []
18
+ tests = []
19
+ for line in lines
20
+ if line.match(/^#/)
21
+ # this is a comment, skip
22
+ else if line.match(/^\s*$/)
23
+ # empty line, skip
24
+ else if line.match(/^( |\t)/)
25
+ # this is a test
26
+ tests.push(JSON.parse(line))
27
+ else
28
+ # this is a route
29
+ if tests.length != 0
30
+ @examples.push new Example(routes, tests)
31
+ routes = []
32
+ tests = []
33
+ parsedRoutes = JSON.parse(line)
34
+ if parsedRoutes instanceof Array
35
+ for r in parsedRoutes
36
+ routes.push(r)
37
+ else
38
+ routes.push(parsedRoutes)
39
+ @examples.push new Example(routes, tests)
40
+ interpretValue: (v) ->
41
+ if v.regex? then new RegExp(v.regex) else v
42
+ invoke: -> throw("need to implement")
43
+ constructRouter: (example) ->
44
+ router = new Sherpa()
45
+ for route in example.routes
46
+ for name, vals of route
47
+ path = null
48
+ opts = {name: name}
49
+ if vals.path?
50
+ path = @interpretValue(vals.path)
51
+ delete vals.path
52
+ if vals.conditions?
53
+ conditions = {}
54
+ for k, v of vals.conditions
55
+ switch k
56
+ when 'request_method' then conditions.method = @interpretValue(v)
57
+ else conditions[k] = @interpretValue(v)
58
+ opts.conditions = conditions
59
+ delete vals.conditions
60
+ if vals.default?
61
+ opts.default = vals.default
62
+ delete vals.default
63
+ matchesWith = {}
64
+ for k, v of vals
65
+ matchesWith[k] = @interpretValue(v)
66
+ delete vals.k
67
+ opts.matchesWith = matchesWith
68
+ else
69
+ path = @interpretValue(vals)
70
+ name = "" + name
71
+ router.add(path, opts).to (req, response) ->
72
+ response.params = req.params
73
+ response.end(req.route.name)
74
+ router
75
+
76
+ class GenerationTest extends Test
77
+ constructor: -> super
78
+ invoke: ->
79
+ console.log("Running #{@examples.length} generation tests")
80
+ for example in @examples
81
+ process.stdout.write "*"
82
+ router = @constructRouter(example)
83
+ for test in example.tests
84
+ process.stdout.write "."
85
+ [expectedResult, name, params] = test
86
+ continue if params? && params instanceof Array
87
+ continue if name instanceof Object
88
+ actualResult = router.url(name, params)
89
+ assert.equal(expectedResult, actualResult)
90
+ console.log("\nDone!")
91
+
92
+ class RecognitionTest extends Test
93
+ constructor: -> super
94
+ invoke: ->
95
+ console.log("Running #{@examples.length} recognition tests")
96
+ for example in @examples
97
+ process.stdout.write "*"
98
+ router = @constructRouter(example)
99
+ for test in example.tests
100
+ mockResponse = end: (part) -> @val = part
101
+ process.stdout.write "."
102
+ [expectedRouteName, requestingPath, expectedParams] = test
103
+ mockRequest = {}
104
+ complex = false
105
+ if requestingPath.path?
106
+ complex = true
107
+ mockRequest.url = requestingPath.path
108
+ delete requestingPath.path
109
+ for k, v of requestingPath
110
+ mockRequest[k] = v
111
+ else
112
+ mockRequest.url = requestingPath
113
+ mockRequest.url = "http://host#{mockRequest.url}" unless mockRequest.url.match(/^http/)
114
+ router.match(mockRequest, mockResponse)
115
+ assert.equal(expectedRouteName, mockResponse.val)
116
+ expectedParams ||= {}
117
+ mockResponse.params ||= {}
118
+ pathInfoExcpectation = null
119
+ if expectedParams.PATH_INFO?
120
+ pathInfoExcpectation = expectedParams.PATH_INFO
121
+ delete expectedParams.PATH_INFO
122
+ assert.equal(pathInfoExcpectation, mockRequest.pathInfo) if pathInfoExcpectation
123
+ assert.deepEqual(expectedParams, mockResponse.params)
124
+ unless complex
125
+ mockResponse = end: (part) -> @val = part
126
+ router.match(requestingPath, mockResponse)
127
+ assert.equal(expectedRouteName, mockResponse.val)
128
+ expectedParams ||= {}
129
+ mockResponse.params ||= {}
130
+ assert.equal(pathInfoExcpectation, mockRequest.pathInfo) if pathInfoExcpectation
131
+ assert.deepEqual(expectedParams, mockResponse.params)
132
+ console.log("\nDone!")
133
+
134
+ new GenerationTest("#{__dirname}/../../test/common/generate.txt").invoke()
135
+ new RecognitionTest("#{__dirname}/../../test/common/recognize.txt").invoke()
136
+
data/js/test/test.js ADDED
@@ -0,0 +1,229 @@
1
+ (function() {
2
+ var Example, GenerationTest, RecognitionTest, Test, assert, fs, http_router, sys, util;
3
+ var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
4
+ for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
5
+ function ctor() { this.constructor = child; }
6
+ ctor.prototype = parent.prototype;
7
+ child.prototype = new ctor;
8
+ child.__super__ = parent.prototype;
9
+ return child;
10
+ };
11
+ require.paths.push("" + __dirname + "/../lib");
12
+ fs = require('fs');
13
+ util = require('util');
14
+ sys = require('sys');
15
+ http_router = require('http_router');
16
+ assert = require('assert');
17
+ Example = (function() {
18
+ function Example(routes, tests) {
19
+ this.routes = routes;
20
+ this.tests = tests;
21
+ }
22
+ return Example;
23
+ })();
24
+ Test = (function() {
25
+ function Test(file) {
26
+ var contents, currentTest, line, lines, parsedRoutes, r, routes, tests, _i, _j, _len, _len2;
27
+ this.examples = [];
28
+ contents = fs.readFileSync(file, 'utf8');
29
+ lines = contents.split(/\n/m);
30
+ currentTest = null;
31
+ routes = [];
32
+ tests = [];
33
+ for (_i = 0, _len = lines.length; _i < _len; _i++) {
34
+ line = lines[_i];
35
+ if (line.match(/^#/)) {} else if (line.match(/^\s*$/)) {} else if (line.match(/^( |\t)/)) {
36
+ tests.push(JSON.parse(line));
37
+ } else {
38
+ if (tests.length !== 0) {
39
+ this.examples.push(new Example(routes, tests));
40
+ routes = [];
41
+ tests = [];
42
+ }
43
+ parsedRoutes = JSON.parse(line);
44
+ if (parsedRoutes instanceof Array) {
45
+ for (_j = 0, _len2 = parsedRoutes.length; _j < _len2; _j++) {
46
+ r = parsedRoutes[_j];
47
+ routes.push(r);
48
+ }
49
+ } else {
50
+ routes.push(parsedRoutes);
51
+ }
52
+ }
53
+ }
54
+ this.examples.push(new Example(routes, tests));
55
+ }
56
+ Test.prototype.interpretValue = function(v) {
57
+ if (v.regex != null) {
58
+ return new RegExp(v.regex);
59
+ } else {
60
+ return v;
61
+ }
62
+ };
63
+ Test.prototype.invoke = function() {
64
+ throw "need to implement";
65
+ };
66
+ Test.prototype.constructRouter = function(example) {
67
+ var conditions, k, matchesWith, name, opts, path, route, router, v, vals, _i, _len, _ref, _ref2;
68
+ router = new Sherpa();
69
+ _ref = example.routes;
70
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
71
+ route = _ref[_i];
72
+ for (name in route) {
73
+ vals = route[name];
74
+ path = null;
75
+ opts = {
76
+ name: name
77
+ };
78
+ if (vals.path != null) {
79
+ path = this.interpretValue(vals.path);
80
+ delete vals.path;
81
+ if (vals.conditions != null) {
82
+ conditions = {};
83
+ _ref2 = vals.conditions;
84
+ for (k in _ref2) {
85
+ v = _ref2[k];
86
+ switch (k) {
87
+ case 'request_method':
88
+ conditions.method = this.interpretValue(v);
89
+ break;
90
+ default:
91
+ conditions[k] = this.interpretValue(v);
92
+ }
93
+ }
94
+ opts.conditions = conditions;
95
+ delete vals.conditions;
96
+ }
97
+ if (vals["default"] != null) {
98
+ opts["default"] = vals["default"];
99
+ delete vals["default"];
100
+ }
101
+ matchesWith = {};
102
+ for (k in vals) {
103
+ v = vals[k];
104
+ matchesWith[k] = this.interpretValue(v);
105
+ delete vals.k;
106
+ }
107
+ opts.matchesWith = matchesWith;
108
+ } else {
109
+ path = this.interpretValue(vals);
110
+ }
111
+ name = "" + name;
112
+ router.add(path, opts).to(function(req, response) {
113
+ response.params = req.params;
114
+ return response.end(req.route.name);
115
+ });
116
+ }
117
+ }
118
+ return router;
119
+ };
120
+ return Test;
121
+ })();
122
+ GenerationTest = (function() {
123
+ __extends(GenerationTest, Test);
124
+ function GenerationTest() {
125
+ GenerationTest.__super__.constructor.apply(this, arguments);
126
+ }
127
+ GenerationTest.prototype.invoke = function() {
128
+ var actualResult, example, expectedResult, name, params, router, test, _i, _j, _len, _len2, _ref, _ref2;
129
+ console.log("Running " + this.examples.length + " generation tests");
130
+ _ref = this.examples;
131
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
132
+ example = _ref[_i];
133
+ process.stdout.write("*");
134
+ router = this.constructRouter(example);
135
+ _ref2 = example.tests;
136
+ for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
137
+ test = _ref2[_j];
138
+ process.stdout.write(".");
139
+ expectedResult = test[0], name = test[1], params = test[2];
140
+ if ((params != null) && params instanceof Array) {
141
+ continue;
142
+ }
143
+ if (name instanceof Object) {
144
+ continue;
145
+ }
146
+ actualResult = router.url(name, params);
147
+ assert.equal(expectedResult, actualResult);
148
+ }
149
+ }
150
+ return console.log("\nDone!");
151
+ };
152
+ return GenerationTest;
153
+ })();
154
+ RecognitionTest = (function() {
155
+ __extends(RecognitionTest, Test);
156
+ function RecognitionTest() {
157
+ RecognitionTest.__super__.constructor.apply(this, arguments);
158
+ }
159
+ RecognitionTest.prototype.invoke = function() {
160
+ var complex, example, expectedParams, expectedRouteName, k, mockRequest, mockResponse, pathInfoExcpectation, requestingPath, router, test, v, _i, _j, _len, _len2, _ref, _ref2;
161
+ console.log("Running " + this.examples.length + " recognition tests");
162
+ _ref = this.examples;
163
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
164
+ example = _ref[_i];
165
+ process.stdout.write("*");
166
+ router = this.constructRouter(example);
167
+ _ref2 = example.tests;
168
+ for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
169
+ test = _ref2[_j];
170
+ mockResponse = {
171
+ end: function(part) {
172
+ return this.val = part;
173
+ }
174
+ };
175
+ process.stdout.write(".");
176
+ expectedRouteName = test[0], requestingPath = test[1], expectedParams = test[2];
177
+ mockRequest = {};
178
+ complex = false;
179
+ if (requestingPath.path != null) {
180
+ complex = true;
181
+ mockRequest.url = requestingPath.path;
182
+ delete requestingPath.path;
183
+ for (k in requestingPath) {
184
+ v = requestingPath[k];
185
+ mockRequest[k] = v;
186
+ }
187
+ } else {
188
+ mockRequest.url = requestingPath;
189
+ }
190
+ if (!mockRequest.url.match(/^http/)) {
191
+ mockRequest.url = "http://host" + mockRequest.url;
192
+ }
193
+ router.match(mockRequest, mockResponse);
194
+ assert.equal(expectedRouteName, mockResponse.val);
195
+ expectedParams || (expectedParams = {});
196
+ mockResponse.params || (mockResponse.params = {});
197
+ pathInfoExcpectation = null;
198
+ if (expectedParams.PATH_INFO != null) {
199
+ pathInfoExcpectation = expectedParams.PATH_INFO;
200
+ delete expectedParams.PATH_INFO;
201
+ }
202
+ if (pathInfoExcpectation) {
203
+ assert.equal(pathInfoExcpectation, mockRequest.pathInfo);
204
+ }
205
+ assert.deepEqual(expectedParams, mockResponse.params);
206
+ if (!complex) {
207
+ mockResponse = {
208
+ end: function(part) {
209
+ return this.val = part;
210
+ }
211
+ };
212
+ router.match(requestingPath, mockResponse);
213
+ assert.equal(expectedRouteName, mockResponse.val);
214
+ expectedParams || (expectedParams = {});
215
+ mockResponse.params || (mockResponse.params = {});
216
+ if (pathInfoExcpectation) {
217
+ assert.equal(pathInfoExcpectation, mockRequest.pathInfo);
218
+ }
219
+ assert.deepEqual(expectedParams, mockResponse.params);
220
+ }
221
+ }
222
+ }
223
+ return console.log("\nDone!");
224
+ };
225
+ return RecognitionTest;
226
+ })();
227
+ new GenerationTest("" + __dirname + "/../../test/common/generate.txt").invoke();
228
+ new RecognitionTest("" + __dirname + "/../../test/common/recognize.txt").invoke();
229
+ }).call(this);
@@ -13,7 +13,7 @@ class HttpRouter
13
13
  end
14
14
 
15
15
  def to_code
16
- b, method_name = @blk, :"blk_#{router.next_counter}"
16
+ b, method_name = @blk, :"blk_#{root.next_counter}"
17
17
  inject_root_methods { define_method(method_name) { b } }
18
18
  "#{"if request.path_finished?" unless @allow_partial}
19
19
  request.continue = proc { |state|
@@ -8,8 +8,9 @@ class HttpRouter
8
8
  end
9
9
 
10
10
  def to_code
11
- "whole_path#{depth} = \"/\#{request.joined_path}\"
12
- if match = #{matcher.inspect}.match(whole_path#{depth}) and match[0].size == whole_path#{depth}.size
11
+ id = root.next_counter
12
+ "whole_path#{id} = \"/\#{request.joined_path}\"
13
+ if match = #{matcher.inspect}.match(whole_path#{id}) and match[0].size == whole_path#{id}.size
13
14
  request.extra_env['router.regex_match'] = match
14
15
  old_path = request.path
15
16
  request.path = ['']
@@ -7,12 +7,13 @@ class HttpRouter
7
7
  end
8
8
 
9
9
  def to_code
10
- "request.params << (globbed_params#{depth} = [])
10
+ id = root.next_counter
11
+ "request.params << (globbed_params#{id} = [])
11
12
  until request.path.empty?
12
- globbed_params#{depth} << request.path.shift
13
+ globbed_params#{id} << request.path.shift
13
14
  #{super}
14
15
  end
15
- request.path[0,0] = globbed_params#{depth}"
16
+ request.path[0,0] = globbed_params#{id}"
16
17
  end
17
18
  end
18
19
  end
@@ -12,10 +12,11 @@ class HttpRouter
12
12
  end
13
13
 
14
14
  def to_code
15
- "request.params << (globbed_params#{depth} = [])
15
+ id = root.next_counter
16
+ "request.params << (globbed_params#{id} = [])
16
17
  remaining_parts = request.path.dup
17
18
  while !remaining_parts.empty? and match = remaining_parts.first.match(#{@matcher.inspect}) and match[0] == remaining_parts.first
18
- globbed_params#{depth} << remaining_parts.shift
19
+ globbed_params#{id} << remaining_parts.shift
19
20
  request.path = remaining_parts
20
21
  #{node_to_code}
21
22
  end
@@ -15,9 +15,8 @@ class HttpRouter
15
15
  end
16
16
 
17
17
  def to_code
18
- lookup_ivar = :"@lookup_#{router.next_counter}"
19
- inject_root_ivar(lookup_ivar, @map)
20
- method_prefix = "lookup_#{router.next_counter} "
18
+ lookup_ivar = inject_root_ivar(@map)
19
+ method_prefix = "lookup_#{root.next_counter} "
21
20
  inject_root_methods @map.keys.map {|k|
22
21
  method = :"#{method_prefix}#{k}"
23
22
  "define_method(#{method.inspect}) do |request|
@@ -0,0 +1,62 @@
1
+ class HttpRouter
2
+ class Node
3
+ class Path < Node
4
+ attr_reader :route, :param_names, :dynamic, :original_path
5
+ alias_method :dynamic?, :dynamic
6
+ def initialize(router, parent, route, path, param_names = [])
7
+ @route, @original_path, @param_names, @dynamic = route, path, param_names, !param_names.empty?
8
+ raise AmbiguousVariableException, "You have duplicate variable name present: #{param_names.join(', ')}" if param_names.uniq.size != param_names.size
9
+ Util.add_path_generation(self, route, @original_path) if @original_path.respond_to?(:split)
10
+ super router, parent
11
+ root.uncompile
12
+ end
13
+
14
+ def hashify_params(params)
15
+ @dynamic && params ? Hash[param_names.zip(params)] : {}
16
+ end
17
+
18
+ def url(args, options)
19
+ if path = raw_url(args, options)
20
+ raise TooManyParametersException unless args.empty?
21
+ [URI.escape(path), options]
22
+ end
23
+ end
24
+
25
+ def to_code
26
+ path_ivar = inject_root_ivar(self)
27
+ "#{"if request.path_finished?" unless route.match_partially?}
28
+ catch(:pass) do
29
+ #{"if request.path.size == 1 && request.path.first == '' && (request.rack_request.head? || request.rack_request.get?) && request.rack_request.path_info[-1] == ?/
30
+ response = ::Rack::Response.new
31
+ response.redirect(request.rack_request.path_info[0, request.rack_request.path_info.size - 1], 302)
32
+ throw :success, response.finish
33
+ end" if router.redirect_trailing_slash?}
34
+
35
+ #{"if request.path.empty?#{" or (request.path.size == 1 and request.path.first == '')" if router.ignore_trailing_slash?}" unless route.match_partially?}
36
+ if request.perform_call
37
+ env = request.rack_request.dup.env
38
+ env['router.request'] = request
39
+ env['router.params'] ||= {}
40
+ #{"env['router.params'].merge!(Hash[#{param_names.inspect}.zip(request.params)])" if dynamic?}
41
+ rewrite#{"_partial" if route.match_partially?}_path_info(env, request)
42
+ response = @router.process_destination_path(#{path_ivar}, env)
43
+ router.pass_on_response(response) ? throw(:pass) : throw(:success, response)
44
+ else
45
+ throw :success, Response.new(request, #{path_ivar})
46
+ end
47
+ #{"end" unless route.match_partially?}
48
+ end
49
+ #{"end" unless route.match_partially?}"
50
+ end
51
+
52
+ def usable?(other)
53
+ other == self
54
+ end
55
+
56
+ private
57
+ def raw_url(args, options)
58
+ raise InvalidRouteException
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,11 +1,23 @@
1
1
  class HttpRouter
2
2
  class Node
3
3
  class Request < Node
4
+ VALID_HTTP_VERBS = %w[HEAD GET DELETE POST PUT OPTIONS PATCH TRACE CONNECT]
5
+
4
6
  attr_reader :request_method, :opts
5
7
 
6
8
  def initialize(router, parent, opts)
9
+ opts.each do |k, v|
10
+ v = [v] unless v.is_a?(Array)
11
+ case k
12
+ when :request_method
13
+ v.map!{|val| val.to_s.upcase}
14
+ v.all?{|m| VALID_HTTP_VERBS.include?(m)} or raise InvalidRequestValueError, "Invalid value for request_method #{v.inspect}"
15
+ v.each{|val| router.known_methods << val}
16
+ end
17
+ opts[k] = v
18
+ end
7
19
  @opts = opts
8
- Array(@opts[:request_method]).each { |m| router.known_methods << m } if @opts.key?(:request_method)
20
+ @opts[:request_method].each { |m| router.known_methods << m } if @opts.key?(:request_method)
9
21
  super(router, parent)
10
22
  end
11
23
 
@@ -16,7 +28,6 @@ class HttpRouter
16
28
  def to_code
17
29
  code = "if "
18
30
  code << @opts.map do |k,v|
19
- v = [v] unless v.is_a?(Array)
20
31
  case v.size
21
32
  when 1 then to_code_condition(k, v.first)
22
33
  else "(#{v.map{|vv| to_code_condition(k, vv)}.join(' or ')})"
@@ -1,21 +1,48 @@
1
1
  class HttpRouter
2
2
  class Node
3
3
  class Root < Node
4
- attr_reader :methods_module
4
+ attr_reader :methods_module, :compiled
5
+ alias_method :compiled?, :compiled
5
6
  def initialize(router)
6
7
  super(router, nil)
7
- @methods_module = Module.new
8
+ @counter, @methods_module = 0, Module.new
8
9
  end
9
10
 
10
11
  def [](request)
11
12
  compile
12
13
  self[request]
13
14
  end
15
+ alias_method :compiling_lookup, :[]
16
+
17
+ def uncompile
18
+ instance_eval "undef :[]; alias :[] :compiling_lookup", __FILE__, __LINE__ if compiled?
19
+ end
20
+
21
+ def next_counter
22
+ @counter += 1
23
+ end
24
+
25
+ def inject_root_ivar(obj)
26
+ name = :"@ivar_#{@counter += 1}"
27
+ root.instance_variable_set(name, obj)
28
+ name
29
+ end
14
30
 
15
31
  private
32
+ def rewrite_partial_path_info(env, request)
33
+ env['PATH_INFO'] = "/#{request.path.join('/')}"
34
+ env['SCRIPT_NAME'] += request.rack_request.path_info[0, request.rack_request.path_info.size - env['PATH_INFO'].size]
35
+ end
36
+
37
+ def rewrite_path_info(env, request)
38
+ env['SCRIPT_NAME'] += request.rack_request.path_info
39
+ env['PATH_INFO'] = ''
40
+ end
41
+
16
42
  def compile
17
43
  root.extend(root.methods_module)
18
44
  instance_eval "def [](request)\n#{to_code}\nnil\nend", __FILE__, __LINE__
45
+ @compiled = true
19
46
  end
20
47
  end
21
48
  end
@@ -3,14 +3,15 @@ class HttpRouter
3
3
  class SpanningRegex < Regex
4
4
  def to_code
5
5
  params_count = @ordered_indicies.size
6
- "whole_path#{depth} = request.joined_path
7
- if match = #{@matcher.inspect}.match(whole_path#{depth}) and match.begin(0).zero?
8
- original_path#{depth} = request.path.dup
6
+ whole_path_var = "whole_path#{root.next_counter}"
7
+ "#{whole_path_var} = request.joined_path
8
+ if match = #{@matcher.inspect}.match(#{whole_path_var}) and match.begin(0).zero?
9
+ _#{whole_path_var} = request.path.dup
9
10
  " << param_capturing_code << "
10
- remaining_path = whole_path#{depth}[match[0].size + (whole_path#{depth}[match[0].size] == ?/ ? 1 : 0), whole_path#{depth}.size]
11
+ remaining_path = #{whole_path_var}[match[0].size + (#{whole_path_var}[match[0].size] == ?/ ? 1 : 0), #{whole_path_var}.size]
11
12
  request.path = remaining_path.split('/')
12
13
  #{node_to_code}
13
- request.path = original_path#{depth}
14
+ request.path = _#{whole_path_var}
14
15
  request.params.slice!(#{-params_count.size}, #{params_count})
15
16
  end
16
17
  "
@@ -11,9 +11,9 @@ class HttpRouter
11
11
  autoload :Arbitrary, 'http_router/node/arbitrary'
12
12
  autoload :Request, 'http_router/node/request'
13
13
  autoload :Lookup, 'http_router/node/lookup'
14
- autoload :Destination, 'http_router/node/destination'
14
+ autoload :Path, 'http_router/node/path'
15
15
 
16
- attr_reader :priority, :router, :node_position, :parent
16
+ attr_reader :router
17
17
 
18
18
  def initialize(router, parent, matchers = [])
19
19
  @router, @parent, @matchers = router, parent, matchers
@@ -32,6 +32,7 @@ class HttpRouter
32
32
  end
33
33
 
34
34
  def add_request(opts)
35
+ raise unless opts
35
36
  add(Request.new(@router, self, opts))
36
37
  end
37
38
 
@@ -51,8 +52,8 @@ class HttpRouter
51
52
  add(FreeRegex.new(@router, self, regexp))
52
53
  end
53
54
 
54
- def add_destination(blk, partial)
55
- add(Destination.new(@router, self, blk, partial))
55
+ def add_destination(route, path, param_names = [])
56
+ add(Path.new(@router, self, route, path, param_names))
56
57
  end
57
58
 
58
59
  def add_lookup(part)
@@ -68,8 +69,8 @@ class HttpRouter
68
69
  code ? root.methods_module.module_eval(code) : root.methods_module.module_eval(&blk)
69
70
  end
70
71
 
71
- def inject_root_ivar(name, val)
72
- root.instance_variable_set(name, val)
72
+ def inject_root_ivar(obj)
73
+ root.inject_root_ivar(obj)
73
74
  end
74
75
 
75
76
  def add(matcher)
@@ -85,12 +86,6 @@ class HttpRouter
85
86
  @router.root
86
87
  end
87
88
 
88
- def depth
89
- d, p = 0, @parent
90
- d, p = d + 1, p.parent until p.nil?
91
- d
92
- end
93
-
94
89
  def use_named_captures?
95
90
  //.respond_to?(:names)
96
91
  end
@@ -51,14 +51,6 @@ module HttpRouter::Rack::BuilderMixin
51
51
  map(path, options, :delete, &block)
52
52
  end
53
53
 
54
- # Maps a path with request methods `HEAD` to a block.
55
- # @param path [String] Path to map to.
56
- # @param options [Hash] Options for added path.
57
- # @see HttpRouter#add
58
- def head(path, options = {}, &block)
59
- map(path, options, :head, &block)
60
- end
61
-
62
54
  def options(path, options = {}, &block)
63
55
  map(path, options, :options, &block)
64
56
  end