http_router 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
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 compatibility.
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
 
@@ -42,6 +42,6 @@ simple_and_dynamic_env = Rack::MockRequest.env_for('/dynamic/anything')
42
42
  report "4 levels, 1 dynamic" do
43
43
  set.url(simple_env, :variable, {:variable => 'onemore'})
44
44
  end
45
-
45
+
46
46
  end
47
47
  end
@@ -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 & Sinatra"
11
- s.description = "This library allows you to recognize and build URLs in a Rack application. As well it contains an interface for use within Sinatra."
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(opts = nil, &blk)
20
+ def initialize(options = nil, &blk)
21
21
  reset!
22
- @ignore_trailing_slash = opts && opts.key?(:ignore_trailing_slash) ? opts[:ignore_trailing_slash] : true
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
- @routes << route
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
@@ -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] = Regex.new(@router, regexp, matching_indicies, priority)
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 << Regex.new(@router, regexp, matching_indicies, priority)
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
- attr_reader :matcher
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, @path, @opts = router, path, opts
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(path), path, [])
8
+ add_non_path_to_tree(@router.root.add_free_match(@original_path), path, [])
9
9
  @compiled = true
10
10
  end
11
11
 
@@ -21,7 +21,7 @@ class HttpRouter
21
21
  def to_s
22
22
  "request path, #{path.inspect}"
23
23
  end
24
-
24
+
25
25
  def clone
26
26
  dup_obj = super
27
27
  dup_obj.path = path.dup
@@ -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
- #mount_point = router.url_mount && router.url_mount.url(options)
141
- #mount_point ? [File.join(mount_point, result), params] : [result, params]
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
- capturing_indicies = []
224
- captures.times {|i| capturing_indicies << i + 1}
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
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  class HttpRouter #:nodoc
3
- VERSION = '0.6.2'
3
+ VERSION = '0.6.3'
4
4
  end
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!
@@ -1,5 +1,5 @@
1
1
  class TestRouteExtensions < MiniTest::Unit::TestCase
2
-
2
+
3
3
  def test_redirect
4
4
  router.get("/index.html").redirect("/")
5
5
  response = router.call(Rack::MockRequest.env_for("/index.html"))
@@ -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'
@@ -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
- #def test_exceptions
3
- # assert_raises(HttpRouter::AmbiguousRouteException) {HttpRouter.new.add("/:var1(/:var2)(/:var3)").compile}
4
- # assert_raises(HttpRouter::AmbiguousVariableException) {HttpRouter.new.add("/:var1(/:var1)(/:var1)").compile}
5
- # assert_raises(HttpRouter::UnsupportedRequestConditionError) {HttpRouter.new.add("/").condition(:flibberty => 'gibet').compile}
6
- #end
7
- #
8
- #def test_cloning
9
- # r1 = HttpRouter.new {
10
- # add('/test').name(:test_route).to :test
11
- # }
12
- # r2 = r1.clone
13
- #
14
- # r2.add('/test2').name(:test).to(:test2)
15
- # assert_equal 2, r2.routes.size
16
- #
17
- # assert r1.recognize(Rack::Request.new(Rack::MockRequest.env_for('/test2'))).nil?
18
- # assert !r2.recognize(Rack::Request.new(Rack::MockRequest.env_for('/test2'))).nil?
19
- # assert_equal r1.routes.first, r1.named_routes[:test_route]
20
- # assert_equal r2.routes.first, r2.named_routes[:test_route]
21
- #
22
- # r1.add('/another').name(:test).to(:test2)
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
@@ -1,89 +1,83 @@
1
1
  class TestMounting < MiniTest::Unit::TestCase
2
- #def setup
3
- # @r1 = HttpRouter.new
4
- # @r2 = HttpRouter.new
5
- # @r2.add("/bar").name(:test).compile
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).compile
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
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
- # it "should clone my nested structure" do
86
- # end
87
- # end
88
- # end
89
- #end
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
@@ -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')
@@ -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: 3
4
+ hash: 1
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 2
10
- version: 0.6.2
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-21 00:00:00 -07:00
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. As well it contains an interface for use within Sinatra.
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 & Sinatra
239
+ summary: A kick-ass HTTP router for use in Rack
240
240
  test_files: []
241
241