http_router 0.6.9 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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