http_router 0.7.10 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -0
- data/benchmarks/rec2.rb +4 -2
- data/lib/http_router.rb +18 -1
- data/lib/http_router/node.rb +26 -8
- data/lib/http_router/node/arbitrary.rb +14 -10
- data/lib/http_router/node/destination.rb +12 -11
- data/lib/http_router/node/free_regex.rb +11 -9
- data/lib/http_router/node/glob.rb +12 -11
- data/lib/http_router/node/glob_regex.rb +11 -2
- data/lib/http_router/node/lookup.rb +12 -7
- data/lib/http_router/node/regex.rb +12 -15
- data/lib/http_router/node/request.rb +12 -11
- data/lib/http_router/node/spanning_regex.rb +12 -9
- data/lib/http_router/node/variable.rb +9 -8
- data/lib/http_router/request.rb +5 -1
- data/lib/http_router/route.rb +1 -3
- data/lib/http_router/version.rb +1 -1
- data/test/test_recognize.rb +16 -1
- data/test/test_request.rb +6 -0
- data/test/test_variable.rb +1 -0
- metadata +88 -38
data/README.md
CHANGED
data/benchmarks/rec2.rb
CHANGED
@@ -15,6 +15,8 @@ u.add('/dynamic/:variable').to {|env| [200, {'Content-type'=>'text/html'}, []]}
|
|
15
15
|
#u.add('/greedy/:greed').matching(:greed => /.*/).compile.to {|env| [200, {'Content-type'=>'text/html'}, []]}
|
16
16
|
#u.add('/greedy/hey.:greed.html').to {|env| [200, {'Content-type'=>'text/html'}, []]}
|
17
17
|
|
18
|
+
u.compile rescue nil
|
19
|
+
|
18
20
|
puts Benchmark.measure {
|
19
21
|
('aa'..'nn').each do |first|
|
20
22
|
('a'..'n').each do |second|
|
@@ -34,7 +36,7 @@ TIMES = 50_000
|
|
34
36
|
#simple_and_dynamic_env1 = Rack::MockRequest.env_for('/rails/controller/action/id')
|
35
37
|
#simple_and_dynamic_env2 = Rack::MockRequest.env_for('/greedy/controller/action/id')
|
36
38
|
#simple_and_dynamic_env3 = Rack::MockRequest.env_for('/greedy/hey.hello.html')
|
37
|
-
|
39
|
+
5.times {
|
38
40
|
RBench.run(TIMES) do
|
39
41
|
|
40
42
|
report "2 levels, static" do
|
@@ -62,5 +64,5 @@ TIMES = 50_000
|
|
62
64
|
#end
|
63
65
|
|
64
66
|
end
|
65
|
-
|
67
|
+
}
|
66
68
|
puts `ps -o rss= -p #{Process.pid}`.to_i
|
data/lib/http_router.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'set'
|
2
2
|
require 'rack'
|
3
|
+
require 'uri'
|
4
|
+
require 'cgi'
|
5
|
+
require 'url_mount'
|
3
6
|
require 'http_router/node'
|
4
7
|
require 'http_router/request'
|
5
8
|
require 'http_router/response'
|
@@ -11,7 +14,7 @@ require 'http_router/optional_compiler'
|
|
11
14
|
|
12
15
|
class HttpRouter
|
13
16
|
|
14
|
-
attr_reader :root, :routes, :known_methods, :named_routes
|
17
|
+
attr_reader :root, :routes, :known_methods, :named_routes, :nodes
|
15
18
|
attr_accessor :default_app, :url_mount
|
16
19
|
|
17
20
|
# Raised when a Route is not able to be generated.
|
@@ -36,6 +39,7 @@ class HttpRouter
|
|
36
39
|
@ignore_trailing_slash = options && options.key?(:ignore_trailing_slash) ? options[:ignore_trailing_slash] : true
|
37
40
|
@redirect_trailing_slash = options && options.key?(:redirect_trailing_slash) ? options[:redirect_trailing_slash] : false
|
38
41
|
@known_methods = Set.new(options && options[:known_methods] || [])
|
42
|
+
@nodes = []
|
39
43
|
reset!
|
40
44
|
instance_eval(&blk) if blk
|
41
45
|
end
|
@@ -143,6 +147,15 @@ class HttpRouter
|
|
143
147
|
@default_app = app
|
144
148
|
end
|
145
149
|
|
150
|
+
def register_node(n)
|
151
|
+
@nodes << n
|
152
|
+
@nodes.size - 1
|
153
|
+
end
|
154
|
+
|
155
|
+
def [](pos)
|
156
|
+
@nodes.at(pos)
|
157
|
+
end
|
158
|
+
|
146
159
|
# Generate a URL for a specified route. This will accept a list of variable values plus any other variable names named as a hash.
|
147
160
|
# This first value must be either the Route object or the name of the route.
|
148
161
|
#
|
@@ -191,6 +204,10 @@ class HttpRouter
|
|
191
204
|
cloned_router
|
192
205
|
end
|
193
206
|
|
207
|
+
def compile
|
208
|
+
@root.compile
|
209
|
+
end
|
210
|
+
|
194
211
|
private
|
195
212
|
def no_response(env, perform_call = true)
|
196
213
|
supported_methods = (@known_methods - [env['REQUEST_METHOD']]).select do |m|
|
data/lib/http_router/node.rb
CHANGED
@@ -11,16 +11,12 @@ class HttpRouter
|
|
11
11
|
autoload :Lookup, 'http_router/node/lookup'
|
12
12
|
autoload :Destination, 'http_router/node/destination'
|
13
13
|
|
14
|
-
attr_reader :priority, :router
|
14
|
+
attr_reader :priority, :router, :node_position
|
15
15
|
|
16
16
|
def initialize(router, matchers = [])
|
17
17
|
@router, @matchers = router, matchers
|
18
18
|
end
|
19
19
|
|
20
|
-
def [](request)
|
21
|
-
@matchers.each {|m| m[request] }; nil
|
22
|
-
end
|
23
|
-
|
24
20
|
def add_variable
|
25
21
|
add(Variable.new(@router))
|
26
22
|
end
|
@@ -61,15 +57,37 @@ class HttpRouter
|
|
61
57
|
false
|
62
58
|
end
|
63
59
|
|
60
|
+
def method_missing(m, *args, &blk)
|
61
|
+
if m.to_s == '[]'
|
62
|
+
compile
|
63
|
+
send(:[], *args)
|
64
|
+
else
|
65
|
+
super
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def compile
|
70
|
+
instance_eval "def [](r0)\n#{to_code(0)}\nnil\nend", __FILE__, __LINE__
|
71
|
+
end
|
72
|
+
|
64
73
|
private
|
65
74
|
def add(matcher)
|
66
75
|
@matchers << matcher unless matcher.usable?(@matchers.last)
|
67
76
|
@matchers.last
|
68
77
|
end
|
69
78
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
79
|
+
def to_code(pos)
|
80
|
+
@matchers.map{ |m| m.to_code(pos) }.join("\n") << "\n"
|
81
|
+
end
|
82
|
+
|
83
|
+
def indented_code(pos, code)
|
84
|
+
lines = code.
|
85
|
+
strip.
|
86
|
+
split(/\n/).
|
87
|
+
select{|l| !l.strip.size.zero?}
|
88
|
+
indent_size = lines.first[/ */].size
|
89
|
+
lines.map! {|l| "#{' ' * pos.next}#{l[indent_size, l.size]}"}
|
90
|
+
"\n" << lines.join("\n") << "\n"
|
73
91
|
end
|
74
92
|
end
|
75
93
|
end
|
@@ -1,26 +1,30 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class Node
|
3
3
|
class Arbitrary < Node
|
4
|
-
alias_method :node_lookup, :[]
|
5
4
|
attr_reader :allow_partial, :blk, :param_names
|
6
5
|
|
7
6
|
def initialize(router, allow_partial, blk, param_names)
|
8
7
|
@allow_partial, @blk, @param_names = allow_partial, blk, param_names
|
8
|
+
@node_position = router.register_node(blk)
|
9
9
|
super(router)
|
10
10
|
end
|
11
11
|
|
12
|
-
def [](request)
|
13
|
-
if request.path.empty? or (request.path.size == 1 and request.path[0] == '') or @allow_partial
|
14
|
-
request = request.clone
|
15
|
-
request.continue = proc { |state| node_lookup(request) if state }
|
16
|
-
params = @param_names.nil? ? {} : Hash[@param_names.zip(request.params)]
|
17
|
-
@blk.call(request, params)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
12
|
def usuable?(other)
|
22
13
|
other.class == self.class && other.allow_partial == allow_partial && other.blk == blk && other.param_names == param_names
|
23
14
|
end
|
15
|
+
|
16
|
+
def to_code(pos)
|
17
|
+
indented_code pos, "
|
18
|
+
#{"if r#{pos}.path_finished?" unless @allow_partial}
|
19
|
+
r#{pos.next} = r#{pos}.dup
|
20
|
+
r#{pos.next}.continue = proc { |state|
|
21
|
+
if state
|
22
|
+
#{super(pos.next)}
|
23
|
+
end
|
24
|
+
}
|
25
|
+
router.nodes.at(#{node_position})[r#{pos.next}, #{@param_names.nil? || @param_names.empty? ? '{}' : "Hash[#{@param_names.inspect}.zip(r#{pos.next}.params)]"}]
|
26
|
+
#{"end" unless @allow_partial}"
|
27
|
+
end
|
24
28
|
end
|
25
29
|
end
|
26
30
|
end
|
@@ -1,25 +1,26 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class Node
|
3
3
|
class Destination < Node
|
4
|
+
attr_reader :blk, :allow_partial, :param_names
|
5
|
+
|
4
6
|
def initialize(router, blk, allow_partial)
|
5
7
|
@blk, @allow_partial = blk, allow_partial
|
8
|
+
@node_position = router.register_node(blk)
|
6
9
|
super(router)
|
7
10
|
end
|
8
11
|
|
9
|
-
def [](request)
|
10
|
-
if request.path.empty? or (request.path.size == 1 and request.path[0] == '') or @allow_partial
|
11
|
-
request.passed_with = catch(:pass) do
|
12
|
-
request = request.clone
|
13
|
-
request.continue = proc { |state| destination(request) if state }
|
14
|
-
params = @param_names.nil? ? {} : Hash[@param_names.zip(request.params)]
|
15
|
-
@blk.call(request, params)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
12
|
def usuable?(other)
|
21
13
|
other.class == self.class && other.allow_partial == allow_partial && other.blk == blk
|
22
14
|
end
|
15
|
+
|
16
|
+
def to_code(pos)
|
17
|
+
indented_code pos, "
|
18
|
+
#{"if r#{pos}.path_finished?" unless @allow_partial}
|
19
|
+
r0.passed_with = catch(:pass) do
|
20
|
+
router.nodes.at(#{node_position})[r#{pos}, #{@param_names.nil? || @param_names.empty? ? 'nil' : "Hash[#{@param_names.inspect}.zip(r#{pos.next}.params)]"}]
|
21
|
+
end
|
22
|
+
#{"end" unless @allow_partial}"
|
23
|
+
end
|
23
24
|
end
|
24
25
|
end
|
25
26
|
end
|
@@ -7,15 +7,17 @@ class HttpRouter
|
|
7
7
|
super(router)
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
def to_code(pos)
|
11
|
+
indented_code pos, "
|
12
|
+
whole_path = \"/\#{r#{pos}.joined_path}\"
|
13
|
+
if match = #{matcher.inspect}.match(whole_path) and match[0].size == whole_path.size
|
14
|
+
r#{pos.next} = r#{pos}.dup
|
15
|
+
r#{pos.next}.extra_env['router.regex_match'] = match
|
16
|
+
r#{pos.next}.path = ['']
|
17
|
+
" << (//.respond_to?(:names) ?
|
18
|
+
"match.names.size.times{|i| r#{pos.next}.params << match[i + 1]} if match.respond_to?(:names) && match.names" : "") << "
|
19
|
+
#{super(pos.next)}
|
20
|
+
end"
|
19
21
|
end
|
20
22
|
|
21
23
|
def usuable?(other)
|
@@ -1,20 +1,21 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class Node
|
3
3
|
class Glob < Node
|
4
|
-
def [](request)
|
5
|
-
request = request.clone
|
6
|
-
request.params << []
|
7
|
-
remaining_parts = request.path.dup
|
8
|
-
until remaining_parts.empty?
|
9
|
-
request.params[-1] << unescape(remaining_parts.shift)
|
10
|
-
request.path = remaining_parts
|
11
|
-
super(request)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
4
|
def usuable?(other)
|
16
5
|
other.class == self.class
|
17
6
|
end
|
7
|
+
|
8
|
+
def to_code(pos)
|
9
|
+
indented_code pos, "
|
10
|
+
r#{pos.next} = r#{pos}.dup
|
11
|
+
r#{pos.next}.params << []
|
12
|
+
remaining_parts = r#{pos.next}.path.dup
|
13
|
+
until remaining_parts.empty?
|
14
|
+
r#{pos.next}.params[-1] << URI.unescape(remaining_parts.shift)
|
15
|
+
r#{pos.next}.path = remaining_parts
|
16
|
+
#{super(pos.next)}
|
17
|
+
end"
|
18
|
+
end
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
@@ -1,8 +1,17 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class Node
|
3
3
|
class GlobRegex < SpanningRegex
|
4
|
-
def
|
5
|
-
|
4
|
+
def to_code(pos)
|
5
|
+
indented_code pos, "
|
6
|
+
whole_path = r#{pos}.joined_path
|
7
|
+
if match = #{@matcher.inspect}.match(whole_path) and match.begin(0).zero?
|
8
|
+
r#{pos.next} = r#{pos}.dup\n" <<
|
9
|
+
@capturing_indicies.map { |c| "r#{pos.next}.params << URI.unescape(match[#{c}].split(/\\//))\n" }.join << "
|
10
|
+
remaining_path = whole_path[match[0].size + (whole_path[match[0].size] == ?/ ? 1 : 0), whole_path.size]
|
11
|
+
r#{pos.next}.path = remaining_path.split('/')
|
12
|
+
#{super(pos.next)}
|
13
|
+
end
|
14
|
+
"
|
6
15
|
end
|
7
16
|
end
|
8
17
|
end
|
@@ -6,13 +6,6 @@ class HttpRouter
|
|
6
6
|
super(router)
|
7
7
|
end
|
8
8
|
|
9
|
-
def [](request)
|
10
|
-
if @map[request.path.first]
|
11
|
-
request = request.clone
|
12
|
-
@map[request.path.shift].each{|m| m[request]}
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
9
|
def add(part)
|
17
10
|
Node.new(@router, @map[part] ||= [])
|
18
11
|
end
|
@@ -20,6 +13,18 @@ class HttpRouter
|
|
20
13
|
def usuable?(other)
|
21
14
|
other.class == self.class
|
22
15
|
end
|
16
|
+
|
17
|
+
def to_code(pos)
|
18
|
+
code = "case r#{pos}.path.first\n"
|
19
|
+
@map.keys.each do |k|
|
20
|
+
code << "when #{k.inspect}\n
|
21
|
+
r#{pos.next} = r#{pos}.dup
|
22
|
+
r#{pos.next}.path.shift
|
23
|
+
#{@map[k].map{|n| n.to_code(pos.next)} * "\n"}"
|
24
|
+
end
|
25
|
+
code << "\nend"
|
26
|
+
indented_code pos, code
|
27
|
+
end
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class Node
|
3
3
|
class Regex < Node
|
4
|
-
alias_method :
|
4
|
+
alias_method :node_to_code, :to_code
|
5
5
|
attr_reader :matcher, :splitting_indicies, :capturing_indicies
|
6
6
|
|
7
7
|
def initialize(router, matcher, capturing_indicies, splitting_indicies = nil)
|
@@ -9,23 +9,20 @@ class HttpRouter
|
|
9
9
|
super(router)
|
10
10
|
end
|
11
11
|
|
12
|
-
def [](request)
|
13
|
-
if match = @matcher.match(request.path.first) and match.begin(0).zero?
|
14
|
-
request = request.clone
|
15
|
-
request.path.shift
|
16
|
-
add_params(request, match)
|
17
|
-
super(request)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def add_params(request, match)
|
22
|
-
@splitting_indicies.each { |idx| request.params << unescape(match[idx]).split(/\//) } if @splitting_indicies
|
23
|
-
@capturing_indicies.each { |idx| request.params << unescape(match[idx]) }
|
24
|
-
end
|
25
|
-
|
26
12
|
def usuable?(other)
|
27
13
|
other.class == self.class && other.matcher == matcher && other.splitting_indicies == splitting_indicies && other.capturing_indicies == capturing_indicies
|
28
14
|
end
|
15
|
+
|
16
|
+
def to_code(pos)
|
17
|
+
indented_code pos, "
|
18
|
+
if match = #{@matcher.inspect}.match(r#{pos}.path.first) and match.begin(0).zero?
|
19
|
+
r#{pos.next} = r#{pos}.dup
|
20
|
+
r#{pos.next}.path.shift\n" <<
|
21
|
+
@splitting_indicies.map { |s| "r#{pos.next}.params << URI.unescape(match[#{s}]).split(/\\//)\n" }.join <<
|
22
|
+
@capturing_indicies.map { |c| "r#{pos.next}.params << URI.unescape(match[#{c}])\n" }.join << "
|
23
|
+
#{super(pos.next)}
|
24
|
+
end"
|
25
|
+
end
|
29
26
|
end
|
30
27
|
end
|
31
28
|
end
|
@@ -9,20 +9,21 @@ class HttpRouter
|
|
9
9
|
super(router)
|
10
10
|
end
|
11
11
|
|
12
|
-
def [](request)
|
13
|
-
@opts.each{|k,v|
|
14
|
-
test = request.rack_request.send(k)
|
15
|
-
return unless case v
|
16
|
-
when Array then v.any?{|vv| vv === test}
|
17
|
-
else v === test
|
18
|
-
end
|
19
|
-
}
|
20
|
-
super(request)
|
21
|
-
end
|
22
|
-
|
23
12
|
def usuable?(other)
|
24
13
|
other.class == self.class && other.opts == opts
|
25
14
|
end
|
15
|
+
|
16
|
+
def to_code(pos)
|
17
|
+
code = "if "
|
18
|
+
code << @opts.map do |k,v|
|
19
|
+
case v
|
20
|
+
when Array then "(#{v.map{|vv| "#{vv.inspect} === r#{pos}.rack_request.#{k}"}.join(' or ')})"
|
21
|
+
else "#{v.inspect} === r#{pos}.rack_request.#{k.inspect}"
|
22
|
+
end
|
23
|
+
end * ' and '
|
24
|
+
code << "\n #{super}\nend"
|
25
|
+
indented_code pos, code
|
26
|
+
end
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
@@ -1,15 +1,18 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class Node
|
3
3
|
class SpanningRegex < Regex
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
def to_code(pos)
|
5
|
+
indented_code(pos, "
|
6
|
+
whole_path = r#{pos}.joined_path
|
7
|
+
if match = #{@matcher.inspect}.match(whole_path) and match.begin(0).zero?
|
8
|
+
r#{pos.next} = r#{pos}.dup\n" <<
|
9
|
+
(@splitting_indicies || []).map { |s| "r#{pos.next}.params << URI.unescape(match[#{s}]).split(/\\//)\n" }.join <<
|
10
|
+
@capturing_indicies.map { |c| "r#{pos.next}.params << URI.unescape(match[#{c}])\n" }.join << "
|
11
|
+
remaining_path = whole_path[match[0].size + (whole_path[match[0].size] == ?/ ? 1 : 0), whole_path.size]
|
12
|
+
r#{pos.next}.path = remaining_path.split('/')
|
13
|
+
#{node_to_code(pos.next)}
|
14
|
+
end
|
15
|
+
")
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
@@ -1,17 +1,18 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class Node
|
3
3
|
class Variable < Node
|
4
|
-
def [](request)
|
5
|
-
unless request.path.empty?
|
6
|
-
request = request.clone
|
7
|
-
request.params << unescape(request.path.shift)
|
8
|
-
super(request)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
4
|
def usuable?(other)
|
13
5
|
other.class == self.class
|
14
6
|
end
|
7
|
+
|
8
|
+
def to_code(pos)
|
9
|
+
indented_code(pos, "
|
10
|
+
unless r#{pos}.path_finished?
|
11
|
+
r#{pos.next} = r#{pos}.dup
|
12
|
+
r#{pos.next}.params << URI.unescape(r#{pos.next}.path.shift)
|
13
|
+
#{super(pos.next)}
|
14
|
+
end")
|
15
|
+
end
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
data/lib/http_router/request.rb
CHANGED
@@ -27,12 +27,16 @@ class HttpRouter
|
|
27
27
|
"request path, #{path.inspect}"
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
30
|
+
def dup
|
31
31
|
dup_obj = super
|
32
32
|
dup_obj.path = path.dup
|
33
33
|
dup_obj.params = params.dup
|
34
34
|
dup_obj.extra_env = extra_env.dup
|
35
35
|
dup_obj
|
36
36
|
end
|
37
|
+
|
38
|
+
def path_finished?
|
39
|
+
@path.size == 0 or @path.size == 1 && @path.first == ''
|
40
|
+
end
|
37
41
|
end
|
38
42
|
end
|
data/lib/http_router/route.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'url_mount'
|
2
|
-
require 'uri'
|
3
1
|
|
4
2
|
class HttpRouter
|
5
3
|
class Route
|
@@ -300,7 +298,7 @@ class HttpRouter
|
|
300
298
|
when Hash
|
301
299
|
value.each{ |k, v| append_querystring_value(uri, "#{key}[#{k}]", v) }
|
302
300
|
else
|
303
|
-
uri << '&' <<
|
301
|
+
uri << '&' << CGI.escape(key.to_s) << '=' << CGI.escape(value.to_s)
|
304
302
|
end
|
305
303
|
end
|
306
304
|
|
data/lib/http_router/version.rb
CHANGED
data/test/test_recognize.rb
CHANGED
@@ -4,12 +4,27 @@ class TestRecognition < MiniTest::Unit::TestCase
|
|
4
4
|
assert_route router.add(''), '/'
|
5
5
|
end
|
6
6
|
|
7
|
-
def
|
7
|
+
def test_simple1
|
8
8
|
assert_route router.add('/'), '/'
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_simple2
|
9
12
|
assert_route router.add('/test'), '/test'
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_simple3
|
10
16
|
assert_route router.add('/test/one'), '/test/one'
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_simple4
|
11
20
|
assert_route router.add('/test/one/two'), '/test/one/two'
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_simple5
|
12
24
|
assert_route router.add('/test.html'), '/test.html'
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_simple6
|
13
28
|
assert_route router.add('/.html'), '/.html'
|
14
29
|
end
|
15
30
|
|
data/test/test_request.rb
CHANGED
@@ -6,6 +6,12 @@ class TestRequest < MiniTest::Unit::TestCase
|
|
6
6
|
assert_status(405, Rack::MockRequest.env_for('/test', :method => 'GET'))
|
7
7
|
end
|
8
8
|
|
9
|
+
def test_simple_case_with_array
|
10
|
+
r = router { add('test', :request => {:request_methods => ['POST', 'GET']}) }
|
11
|
+
assert_route r, Rack::MockRequest.env_for('/test', :method => 'POST')
|
12
|
+
assert_route r, Rack::MockRequest.env_for('/test', :method => 'GET')
|
13
|
+
end
|
14
|
+
|
9
15
|
def test_single_app_with_404
|
10
16
|
r = router { add('test').post.to{|env| [404, {}, []]} }
|
11
17
|
assert_route nil, Rack::MockRequest.env_for('/test', :method => 'POST')
|
data/test/test_variable.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http_router
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 63
|
4
5
|
prerelease:
|
5
|
-
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 8
|
9
|
+
- 0
|
10
|
+
version: 0.8.0
|
6
11
|
platform: ruby
|
7
12
|
authors:
|
8
13
|
- Joshua Hull
|
@@ -10,108 +15,147 @@ autorequire:
|
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
17
|
|
13
|
-
date: 2011-
|
18
|
+
date: 2011-06-01 00:00:00 -04:00
|
14
19
|
default_executable:
|
15
20
|
dependencies:
|
16
21
|
- !ruby/object:Gem::Dependency
|
17
|
-
|
18
|
-
prerelease: false
|
19
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
22
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
20
23
|
none: false
|
21
24
|
requirements:
|
22
25
|
- - ">="
|
23
26
|
- !ruby/object:Gem::Version
|
27
|
+
hash: 23
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 0
|
31
|
+
- 0
|
24
32
|
version: 1.0.0
|
33
|
+
requirement: *id001
|
34
|
+
prerelease: false
|
25
35
|
type: :runtime
|
26
|
-
|
36
|
+
name: rack
|
27
37
|
- !ruby/object:Gem::Dependency
|
28
|
-
|
29
|
-
prerelease: false
|
30
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
31
39
|
none: false
|
32
40
|
requirements:
|
33
41
|
- - ~>
|
34
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 21
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
- 2
|
47
|
+
- 1
|
35
48
|
version: 0.2.1
|
49
|
+
requirement: *id002
|
50
|
+
prerelease: false
|
36
51
|
type: :runtime
|
37
|
-
|
52
|
+
name: url_mount
|
38
53
|
- !ruby/object:Gem::Dependency
|
39
|
-
|
40
|
-
prerelease: false
|
41
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
42
55
|
none: false
|
43
56
|
requirements:
|
44
57
|
- - ~>
|
45
58
|
- !ruby/object:Gem::Version
|
59
|
+
hash: 15
|
60
|
+
segments:
|
61
|
+
- 2
|
62
|
+
- 0
|
63
|
+
- 0
|
46
64
|
version: 2.0.0
|
65
|
+
requirement: *id003
|
66
|
+
prerelease: false
|
47
67
|
type: :development
|
48
|
-
|
68
|
+
name: minitest
|
49
69
|
- !ruby/object:Gem::Dependency
|
50
|
-
|
51
|
-
prerelease: false
|
52
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
70
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
53
71
|
none: false
|
54
72
|
requirements:
|
55
73
|
- - ">="
|
56
74
|
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
57
78
|
version: "0"
|
79
|
+
requirement: *id004
|
80
|
+
prerelease: false
|
58
81
|
type: :development
|
59
|
-
|
82
|
+
name: code_stats
|
60
83
|
- !ruby/object:Gem::Dependency
|
61
|
-
|
62
|
-
prerelease: false
|
63
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
84
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
64
85
|
none: false
|
65
86
|
requirements:
|
66
87
|
- - ~>
|
67
88
|
- !ruby/object:Gem::Version
|
89
|
+
hash: 49
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
- 8
|
93
|
+
- 7
|
68
94
|
version: 0.8.7
|
95
|
+
requirement: *id005
|
96
|
+
prerelease: false
|
69
97
|
type: :development
|
70
|
-
|
98
|
+
name: rake
|
71
99
|
- !ruby/object:Gem::Dependency
|
72
|
-
|
73
|
-
prerelease: false
|
74
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
100
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
75
101
|
none: false
|
76
102
|
requirements:
|
77
103
|
- - ">="
|
78
104
|
- !ruby/object:Gem::Version
|
105
|
+
hash: 3
|
106
|
+
segments:
|
107
|
+
- 0
|
79
108
|
version: "0"
|
109
|
+
requirement: *id006
|
110
|
+
prerelease: false
|
80
111
|
type: :development
|
81
|
-
|
112
|
+
name: rbench
|
82
113
|
- !ruby/object:Gem::Dependency
|
83
|
-
|
84
|
-
prerelease: false
|
85
|
-
requirement: &id007 !ruby/object:Gem::Requirement
|
114
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
86
115
|
none: false
|
87
116
|
requirements:
|
88
117
|
- - ">="
|
89
118
|
- !ruby/object:Gem::Version
|
119
|
+
hash: 3
|
120
|
+
segments:
|
121
|
+
- 0
|
90
122
|
version: "0"
|
123
|
+
requirement: *id007
|
124
|
+
prerelease: false
|
91
125
|
type: :development
|
92
|
-
|
126
|
+
name: phocus
|
93
127
|
- !ruby/object:Gem::Dependency
|
94
|
-
|
95
|
-
prerelease: false
|
96
|
-
requirement: &id008 !ruby/object:Gem::Requirement
|
128
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
97
129
|
none: false
|
98
130
|
requirements:
|
99
131
|
- - ~>
|
100
132
|
- !ruby/object:Gem::Version
|
133
|
+
hash: 23
|
134
|
+
segments:
|
135
|
+
- 1
|
136
|
+
- 0
|
137
|
+
- 0
|
101
138
|
version: 1.0.0
|
139
|
+
requirement: *id008
|
140
|
+
prerelease: false
|
102
141
|
type: :development
|
103
|
-
|
142
|
+
name: bundler
|
104
143
|
- !ruby/object:Gem::Dependency
|
105
|
-
|
106
|
-
prerelease: false
|
107
|
-
requirement: &id009 !ruby/object:Gem::Requirement
|
144
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
108
145
|
none: false
|
109
146
|
requirements:
|
110
147
|
- - "="
|
111
148
|
- !ruby/object:Gem::Version
|
149
|
+
hash: 15
|
150
|
+
segments:
|
151
|
+
- 1
|
152
|
+
- 2
|
153
|
+
- 8
|
112
154
|
version: 1.2.8
|
155
|
+
requirement: *id009
|
156
|
+
prerelease: false
|
113
157
|
type: :development
|
114
|
-
|
158
|
+
name: thin
|
115
159
|
description: This library allows you to recognize and build URLs in a Rack application.
|
116
160
|
email: joshbuddy@gmail.com
|
117
161
|
executables: []
|
@@ -195,12 +239,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
195
239
|
requirements:
|
196
240
|
- - ">="
|
197
241
|
- !ruby/object:Gem::Version
|
242
|
+
hash: 3
|
243
|
+
segments:
|
244
|
+
- 0
|
198
245
|
version: "0"
|
199
246
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
247
|
none: false
|
201
248
|
requirements:
|
202
249
|
- - ">="
|
203
250
|
- !ruby/object:Gem::Version
|
251
|
+
hash: 3
|
252
|
+
segments:
|
253
|
+
- 0
|
204
254
|
version: "0"
|
205
255
|
requirements: []
|
206
256
|
|