http_router 0.6.2 → 0.6.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.
- data/README.rdoc +3 -3
- data/benchmarks/rack_mount.rb +1 -1
- data/benchmarks/rack_recognition_bm.rb +4 -4
- data/http_router.gemspec +2 -2
- data/lib/http_router.rb +28 -6
- data/lib/http_router/node.rb +21 -19
- data/lib/http_router/node/regex.rb +4 -4
- data/lib/http_router/optional_compiler.rb +1 -1
- data/lib/http_router/regex_route.rb +2 -2
- data/lib/http_router/request.rb +1 -1
- data/lib/http_router/route.rb +27 -6
- data/lib/http_router/version.rb +1 -1
- data/test/helper.rb +2 -2
- data/test/rack/test_route.rb +1 -1
- data/test/test_generate.rb +3 -3
- data/test/test_interstitial.rb +1 -1
- data/test/test_misc.rb +22 -28
- data/test/test_mounting.rb +81 -87
- data/test/test_recognize.rb +1 -1
- data/test/test_request.rb +1 -1
- data/test/test_variable.rb +15 -3
- metadata +6 -6
data/README.rdoc
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
* Partial matches.
|
9
9
|
* Supports interstitial variables (e.g. /my-:variable-brings.all.the.boys/yard) and unnamed variable /one/:/two
|
10
10
|
* Very fast and small code base (~1,000 loc).
|
11
|
-
* Sinatra
|
11
|
+
* Sinatra via https://github.com/joshbuddy/http_router_sinatra
|
12
12
|
|
13
13
|
== Usage
|
14
14
|
|
@@ -36,12 +36,12 @@ As well, you can escape the following characters with a backslash: <tt>( ) : *</
|
|
36
36
|
Once you have a route object, use <tt>HttpRouter::Route#to</tt> to add a destination and <tt>HttpRouter::Route#name</tt> to name it.
|
37
37
|
|
38
38
|
e.g.
|
39
|
-
|
39
|
+
|
40
40
|
r = HttpRouter.new
|
41
41
|
r.add('/test/:variable(.:format)').name(:my_test_path).to {|env| [200, {}, "Hey dude #{env['router.params'][:variable]}"]}
|
42
42
|
r.add('/test').redirect("http://www.google.com/")
|
43
43
|
r.add('/static').static('/my_file_system')
|
44
|
-
|
44
|
+
|
45
45
|
As well, you can support regex matching and request conditions. To add a regex match, use <tt>matching(:id => /\d+/)</tt>.
|
46
46
|
To match on a request condition you can use <tt>condition(:request_method => %w(POST HEAD))</tt> or more succinctly <tt>request_method('POST', 'HEAD')</tt>.
|
47
47
|
|
data/benchmarks/rack_mount.rb
CHANGED
@@ -28,19 +28,19 @@ RBench.run(TIMES) do
|
|
28
28
|
report "4 levels, static" do
|
29
29
|
u.call(simple2_env).first == 200 or raise
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
report "8 levels, static" do
|
33
33
|
u.call(simple3_env).first == 200 or raise
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
report "4 levels, 1 dynamic" do
|
37
37
|
u.call(simple_and_dynamic_env).first == 200 or raise
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
report "8 levels, 3 dynamic" do
|
41
41
|
u.call(simple_and_dynamic_env1).first == 200 or raise
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
report "4 levels, 1 greedy" do
|
45
45
|
u.call(simple_and_dynamic_env2).first == 200 or raise
|
46
46
|
end
|
data/http_router.gemspec
CHANGED
@@ -7,8 +7,8 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = HttpRouter::VERSION
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
9
|
s.authors = ["Joshua Hull"]
|
10
|
-
s.summary = "A kick-ass HTTP router for use in Rack
|
11
|
-
s.description = "This library allows you to recognize and build URLs in a Rack application.
|
10
|
+
s.summary = "A kick-ass HTTP router for use in Rack"
|
11
|
+
s.description = "This library allows you to recognize and build URLs in a Rack application."
|
12
12
|
s.email = %q{joshbuddy@gmail.com}
|
13
13
|
s.extra_rdoc_files = ['README.rdoc']
|
14
14
|
s.files = `git ls-files`.split("\n")
|
data/lib/http_router.rb
CHANGED
@@ -9,17 +9,19 @@ require 'http_router/regex_route'
|
|
9
9
|
require 'http_router/optional_compiler'
|
10
10
|
|
11
11
|
class HttpRouter
|
12
|
-
|
12
|
+
|
13
13
|
attr_reader :root, :routes, :known_methods, :named_routes
|
14
|
-
attr_accessor :default_app
|
14
|
+
attr_accessor :default_app, :url_mount
|
15
15
|
|
16
16
|
UngeneratableRouteException = Class.new(RuntimeError)
|
17
17
|
InvalidRouteException = Class.new(RuntimeError)
|
18
18
|
MissingParameterException = Class.new(RuntimeError)
|
19
19
|
|
20
|
-
def initialize(
|
20
|
+
def initialize(options = nil, &blk)
|
21
21
|
reset!
|
22
|
-
@
|
22
|
+
@options = options
|
23
|
+
@default_app = default_app || options && options[:default_app] || proc{|env| ::Rack::Response.new("Not Found", 404).finish }
|
24
|
+
@ignore_trailing_slash = options && options.key?(:ignore_trailing_slash) ? options[:ignore_trailing_slash] : true
|
23
25
|
instance_eval(&blk) if blk
|
24
26
|
end
|
25
27
|
|
@@ -30,11 +32,15 @@ class HttpRouter
|
|
30
32
|
else
|
31
33
|
Route.new(self, path, opts)
|
32
34
|
end
|
33
|
-
|
35
|
+
add_route(route)
|
34
36
|
route.to(app) if app
|
35
37
|
route
|
36
38
|
end
|
37
39
|
|
40
|
+
def add_route(route)
|
41
|
+
@routes << route
|
42
|
+
end
|
43
|
+
|
38
44
|
def add_with_request_method(path, method, opts = {}, &app)
|
39
45
|
route = add(path, opts).send(method.to_sym)
|
40
46
|
route.to(app) if app
|
@@ -68,7 +74,7 @@ class HttpRouter
|
|
68
74
|
@default_app.call(env)
|
69
75
|
end
|
70
76
|
end
|
71
|
-
|
77
|
+
|
72
78
|
def reset!
|
73
79
|
@root = Node.new(self)
|
74
80
|
@default_app = Proc.new{ |env| Rack::Response.new("Your request couldn't be found", 404).finish }
|
@@ -104,4 +110,20 @@ class HttpRouter
|
|
104
110
|
end
|
105
111
|
uri
|
106
112
|
end
|
113
|
+
|
114
|
+
# Creates a deep-copy of the router.
|
115
|
+
def clone(klass = self.class)
|
116
|
+
cloned_router = klass.new(@options)
|
117
|
+
@routes.each do |route|
|
118
|
+
new_route = route.clone(cloned_router)
|
119
|
+
cloned_router.add_route(new_route)
|
120
|
+
new_route.name(route.named) if route.named
|
121
|
+
begin
|
122
|
+
new_route.to route.dest.clone
|
123
|
+
rescue
|
124
|
+
new_route.to route.dest
|
125
|
+
end
|
126
|
+
end
|
127
|
+
cloned_router
|
128
|
+
end
|
107
129
|
end
|
data/lib/http_router/node.rb
CHANGED
@@ -29,26 +29,26 @@ class HttpRouter
|
|
29
29
|
def linear(request)
|
30
30
|
@linear && @linear.each{|n| n[request]}
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def lookup(request)
|
34
34
|
if @lookup && @lookup[request.path.first]
|
35
35
|
request = request.clone
|
36
36
|
@lookup[request.path.shift][request]
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
def variable(request)
|
41
41
|
@variable && @variable[request]
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def glob(request)
|
45
45
|
@glob && @glob[request]
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def request(request)
|
49
49
|
@request && @request[request]
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
def arbitrary(request)
|
53
53
|
@arbitrary && @arbitrary.each{|n| n[request]}
|
54
54
|
end
|
@@ -132,38 +132,40 @@ class HttpRouter
|
|
132
132
|
@arbitrary << Arbitrary.new(@router, allow_partial, blk, param_names)
|
133
133
|
@arbitrary.last
|
134
134
|
end
|
135
|
-
|
136
|
-
def add_match(regexp, matching_indicies = [0], priority = 0)
|
135
|
+
|
136
|
+
def add_match(regexp, matching_indicies = [0], priority = 0, splitting_indicies = nil)
|
137
|
+
add_prioritized_match(Regex.new(@router, regexp, matching_indicies, priority, splitting_indicies))
|
138
|
+
end
|
139
|
+
|
140
|
+
def add_spanning_match(regexp, matching_indicies = [0], priority = 0, splitting_indicies = nil)
|
141
|
+
add_prioritized_match(SpanningRegex.new(@router, regexp, matching_indicies, priority, splitting_indicies))
|
142
|
+
end
|
143
|
+
|
144
|
+
def add_prioritized_match(match)
|
137
145
|
@linear ||= []
|
138
|
-
if priority != 0
|
146
|
+
if match.priority != 0
|
139
147
|
@linear.each_with_index { |n, i|
|
140
|
-
if priority > (n.priority || 0)
|
141
|
-
@linear[i, 0] =
|
148
|
+
if match.priority > (n.priority || 0)
|
149
|
+
@linear[i, 0] = match
|
142
150
|
return @linear[i]
|
143
151
|
end
|
144
152
|
}
|
145
153
|
end
|
146
|
-
@linear <<
|
154
|
+
@linear << match
|
147
155
|
@linear.last
|
148
156
|
end
|
149
157
|
|
150
|
-
def add_spanning_match(regexp, matching_indicies = [0])
|
151
|
-
@linear ||= []
|
152
|
-
@linear << SpanningRegex.new(@router, regexp, matching_indicies)
|
153
|
-
@linear.last
|
154
|
-
end
|
155
|
-
|
156
158
|
def add_free_match(regexp)
|
157
159
|
@linear ||= []
|
158
160
|
@linear << FreeRegex.new(@router, regexp)
|
159
161
|
@linear.last
|
160
162
|
end
|
161
|
-
|
163
|
+
|
162
164
|
def add_destination(route)
|
163
165
|
@destination ||= []
|
164
166
|
@destination << route
|
165
167
|
end
|
166
|
-
|
168
|
+
|
167
169
|
def add_lookup(part)
|
168
170
|
@lookup ||= {}
|
169
171
|
@lookup[part] ||= Node.new(@router)
|
@@ -2,11 +2,10 @@ class HttpRouter
|
|
2
2
|
class Node
|
3
3
|
class Regex < Node
|
4
4
|
alias_method :node_lookup, :[]
|
5
|
+
attr_reader :matcher, :splitting_indicies
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(router, matcher, capturing_indicies, priority = 0)
|
9
|
-
@router, @matcher, @capturing_indicies, @priority = router, matcher, capturing_indicies, priority
|
7
|
+
def initialize(router, matcher, capturing_indicies, priority = 0, splitting_indicies = nil)
|
8
|
+
@router, @matcher, @capturing_indicies, @priority, @splitting_indicies = router, matcher, capturing_indicies, priority, splitting_indicies
|
10
9
|
end
|
11
10
|
|
12
11
|
def [](request)
|
@@ -19,6 +18,7 @@ class HttpRouter
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def add_params(request, match)
|
21
|
+
@splitting_indicies.each { |idx| request.params << unescape(match[idx]).split(/\//) } if @splitting_indicies
|
22
22
|
@capturing_indicies.each { |idx| request.params << unescape(match[idx]) }
|
23
23
|
end
|
24
24
|
end
|
@@ -22,7 +22,7 @@ class HttpRouter
|
|
22
22
|
def add_to_current_set(c)
|
23
23
|
(@start_index...@end_index).each { |path_index| @paths[path_index] << c }
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# over current working set, double @paths
|
27
27
|
def double_paths
|
28
28
|
(@start_index...@end_index).each { |path_index| @paths << @paths[path_index].dup }
|
@@ -1,11 +1,11 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class RegexRoute < Route
|
3
3
|
def initialize(router, path, opts = {})
|
4
|
-
@router, @
|
4
|
+
@router, @original_path, @opts = router, path, opts
|
5
5
|
end
|
6
6
|
|
7
7
|
def compile
|
8
|
-
add_non_path_to_tree(@router.root.add_free_match(
|
8
|
+
add_non_path_to_tree(@router.root.add_free_match(@original_path), path, [])
|
9
9
|
@compiled = true
|
10
10
|
end
|
11
11
|
|
data/lib/http_router/request.rb
CHANGED
data/lib/http_router/route.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'url_mount'
|
2
|
+
|
1
3
|
class HttpRouter
|
2
4
|
class Route
|
3
5
|
attr_reader :default_values, :matches_with, :router, :path, :conditions
|
@@ -126,6 +128,10 @@ class HttpRouter
|
|
126
128
|
@router.append_querystring(result, extra_params)
|
127
129
|
end
|
128
130
|
|
131
|
+
def clone(new_router)
|
132
|
+
Route.new(new_router, @original_path.dup, as_options)
|
133
|
+
end
|
134
|
+
|
129
135
|
def url_with_params(*args)
|
130
136
|
options = args.last.is_a?(Hash) ? args.pop : nil
|
131
137
|
options = options.nil? ? default_values.dup : default_values.merge(options) if default_values
|
@@ -137,9 +143,8 @@ class HttpRouter
|
|
137
143
|
end
|
138
144
|
raise UngeneratableRouteException unless path
|
139
145
|
result, params = path.url(args, options)
|
140
|
-
|
141
|
-
|
142
|
-
[result, params]
|
146
|
+
mount_point = router.url_mount && router.url_mount.url(options)
|
147
|
+
mount_point ? [File.join(mount_point, result), params] : [result, params]
|
143
148
|
end
|
144
149
|
|
145
150
|
def significant_variable_names
|
@@ -203,14 +208,26 @@ class HttpRouter
|
|
203
208
|
node.add_lookup(parts[0])
|
204
209
|
end
|
205
210
|
else
|
211
|
+
capturing_indicies = []
|
212
|
+
splitting_indicies = []
|
206
213
|
captures = 0
|
207
214
|
priority = 0
|
215
|
+
spans = false
|
208
216
|
regex = parts.inject('') do |reg, part|
|
209
217
|
reg << case part[0]
|
210
218
|
when ?\\
|
211
219
|
Regexp.quote(part[1].chr)
|
212
220
|
when ?:
|
213
221
|
captures += 1
|
222
|
+
capturing_indicies << captures
|
223
|
+
name = part[1, part.size].to_sym
|
224
|
+
param_names << name
|
225
|
+
matches_with[name] = @opts[name]
|
226
|
+
"(#{(@opts[name] || '[^/]*?')})"
|
227
|
+
when ?*
|
228
|
+
spans = true
|
229
|
+
captures += 1
|
230
|
+
splitting_indicies << captures
|
214
231
|
name = part[1, part.size].to_sym
|
215
232
|
param_names << name
|
216
233
|
matches_with[name] = @opts[name]
|
@@ -220,9 +237,8 @@ class HttpRouter
|
|
220
237
|
Regexp.quote(part)
|
221
238
|
end
|
222
239
|
end
|
223
|
-
|
224
|
-
|
225
|
-
node = node.add_match(Regexp.new("#{regex}$"), capturing_indicies, priority)
|
240
|
+
node = spans ? node.add_spanning_match(Regexp.new("#{regex}$"), capturing_indicies, priority, splitting_indicies) :
|
241
|
+
node.add_match(Regexp.new("#{regex}$"), capturing_indicies, priority, splitting_indicies)
|
226
242
|
end
|
227
243
|
end
|
228
244
|
add_non_path_to_tree(node, path, param_names)
|
@@ -239,6 +255,11 @@ class HttpRouter
|
|
239
255
|
@arbitrary.each{|a| nodes.map!{|n| n.add_arbitrary(a, match_partially?, names)} } if @arbitrary
|
240
256
|
path_obj = Path.new(self, path, names)
|
241
257
|
nodes.each{|n| n.add_destination(path_obj)}
|
258
|
+
if dest.respond_to?(:url_mount=)
|
259
|
+
urlmount = UrlMount.new(@original_path, @default_values)
|
260
|
+
urlmount.url_mount = router.url_mount if router.url_mount
|
261
|
+
dest.url_mount = urlmount
|
262
|
+
end
|
242
263
|
path_obj
|
243
264
|
end
|
244
265
|
end
|
data/lib/http_router/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -29,7 +29,7 @@ class MiniTest::Unit::TestCase
|
|
29
29
|
response.last.each {|p| body << p}
|
30
30
|
assert_equal expect, body
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def assert_header(header, response)
|
34
34
|
response = Rack::MockRequest.env_for(response) if response.is_a?(String)
|
35
35
|
response = router.call(response) if response.is_a?(Hash)
|
@@ -64,7 +64,7 @@ class MiniTest::Unit::TestCase
|
|
64
64
|
assert_equal 404, response.first
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
def assert_generate(path, route, *args)
|
69
69
|
if route.is_a?(String)
|
70
70
|
router.reset!
|
data/test/rack/test_route.rb
CHANGED
data/test/test_generate.rb
CHANGED
@@ -19,12 +19,12 @@ class TestGenerate < MiniTest::Unit::TestCase
|
|
19
19
|
assert_generate '/test', '/:var', :var => 'test'
|
20
20
|
assert_generate '/test', '/:var', 'test'
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def test_array_with_extras
|
24
24
|
assert_generate '/test?query=string', '/:var', :var => 'test', :query => 'string'
|
25
25
|
assert_generate '/test?query=string', '/:var', 'test', :query => 'string'
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def test_multiple_dynamics
|
29
29
|
assert_generate '/one/two', "/:var/:baz", :var => 'one', :baz => 'two'
|
30
30
|
assert_generate '/one/two', "/:var/:baz", 'one', 'two'
|
@@ -60,7 +60,7 @@ class TestGenerate < MiniTest::Unit::TestCase
|
|
60
60
|
assert_generate '/var/fooz', "/:var1(/:var2)", :var1 => 'var', :var2 => 'fooz'
|
61
61
|
assert_raises(HttpRouter::UngeneratableRouteException) { router.url(router.add("/:var1(/:var2)").to(:test), :var2 => 'fooz') }
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def test_optionals_with_format
|
65
65
|
assert_generate '/var', "/:var1(/:var2.:format)", 'var'
|
66
66
|
assert_generate '/var/fooz.html', "/:var1(/:var2.:format)", 'var', 'fooz', 'html'
|
data/test/test_interstitial.rb
CHANGED
@@ -35,7 +35,7 @@ class TestInterstitial < MiniTest::Unit::TestCase
|
|
35
35
|
assert_route r5, '/one-value-time-one-variable', {:var1 => 'one', :var2 => 'value', :var3 => 'time', :var4 => 'one', :var5 => 'variable'}
|
36
36
|
assert_route r6, '/one-value-time-one-value-time', {:var1 => 'one', :var2 => 'value', :var3 => 'time', :var4 => 'one', :var5 => 'value', :var6 => 'time'}
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def test_regex_with_mutliple_variables
|
40
40
|
with_regex, without_regex = router {
|
41
41
|
add("/:common_variable.:matched").matching(:matched => /\d+/)
|
data/test/test_misc.rb
CHANGED
@@ -1,30 +1,24 @@
|
|
1
1
|
class TestMisc < MiniTest::Unit::TestCase
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
# assert_equal r1.routes.size, r2.routes.size
|
25
|
-
# assert_equal '/another', r1.url(:test)
|
26
|
-
# assert_equal '/test2', r2.url(:test)
|
27
|
-
# assert_equal :test, r1.routes.first.dest
|
28
|
-
# assert_equal :test, r2.routes.first.dest
|
29
|
-
#end
|
2
|
+
def test_cloning
|
3
|
+
r1 = HttpRouter.new {
|
4
|
+
add('/test').name(:test_route).to :test
|
5
|
+
}
|
6
|
+
r2 = r1.clone
|
7
|
+
|
8
|
+
r2.add('/test2').name(:test).to(:test2)
|
9
|
+
assert_equal 2, r2.routes.size
|
10
|
+
|
11
|
+
assert_equal 404, r1.recognize(Rack::Request.new(Rack::MockRequest.env_for('/test2'))).first
|
12
|
+
assert r2.recognize(Rack::Request.new(Rack::MockRequest.env_for('/test2')))
|
13
|
+
assert_equal r1.routes.first, r1.named_routes[:test_route]
|
14
|
+
assert_equal r2.routes.first, r2.named_routes[:test_route]
|
15
|
+
|
16
|
+
r1.add('/another').name(:test).to(:test2)
|
17
|
+
|
18
|
+
assert_equal r1.routes.size, r2.routes.size
|
19
|
+
assert_equal '/another', r1.url(:test)
|
20
|
+
assert_equal '/test2', r2.url(:test)
|
21
|
+
assert_equal :test, r1.routes.first.dest
|
22
|
+
assert_equal :test, r2.routes.first.dest
|
23
|
+
end
|
30
24
|
end
|
data/test/test_mounting.rb
CHANGED
@@ -1,89 +1,83 @@
|
|
1
1
|
class TestMounting < MiniTest::Unit::TestCase
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
#
|
39
|
-
#def test_nest3
|
40
|
-
# @r3 = HttpRouter.new
|
41
|
-
# @r1.add("/foo(/:bar)").default(:bar => "barry").to(@r2)
|
42
|
-
# @r2.add("/hi").name(:hi).compile
|
43
|
-
# @r2.add("/mounted").to(@r3)
|
44
|
-
# @r3.add("/endpoint").name(:endpoint).compile
|
45
|
-
#
|
46
|
-
# assert_equal "/foo/barry/hi", @r2.url(:hi)
|
47
|
-
# assert_equal "/foo/barry/mounted/endpoint", @r3.url(:endpoint)
|
48
|
-
# assert_equal "/foo/flower/mounted/endpoint", @r3.url(:endpoint, :bar => "flower")
|
49
|
-
#end
|
50
|
-
#
|
51
|
-
#def test_with_default_host
|
52
|
-
# @r1.add("/mounted").default(:host => "example.com").to(@r2)
|
53
|
-
# assert_equal "http://example.com/mounted/bar", @r2.url(:test)
|
54
|
-
#end
|
55
|
-
#
|
56
|
-
#def test_with_host
|
57
|
-
# @r1.add("/mounted").to(@r2)
|
58
|
-
# assert_equal "/mounted/bar", @r2.url(:test)
|
59
|
-
# assert_equal "http://example.com/mounted/bar", @r2.url(:test, :host => "example.com")
|
60
|
-
#end
|
61
|
-
#
|
62
|
-
#def test_with_scheme
|
63
|
-
# @r1.add("/mounted").to(@r2)
|
64
|
-
# assert_equal "/mounted/bar", @r2.url(:test)
|
65
|
-
# assert_equal "https://example.com/mounted/bar", @r2.url(:test, :scheme => "https", :host => "example.com")
|
66
|
-
#end
|
67
|
-
#
|
68
|
-
#def test_clone
|
69
|
-
# @r3 = HttpRouter.new
|
70
|
-
# @r1.add("/first").to(@r2)
|
71
|
-
# @r2.add("/second").to(@r3)
|
72
|
-
# r1 = @r1.clone
|
73
|
-
# assert @r1.routes.first
|
74
|
-
# r2 = r1.routes.first.dest
|
75
|
-
# assert r2
|
76
|
-
# assert_equal @r1.routes.first.dest.object_id, @r2.object_id
|
77
|
-
# assert r2.object_id != @r2.object_id
|
78
|
-
# assert_equal 2, r2.routes.size
|
79
|
-
# r3 = r2.routes.last.dest
|
80
|
-
# assert_instance_of HttpRouter, r3
|
81
|
-
# assert r3.object_id != @r3.object_id
|
82
|
-
#end
|
83
|
-
end
|
2
|
+
def setup
|
3
|
+
@r1 = HttpRouter.new
|
4
|
+
@r2 = HttpRouter.new
|
5
|
+
@r2.add("/bar").name(:test).to{|env| [200, {}, []]}
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_url_mount_for_child_route
|
9
|
+
route = @r1.add("/foo").to(@r2)
|
10
|
+
assert_equal "/foo", @r2.url_mount.url
|
11
|
+
assert_equal "/foo/bar", @r2.url(:test)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_default_values
|
15
|
+
route = @r1.add("/foo/:bar").default(:bar => "baz").to(@r2)
|
16
|
+
assert_equal "/foo/baz/bar", @r2.url(:test)
|
17
|
+
assert_equal "/foo/haha/bar", @r2.url(:test, :bar => "haha")
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_multiple_values
|
21
|
+
@r1.add("/foo/:bar/:baz").default(:bar => "bar").to(@r2)
|
22
|
+
assert_equal "/foo/bar/baz/bar", @r2.url(:test, :baz => "baz")
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_bubble_params
|
26
|
+
route = @r1.add("/foo/:bar").default(:bar => "baz").to(@r2)
|
27
|
+
assert_equal "/foo/baz/bar?bang=ers", @r2.url(:test, :bang => "ers")
|
28
|
+
assert_equal "/foo/haha/bar?bang=ers", @r2.url(:test, :bar => "haha", :bang => "ers")
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_path_with_optional
|
32
|
+
@r1.add("/foo(/:bar)").to(@r2)
|
33
|
+
@r2.add("/hey(/:there)").name(:test).to{|env| [200, {}, []]}
|
34
|
+
assert_equal "/foo/hey", @r2.url(:test)
|
35
|
+
assert_equal "/foo/bar/hey", @r2.url(:test, :bar => "bar")
|
36
|
+
assert_equal "/foo/bar/hey/there", @r2.url(:test, :bar => "bar", :there => "there")
|
37
|
+
end
|
84
38
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
39
|
+
def test_nest3
|
40
|
+
@r3 = HttpRouter.new
|
41
|
+
@r1.add("/foo(/:bar)").default(:bar => "barry").to(@r2)
|
42
|
+
@r2.add("/hi").name(:hi).to{|env| [200, {}, []]}
|
43
|
+
@r2.add("/mounted").to(@r3)
|
44
|
+
@r3.add("/endpoint").name(:endpoint).to{|env| [200, {}, []]}
|
45
|
+
|
46
|
+
assert_equal "/foo/barry/hi", @r2.url(:hi)
|
47
|
+
assert_equal "/foo/barry/mounted/endpoint", @r3.url(:endpoint)
|
48
|
+
assert_equal "/foo/flower/mounted/endpoint", @r3.url(:endpoint, :bar => "flower")
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_with_default_host
|
52
|
+
@r1.add("/mounted").default(:host => "example.com").to(@r2)
|
53
|
+
assert_equal "http://example.com/mounted/bar", @r2.url(:test)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_with_host
|
57
|
+
@r1.add("/mounted").to(@r2)
|
58
|
+
assert_equal "/mounted/bar", @r2.url(:test)
|
59
|
+
assert_equal "http://example.com/mounted/bar", @r2.url(:test, :host => "example.com")
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_with_scheme
|
63
|
+
@r1.add("/mounted").to(@r2)
|
64
|
+
assert_equal "/mounted/bar", @r2.url(:test)
|
65
|
+
assert_equal "https://example.com/mounted/bar", @r2.url(:test, :scheme => "https", :host => "example.com")
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_clone
|
69
|
+
@r3 = HttpRouter.new
|
70
|
+
@r1.add("/first").to(@r2)
|
71
|
+
@r2.add("/second").to(@r3)
|
72
|
+
r1 = @r1.clone
|
73
|
+
assert @r1.routes.first
|
74
|
+
r2 = r1.routes.first.dest
|
75
|
+
assert r2
|
76
|
+
assert_equal @r1.routes.first.dest.object_id, @r2.object_id
|
77
|
+
assert r2.object_id != @r2.object_id
|
78
|
+
assert_equal 2, r2.routes.size
|
79
|
+
r3 = r2.routes.last.dest
|
80
|
+
assert_instance_of HttpRouter, r3
|
81
|
+
assert r3.object_id != @r3.object_id
|
82
|
+
end
|
83
|
+
end
|
data/test/test_recognize.rb
CHANGED
@@ -40,7 +40,7 @@ class TestRecognition < MiniTest::Unit::TestCase
|
|
40
40
|
assert_body '/optional', router.call(Rack::MockRequest.env_for('/test/optional'))
|
41
41
|
assert_body '/', router.call(Rack::MockRequest.env_for('/test'))
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def test_partial_root
|
45
45
|
router.add("/*").to { |env| Rack::Response.new(env['PATH_INFO']).finish }
|
46
46
|
assert_body '/optional', router.call(Rack::MockRequest.env_for('/optional'))
|
data/test/test_request.rb
CHANGED
@@ -83,7 +83,7 @@ class TestRequest < MiniTest::Unit::TestCase
|
|
83
83
|
}
|
84
84
|
assert_route router.add("/test").host('host2'), Rack::MockRequest.env_for('http://host2/test', :method => 'POST')
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
def test_match_on_scheme
|
88
88
|
http, https = router { get("/test").scheme('http'); get("/test").scheme('https') }
|
89
89
|
assert_status 405, Rack::MockRequest.env_for('https://example.org/test', :method => 'POST')
|
data/test/test_variable.rb
CHANGED
@@ -19,7 +19,7 @@ class TestVariable < MiniTest::Unit::TestCase
|
|
19
19
|
assert_route static, '/one'
|
20
20
|
assert_route nil, '/two'
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def test_variable_and_static
|
24
24
|
dynamic, static = router {
|
25
25
|
add("/foo/:id")
|
@@ -83,13 +83,25 @@ class TestVariable < MiniTest::Unit::TestCase
|
|
83
83
|
def test_glob_with_static
|
84
84
|
assert_route '/test/*variable/test', '/test/one/two/three/test', {:variable => ['one', 'two', 'three']}
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
|
+
def test_glob_with_variable
|
88
|
+
assert_route '/test/*variable/:test', '/test/one/two/three', {:variable => ['one', 'two'], :test => 'three'}
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_glob_with_format
|
92
|
+
assert_route '/test/*variable.:format', 'test/one/two/three.html', {:variable => ['one', 'two', 'three'], :format => 'html'}
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_glob_with_literal
|
96
|
+
assert_route '/test/*variable.html', 'test/one/two/three.html', {:variable => ['one', 'two', 'three']}
|
97
|
+
end
|
98
|
+
|
87
99
|
def test_glob_with_regex
|
88
100
|
r = router { add('/test/*variable/anymore')}
|
89
101
|
assert_route r, '/test/123/345/567/anymore', {:variable => ['123', '345', '567']}
|
90
102
|
assert_route nil, '/test/123/345/567'
|
91
103
|
end
|
92
|
-
|
104
|
+
|
93
105
|
def test_regex_and_greedy
|
94
106
|
with_regex, without_regex = router {
|
95
107
|
add("/:common_variable/:matched").matching(:matched => /\d+/)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http_router
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 0.6.
|
9
|
+
- 3
|
10
|
+
version: 0.6.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Joshua Hull
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-03-
|
18
|
+
date: 2011-03-22 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -138,7 +138,7 @@ dependencies:
|
|
138
138
|
version: 1.0.0
|
139
139
|
type: :development
|
140
140
|
version_requirements: *id008
|
141
|
-
description: This library allows you to recognize and build URLs in a Rack application.
|
141
|
+
description: This library allows you to recognize and build URLs in a Rack application.
|
142
142
|
email: joshbuddy@gmail.com
|
143
143
|
executables: []
|
144
144
|
|
@@ -236,6 +236,6 @@ rubyforge_project: http_router
|
|
236
236
|
rubygems_version: 1.3.7
|
237
237
|
signing_key:
|
238
238
|
specification_version: 3
|
239
|
-
summary: A kick-ass HTTP router for use in Rack
|
239
|
+
summary: A kick-ass HTTP router for use in Rack
|
240
240
|
test_files: []
|
241
241
|
|