http_router 0.6.9 → 0.7.0

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.
@@ -1,6 +1,10 @@
1
- = HTTP Router
1
+ # HTTP Router
2
2
 
3
- == Features
3
+ ## What is it?
4
+
5
+ This is an HTTP router for use in either a web framework, or on it's own using Rack. It takes a set of routes and attempts to find the best match for it. Take a look at the examples directory for how you'd use it in the Rack context.
6
+
7
+ ## Features
4
8
 
5
9
  * Supports variables, and globbing, both named and unnamed.
6
10
  * Regex support for variables.
@@ -10,30 +14,30 @@
10
14
  * Very fast and small code base (~1,000 loc).
11
15
  * Sinatra via https://github.com/joshbuddy/http_router_sinatra
12
16
 
13
- == Usage
17
+ ## Usage
14
18
 
15
19
  Please see the examples directory for a bunch of awesome rackup file examples, with tonnes of commentary. As well, the rdocs should provide a lot of useful specifics and exact usage.
16
20
 
17
- === <tt>HttpRouter.new</tt>
21
+ ### `HttpRouter.new`
18
22
 
19
23
  Takes the following options:
20
24
 
21
- * <tt>:default_app</tt> - The default #call made on non-matches. Defaults to a 404 generator.
22
- * <tt>:ignore_trailing_slash</tt> - Ignores the trailing slash when matching. Defaults to true.
23
- * <tt>:redirect_trailing_slash</tt> - Redirect on trailing slash matches to non-trailing slash paths. Defaults to false.
24
- * <tt>:middleware</tt> - Perform matching without deferring to matched route. Defaults to false.
25
+ * `:default_app` - The default #call made on non-matches. Defaults to a 404 generator.
26
+ * `:ignore_trailing_slash` - Ignores the trailing slash when matching. Defaults to true.
27
+ * `:redirect_trailing_slash` - Redirect on trailing slash matches to non-trailing slash paths. Defaults to false.
28
+ * `:middleware` - Perform matching without deferring to matched route. Defaults to false.
25
29
 
26
- === <tt>#add(name, options)</tt>
30
+ ### `#add(name, options)`
27
31
 
28
32
  Maps a route. The format for variables in paths is:
29
33
  :variable
30
34
  *glob
31
35
 
32
- Everything else is treated literally. Optional parts are surrounded by brackets. Partially matching paths have a trailing <tt>*</tt>. Optional trailing slash matching is done with <tt>/?</tt>.
36
+ Everything else is treated literally. Optional parts are surrounded by brackets. Partially matching paths have a trailing `*`. Optional trailing slash matching is done with `/?`.
33
37
 
34
- As well, you can escape the following characters with a backslash: <tt>( ) : *</tt>
38
+ As well, you can escape the following characters with a backslash: `( ) : *`
35
39
 
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.
40
+ Once you have a route object, use `HttpRouter::Route#to` to add a destination and `HttpRouter::Route#name` to name it.
37
41
 
38
42
  e.g.
39
43
 
@@ -42,22 +46,22 @@ e.g.
42
46
  r.add('/test').redirect("http://www.google.com/")
43
47
  r.add('/static').static('/my_file_system')
44
48
 
45
- As well, you can support regex matching and request conditions. To add a regex match, use <tt>matching(:id => /\d+/)</tt>.
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>.
49
+ As well, you can support regex matching and request conditions. To add a regex match, use `matching(:id => /\d+/)`.
50
+ To match on a request condition you can use `condition(:request_method => %w(POST HEAD))` or more succinctly `request_method('POST', 'HEAD')`.
47
51
 
48
52
  There are convenience methods HttpRouter#get, HttpRouter#post, etc for each request method.
49
53
 
50
- Routes will not be recognized unless <tt>#to</tt> has been called on it.
54
+ Routes will not be recognized unless `#to` has been called on it.
51
55
 
52
- === <tt>#url(name or route, *args)</tt>
56
+ ### `#url(name or route, *args)`
53
57
 
54
58
  Generates a route. The args can either be a hash, a list, or a mix of both.
55
59
 
56
- === <tt>#call(env or Rack::Request)</tt>
60
+ ### `#call(env or Rack::Request)`
57
61
 
58
62
  Recognizes and dispatches the request.
59
63
 
60
- === <tt>#recognize(env or Rack::Request)</tt>
64
+ ### `#recognize(env or Rack::Request)`
61
65
 
62
66
  Only performs recognition.
63
67
 
data/Rakefile CHANGED
@@ -39,7 +39,7 @@ namespace :test do
39
39
  case c
40
40
  when /^\$/
41
41
  out = `#{c[1, c.size]} 2>/dev/null`.split(/\n/)
42
- raise "#{c} produced #{out}" unless $?.success?
42
+ raise "#{c} produced #{`#{c[1, c.size]} 2>&1`}" unless $?.success?
43
43
  when /^=> ?(.*)/
44
44
  c = $1
45
45
  raise "out was nil" if out.nil?
@@ -1,8 +1,8 @@
1
1
  require 'http_router'
2
2
  HttpRouter::Rack.override_rack_builder!
3
3
 
4
- map('/get/:id') { |env|
5
- [200, {'Content-type' => 'text/plain'}, ["My id is #{env['router.params'][:id]}\n"]]
4
+ map('/get/:id', :matching => {:id => /\d+/}) { |env|
5
+ [200, {'Content-type' => 'text/plain'}, ["My id is #{env['router.params'][:id]}, which is a number\n"]]
6
6
  }
7
7
 
8
8
  # you have post, get, head, put and delete.
@@ -10,10 +10,11 @@ post('/get/:id') { |env|
10
10
  [200, {'Content-type' => 'text/plain'}, ["My id is #{env['router.params'][:id]} and you posted!\n"]]
11
11
  }
12
12
 
13
- map('/get/:id', :matching => {:id => /\d+/}) { |env|
14
- [200, {'Content-type' => 'text/plain'}, ["My id is #{env['router.params'][:id]}, which is a number\n"]]
13
+ map('/get/:id') { |env|
14
+ [200, {'Content-type' => 'text/plain'}, ["My id is #{env['router.params'][:id]}\n"]]
15
15
  }
16
16
 
17
+
17
18
  # $ curl http://127.0.0.1:3000/get/foo
18
19
  # => My id is foo
19
20
  # $ curl -X POST http://127.0.0.1:3000/get/foo
data/http_router.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.summary = "A kick-ass HTTP router for use in Rack"
11
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
- s.extra_rdoc_files = ['README.rdoc']
13
+ s.extra_rdoc_files = ['README.md']
14
14
  s.files = `git ls-files`.split("\n")
15
15
  s.homepage = %q{http://github.com/joshbuddy/http_router}
16
16
  s.rdoc_options = ["--charset=UTF-8"]
@@ -2,13 +2,14 @@ class HttpRouter
2
2
  class Node
3
3
  class Arbitrary < Node
4
4
  def initialize(router, allow_partial, blk, param_names)
5
- @router, @allow_partial, @blk, @param_names = router, allow_partial, blk, param_names
5
+ @allow_partial, @blk, @param_names = allow_partial, blk, param_names
6
+ super(router)
6
7
  end
7
8
 
8
9
  def [](request)
9
10
  if request.path.empty? or (request.path.size == 1 and request.path[0] == '') or @allow_partial
10
11
  request = request.clone
11
- request.continue = proc { |state| destination(request) if state }
12
+ request.continue = proc { |state| super(request) if state }
12
13
  params = @param_names.nil? ? {} : Hash[@param_names.zip(request.params)]
13
14
  @blk.call(request, params)
14
15
  end
@@ -0,0 +1,21 @@
1
+ class HttpRouter
2
+ class Node
3
+ class Destination < Node
4
+ def initialize(router, blk, allow_partial)
5
+ @blk, @allow_partial = blk, allow_partial
6
+ super(router)
7
+ end
8
+
9
+ def [](request)
10
+ if request.path.empty? or (request.path.size == 1 and request.path[0] == '') or @allow_partial
11
+ 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
+ end
20
+ end
21
+ end
@@ -3,7 +3,8 @@ class HttpRouter
3
3
  class FreeRegex < Node
4
4
  attr_reader :matcher
5
5
  def initialize(router, matcher)
6
- @router, @matcher = router, matcher
6
+ @matcher = matcher
7
+ super(router)
7
8
  end
8
9
 
9
10
  def [](request)
@@ -11,6 +12,7 @@ class HttpRouter
11
12
  if match = @matcher.match(whole_path) and match[0].size == whole_path.size
12
13
  request = request.clone
13
14
  request.extra_env['router.regex_match'] = match
15
+ request.path = ['']
14
16
  match.names.size.times{|i| request.params << match[i + 1]} if match.respond_to?(:names) && match.names
15
17
  super
16
18
  end
@@ -0,0 +1,21 @@
1
+ class HttpRouter
2
+ class Node
3
+ class Lookup < Node
4
+ def initialize(router)
5
+ @map = {}
6
+ super(router)
7
+ end
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
+ def add(part)
17
+ Node.new(@router, @map[part] ||= [])
18
+ end
19
+ end
20
+ end
21
+ end
@@ -4,8 +4,9 @@ class HttpRouter
4
4
  alias_method :node_lookup, :[]
5
5
  attr_reader :matcher, :splitting_indicies
6
6
 
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
7
+ def initialize(router, matcher, capturing_indicies, splitting_indicies = nil)
8
+ @matcher, @capturing_indicies, @splitting_indicies = matcher, capturing_indicies, splitting_indicies
9
+ super(router)
9
10
  end
10
11
 
11
12
  def [](request)
@@ -3,57 +3,21 @@ class HttpRouter
3
3
  class Request < Node
4
4
  attr_reader :request_method
5
5
 
6
- def initialize(router)
7
- @router, @linear, @catchall, @lookup = router, [], nil, {}
8
- end
9
-
10
- def transform_to(meth)
11
- new_node = Request.new(router)
12
- new_node.request_method = @request_method
13
- new_node.instance_var_set(:@linear, @linear.dup)
14
- new_node.instance_var_set(:@catchall, @catchall)
15
- new_node.instance_var_set(:@lookup, @lookup.dup)
16
- @linear.clear
17
- @lookup.clear
18
- @catchall = new_node
19
- @request_method = meth
20
- new_node
21
- end
22
-
23
- def request_method=(meth)
24
- @request_method = meth == :method ? :request_method : meth
25
- if @destination
26
- next_node = add_catchall
27
- next_node.instance_variable_set(:@destination, @destination)
28
- @destination = nil
29
- end
30
- @request_method
31
- end
32
-
33
- def add_lookup(val)
34
- @router.known_methods << val if @request_method == :request_method
35
- @lookup[val] ||= Request.new(@router)
36
- end
37
-
38
- def add_catchall
39
- @catchall ||= Request.new(@router)
40
- end
41
-
42
- def add_linear(matcher)
43
- next_node = Request.new(@router)
44
- @linear << [matcher, next_node]
45
- next_node
6
+ def initialize(router, opts)
7
+ @opts = opts
8
+ Array(@opts[:request_method]).each { |m| router.known_methods << m } if @opts.key?(:request_method)
9
+ super(router)
46
10
  end
47
11
 
48
12
  def [](request)
49
- if @request_method
50
- val = request.rack_request.send(@request_method.to_sym)
51
- @linear.each { |(matcher, node)| node[request] if matcher === val }
52
- @lookup[val][request] if @lookup.key?(val)
53
- @catchall[request] if @catchall
54
- else
55
- super(request)
56
- end
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)
57
21
  end
58
22
  end
59
23
  end
@@ -2,9 +2,11 @@ class HttpRouter
2
2
  class Node
3
3
  class Variable < Node
4
4
  def [](request)
5
- request = request.clone
6
- request.params << unescape(request.path.shift)
7
- super(request)
5
+ unless request.path.empty?
6
+ request = request.clone
7
+ request.params << unescape(request.path.shift)
8
+ super(request)
9
+ end
8
10
  end
9
11
  end
10
12
  end
@@ -8,145 +8,69 @@ class HttpRouter
8
8
  autoload :FreeRegex, 'http_router/node/free_regex'
9
9
  autoload :Arbitrary, 'http_router/node/arbitrary'
10
10
  autoload :Request, 'http_router/node/request'
11
+ autoload :Lookup, 'http_router/node/lookup'
12
+ autoload :Destination, 'http_router/node/destination'
11
13
 
12
14
  attr_reader :priority, :router
13
15
 
14
- def initialize(router)
15
- @router = router
16
+ def initialize(router, matchers = [])
17
+ @router, @matchers = router, matchers
16
18
  end
17
19
 
18
20
  def [](request)
19
- destination(request, false)
20
- unless request.path.empty?
21
- linear(request)
22
- lookup(request)
23
- variable(request)
24
- glob(request)
25
- end
26
- destination(request)
27
- end
28
-
29
- def linear(request)
30
- @linear && @linear.each{|n| n[request]}
31
- end
32
-
33
- def lookup(request)
34
- if @lookup && @lookup[request.path.first]
35
- request = request.clone
36
- @lookup[request.path.shift][request]
37
- end
38
- end
39
-
40
- def variable(request)
41
- @variable && @variable[request]
42
- end
43
-
44
- def glob(request)
45
- @glob && @glob[request]
46
- end
47
-
48
- def request(request)
49
- @request && @request[request]
50
- end
51
-
52
- def arbitrary(request)
53
- @arbitrary && @arbitrary.each{|n| n[request]}
54
- end
55
-
56
- def unescape(val)
57
- val.to_s.gsub(/((?:%[0-9a-fA-F]{2})+)/n){ [$1.delete('%')].pack('H*') }
58
- end
59
-
60
- def destination(request_obj, match_partially = true)
61
- request(request_obj)
62
- arbitrary(request_obj)
63
- @destination.call(request_obj, match_partially) if @destination
21
+ @matchers.each {|m| m[request] }
22
+ nil
64
23
  end
65
24
 
66
25
  def add_variable
67
- @variable ||= Variable.new(@router)
26
+ add(Variable.new(@router))
68
27
  end
69
28
 
70
29
  def add_glob
71
- @glob ||= Glob.new(@router)
30
+ add(Glob.new(@router))
72
31
  end
73
32
 
74
33
  def add_request(opts)
75
- @request ||= Request.new(@router)
76
- next_requests = [@request]
77
- @router.request_methods.each_with_index do |method, method_index|
78
- next_requests.map! do |next_request|
79
- if opts[method].nil? && next_request.request_method.nil?
80
- next_request
81
- else
82
- next_request_index = next_request.request_method && @router.request_methods.index(next_request.request_method)
83
- rank = next_request_index ? method_index <=> next_request_index : 0
84
- case rank
85
- when 0
86
- next_request.request_method = method
87
- (opts[method].nil? ? [nil] : Array(opts[method])).map do |request_matcher|
88
- case request_matcher
89
- when nil then next_request.add_catchall
90
- when String then next_request.add_lookup(request_matcher)
91
- when Regexp then next_request.add_linear(request_matcher)
92
- end
93
- end
94
- when -1 then next_request
95
- when 1 then next_request.transform_to(method)
96
- end
97
- end
98
- end
99
- next_requests.flatten!
100
- end
101
- next_requests
34
+ add(Request.new(@router, opts))
102
35
  end
103
36
 
104
37
  def add_arbitrary(blk, allow_partial, param_names)
105
- @arbitrary ||= []
106
- @arbitrary << Arbitrary.new(@router, allow_partial, blk, param_names)
107
- @arbitrary.last
38
+ add(Arbitrary.new(@router, allow_partial, blk, param_names))
108
39
  end
109
40
 
110
- def add_match(regexp, matching_indicies = [0], priority = 0, splitting_indicies = nil)
111
- add_prioritized_match(Regex.new(@router, regexp, matching_indicies, priority, splitting_indicies))
41
+ def add_match(regexp, matching_indicies = [0], splitting_indicies = nil)
42
+ add(Regex.new(@router, regexp, matching_indicies, splitting_indicies))
112
43
  end
113
44
 
114
- def add_spanning_match(regexp, matching_indicies = [0], priority = 0, splitting_indicies = nil)
115
- add_prioritized_match(SpanningRegex.new(@router, regexp, matching_indicies, priority, splitting_indicies))
45
+ def add_spanning_match(regexp, matching_indicies = [0], splitting_indicies = nil)
46
+ add(SpanningRegex.new(@router, regexp, matching_indicies, splitting_indicies))
116
47
  end
117
48
 
118
49
  def add_free_match(regexp)
119
- @linear ||= []
120
- @linear << FreeRegex.new(@router, regexp)
121
- @linear.last
50
+ add(FreeRegex.new(@router, regexp))
122
51
  end
123
52
 
124
- def add_destination(&dest)
125
- @destination = dest
53
+ def add_destination(blk, partial)
54
+ add(Destination.new(@router, blk, partial))
126
55
  end
127
56
 
128
57
  def add_lookup(part)
129
- @lookup ||= {}
130
- @lookup[part] ||= Node.new(@router)
58
+ add(Lookup.new(@router)) unless @matchers.last.is_a?(Lookup)
59
+ @matchers.last.add(part)
131
60
  end
132
61
 
133
- def join_whole_path(request)
134
- request.path * '/'
62
+ private
63
+ def add(matcher)
64
+ @matchers << matcher
65
+ @matchers.last
135
66
  end
136
67
 
137
- private
138
- def add_prioritized_match(match)
139
- @linear ||= []
140
- if match.priority != 0
141
- @linear.each_with_index { |n, i|
142
- if match.priority > (n.priority || 0)
143
- @linear[i, 0] = match
144
- return @linear[i]
145
- end
146
- }
147
- end
148
- @linear << match
149
- @linear.last
68
+ def unescape(val)
69
+ val.to_s.gsub(/((?:%[0-9a-fA-F]{2})+)/n){ [$1.delete('%')].pack('H*') }
70
+ end
71
+
72
+ def join_whole_path(request)
73
+ request.path * '/'
150
74
  end
151
75
  end
152
76
  end
@@ -15,7 +15,7 @@ class HttpRouter
15
15
  add_to_current_set(@chars.shift)
16
16
  end
17
17
  end
18
- @paths
18
+ @paths.reverse!
19
19
  end
20
20
 
21
21
  private
@@ -167,7 +167,7 @@ class HttpRouter
167
167
  path.param_names.size == var_count
168
168
  }
169
169
  else
170
- @paths.reverse_each do |path|
170
+ @paths.each do |path|
171
171
  if params && !params.empty?
172
172
  return path if (path.param_names & params.keys).size == path.param_names.size
173
173
  elsif path.param_names.empty?
@@ -216,7 +216,6 @@ class HttpRouter
216
216
  capturing_indicies = []
217
217
  splitting_indicies = []
218
218
  captures = 0
219
- priority = 0
220
219
  spans = false
221
220
  regex = parts.inject('') do |reg, part|
222
221
  reg << case part[0]
@@ -238,12 +237,11 @@ class HttpRouter
238
237
  matches_with[name] = @opts[name]
239
238
  "(#{(@opts[name] || '.*?')})"
240
239
  else
241
- priority += part.size
242
240
  Regexp.quote(URI.encode(part))
243
241
  end
244
242
  end
245
- node = spans ? node.add_spanning_match(Regexp.new("#{regex}$"), capturing_indicies, priority, splitting_indicies) :
246
- node.add_match(Regexp.new("#{regex}$"), capturing_indicies, priority, splitting_indicies)
243
+ node = spans ? node.add_spanning_match(Regexp.new("#{regex}$"), capturing_indicies, splitting_indicies) :
244
+ node.add_match(Regexp.new("#{regex}$"), capturing_indicies, splitting_indicies)
247
245
  end
248
246
  end
249
247
  add_non_path_to_tree(node, path, param_names)
@@ -274,9 +272,9 @@ class HttpRouter
274
272
  end
275
273
  end
276
274
  }
277
- nodes = @conditions && !@conditions.empty? ? node.add_request(@conditions) : [node]
278
- @arbitrary.each{|a| nodes.map!{|n| n.add_arbitrary(a, match_partially?, names)} } if @arbitrary
279
- nodes.map!{|n| n.add_destination(&destination)}
275
+ node = node.add_request(@conditions) if @conditions && !@conditions.empty?
276
+ @arbitrary.each{|a| node = node.add_arbitrary(a, match_partially?, names)} if @arbitrary
277
+ node.add_destination(destination, @match_partially)
280
278
  if dest.respond_to?(:url_mount=)
281
279
  urlmount = UrlMount.new(@original_path, @default_values)
282
280
  urlmount.url_mount = router.url_mount if router.url_mount
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  class HttpRouter #:nodoc
3
- VERSION = '0.6.9'
3
+ VERSION = '0.7.0'
4
4
  end
@@ -9,11 +9,11 @@ class TestArbitrary < MiniTest::Unit::TestCase
9
9
  end
10
10
 
11
11
  def test_less_specific_node
12
- general, hello, love80, love8080 = router {
13
- add("/test")
12
+ hello, love80, love8080, general = router {
14
13
  add("/test").arbitrary(Proc.new{|req, params| req.rack.host == 'hellodooly' })
15
14
  add("/test").arbitrary(Proc.new{|req, params| req.rack.host == 'lovelove' }).arbitrary{|req, params| req.rack.port == 80}
16
15
  add("/test").arbitrary(Proc.new{|req, params| req.rack.host == 'lovelove' }).arbitrary{|req, params| req.rack.port == 8080}
16
+ add("/test")
17
17
  }
18
18
  assert_route general, 'http://lovelove:8081/test'
19
19
  assert_route hello, 'http://hellodooly:8081/test'
@@ -20,13 +20,13 @@ class TestInterstitial < MiniTest::Unit::TestCase
20
20
  end
21
21
 
22
22
  def test_multi
23
- r1, r2, r3, r4, r5, r6 = router {
24
- add('/:var1')
25
- add('/:var1-:var2')
26
- add('/:var1-:var2-:var3')
27
- add('/:var1-:var2-:var3-:var4')
28
- add('/:var1-:var2-:var3-:var4-:var5')
23
+ r6, r5, r4, r3, r2, r1 = router {
29
24
  add('/:var1-:var2-:var3-:var4-:var5-:var6')
25
+ add('/:var1-:var2-:var3-:var4-:var5')
26
+ add('/:var1-:var2-:var3-:var4')
27
+ add('/:var1-:var2-:var3')
28
+ add('/:var1-:var2')
29
+ add('/:var1')
30
30
  }
31
31
  assert_route r1, '/one', {:var1 => 'one'}
32
32
  assert_route r2, '/one-value', {:var1 => 'one', :var2 => 'value'}
@@ -12,6 +12,14 @@ class TestRecognition < MiniTest::Unit::TestCase
12
12
  assert_route router.add('/.html'), '/.html'
13
13
  end
14
14
 
15
+ def test_passing
16
+ passed, working = router {
17
+ add('/').to { |env| throw :pass; [200, {}, ['pass']] }
18
+ add('/').to { |env| [200, {}, ['working']] }
19
+ }
20
+ assert_body 'working', router.call(Rack::MockRequest.env_for('/'))
21
+ end
22
+
15
23
  def test_optional
16
24
  route = router {
17
25
  add 'one(/two(/three(/four)(/five)))'
data/test/test_request.rb CHANGED
@@ -47,20 +47,20 @@ class TestRequest < MiniTest::Unit::TestCase
47
47
  end
48
48
 
49
49
  def test_move_node
50
- general, post = router {
51
- add("/test").default_destination
50
+ post, general = router {
52
51
  post("/test").default_destination
52
+ add("/test").default_destination
53
53
  }
54
54
  assert_route post, Rack::MockRequest.env_for('/test', :method => 'POST')
55
55
  assert_route general, Rack::MockRequest.env_for('/test', :method => 'PUT')
56
56
  end
57
57
 
58
58
  def test_complex_routing
59
- host2, post, host2_get, host2_post = router {
59
+ host2_post, host2_get, host2, post = router {
60
+ add("/test").post.host('host2')
61
+ add("/test").host('host2').get
60
62
  add("/test").host('host2')
61
63
  add("/test").post
62
- add("/test").host('host2').get
63
- add("/test").post.host('host2')
64
64
  }
65
65
  assert_route host2, Rack::MockRequest.env_for('http://host2/test', :method => 'PUT')
66
66
  assert_route post, Rack::MockRequest.env_for('http://host1/test', :method => 'POST')
@@ -5,7 +5,7 @@ class TestVariable < MiniTest::Unit::TestCase
5
5
  end
6
6
 
7
7
  def test_variable_vs_static
8
- dynamic, static = router { add ':one'; add 'one' }
8
+ static, dynamic = router { add 'one'; add ':one' }
9
9
  assert_route dynamic, '/two', {:one => 'two'}
10
10
  assert_route static, '/one'
11
11
  end
@@ -107,10 +107,10 @@ class TestVariable < MiniTest::Unit::TestCase
107
107
  end
108
108
 
109
109
  def test_regex_and_greedy
110
- with_regex, without_regex, with_post = router {
110
+ with_regex, with_post, without_regex = router {
111
111
  add("/:common_variable/:matched").matching(:matched => /\d+/)
112
- add("/:common_variable/:unmatched")
113
112
  post("/:common_variable/:unmatched")
113
+ add("/:common_variable/:unmatched")
114
114
  }
115
115
  assert_route with_regex, '/common/123', {:common_variable => 'common', :matched => '123'}
116
116
  assert_route without_regex, '/common/other', {:common_variable => 'common', :unmatched => 'other'}
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: 21
5
- prerelease: false
4
+ hash: 3
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
- - 6
9
- - 9
10
- version: 0.6.9
8
+ - 7
9
+ - 0
10
+ version: 0.7.0
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-04-07 00:00:00 -07:00
18
+ date: 2011-04-18 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -161,13 +161,13 @@ executables: []
161
161
  extensions: []
162
162
 
163
163
  extra_rdoc_files:
164
- - README.rdoc
164
+ - README.md
165
165
  files:
166
166
  - .gitignore
167
167
  - .rspec
168
168
  - CHANGELOG
169
169
  - Gemfile
170
- - README.rdoc
170
+ - README.md
171
171
  - Rakefile
172
172
  - benchmarks/gen2.rb
173
173
  - benchmarks/generation_bm.rb
@@ -189,9 +189,11 @@ files:
189
189
  - lib/http_router.rb
190
190
  - lib/http_router/node.rb
191
191
  - lib/http_router/node/arbitrary.rb
192
+ - lib/http_router/node/destination.rb
192
193
  - lib/http_router/node/free_regex.rb
193
194
  - lib/http_router/node/glob.rb
194
195
  - lib/http_router/node/glob_regex.rb
196
+ - lib/http_router/node/lookup.rb
195
197
  - lib/http_router/node/regex.rb
196
198
  - lib/http_router/node/request.rb
197
199
  - lib/http_router/node/spanning_regex.rb
@@ -250,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
250
252
  requirements: []
251
253
 
252
254
  rubyforge_project: http_router
253
- rubygems_version: 1.3.7
255
+ rubygems_version: 1.6.2
254
256
  signing_key:
255
257
  specification_version: 3
256
258
  summary: A kick-ass HTTP router for use in Rack