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.
- data/{README.rdoc → README.md} +22 -18
- data/Rakefile +1 -1
- data/examples/rack_mapper.ru +5 -4
- data/http_router.gemspec +1 -1
- data/lib/http_router/node/arbitrary.rb +3 -2
- data/lib/http_router/node/destination.rb +21 -0
- data/lib/http_router/node/free_regex.rb +3 -1
- data/lib/http_router/node/lookup.rb +21 -0
- data/lib/http_router/node/regex.rb +3 -2
- data/lib/http_router/node/request.rb +12 -48
- data/lib/http_router/node/variable.rb +5 -3
- data/lib/http_router/node.rb +29 -105
- data/lib/http_router/optional_compiler.rb +1 -1
- data/lib/http_router/route.rb +6 -8
- data/lib/http_router/version.rb +1 -1
- data/test/test_arbitrary.rb +2 -2
- data/test/test_interstitial.rb +6 -6
- data/test/test_recognize.rb +8 -0
- data/test/test_request.rb +5 -5
- data/test/test_variable.rb +3 -3
- metadata +11 -9
data/{README.rdoc → README.md}
RENAMED
@@ -1,6 +1,10 @@
|
|
1
|
-
|
1
|
+
# HTTP Router
|
2
2
|
|
3
|
-
|
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
|
-
|
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
|
-
|
21
|
+
### `HttpRouter.new`
|
18
22
|
|
19
23
|
Takes the following options:
|
20
24
|
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
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
|
-
|
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
|
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:
|
38
|
+
As well, you can escape the following characters with a backslash: `( ) : *`
|
35
39
|
|
36
|
-
Once you have a route object, use
|
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
|
46
|
-
To match on a request condition you can use
|
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
|
54
|
+
Routes will not be recognized unless `#to` has been called on it.
|
51
55
|
|
52
|
-
|
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
|
-
|
60
|
+
### `#call(env or Rack::Request)`
|
57
61
|
|
58
62
|
Recognizes and dispatches the request.
|
59
63
|
|
60
|
-
|
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 #{
|
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?
|
data/examples/rack_mapper.ru
CHANGED
@@ -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'
|
14
|
-
[200, {'Content-type' => 'text/plain'}, ["My id is #{env['router.params'][:id]}
|
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.
|
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
|
-
@
|
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|
|
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
|
-
@
|
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,
|
8
|
-
@
|
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
|
-
@
|
8
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
6
|
-
|
7
|
-
|
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
|
data/lib/http_router/node.rb
CHANGED
@@ -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
|
-
|
20
|
-
|
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
|
-
|
26
|
+
add(Variable.new(@router))
|
68
27
|
end
|
69
28
|
|
70
29
|
def add_glob
|
71
|
-
|
30
|
+
add(Glob.new(@router))
|
72
31
|
end
|
73
32
|
|
74
33
|
def add_request(opts)
|
75
|
-
|
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
|
-
@
|
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],
|
111
|
-
|
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],
|
115
|
-
|
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
|
-
@
|
120
|
-
@linear << FreeRegex.new(@router, regexp)
|
121
|
-
@linear.last
|
50
|
+
add(FreeRegex.new(@router, regexp))
|
122
51
|
end
|
123
52
|
|
124
|
-
def add_destination(
|
125
|
-
@
|
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
|
-
@
|
130
|
-
@
|
58
|
+
add(Lookup.new(@router)) unless @matchers.last.is_a?(Lookup)
|
59
|
+
@matchers.last.add(part)
|
131
60
|
end
|
132
61
|
|
133
|
-
|
134
|
-
|
62
|
+
private
|
63
|
+
def add(matcher)
|
64
|
+
@matchers << matcher
|
65
|
+
@matchers.last
|
135
66
|
end
|
136
67
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
data/lib/http_router/route.rb
CHANGED
@@ -167,7 +167,7 @@ class HttpRouter
|
|
167
167
|
path.param_names.size == var_count
|
168
168
|
}
|
169
169
|
else
|
170
|
-
@paths.
|
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,
|
246
|
-
node.add_match(Regexp.new("#{regex}$"), capturing_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
|
-
|
278
|
-
@arbitrary.each{|a|
|
279
|
-
|
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
|
data/lib/http_router/version.rb
CHANGED
data/test/test_arbitrary.rb
CHANGED
@@ -9,11 +9,11 @@ class TestArbitrary < MiniTest::Unit::TestCase
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def test_less_specific_node
|
12
|
-
|
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'
|
data/test/test_interstitial.rb
CHANGED
@@ -20,13 +20,13 @@ class TestInterstitial < MiniTest::Unit::TestCase
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_multi
|
23
|
-
|
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'}
|
data/test/test_recognize.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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')
|
data/test/test_variable.rb
CHANGED
@@ -5,7 +5,7 @@ class TestVariable < MiniTest::Unit::TestCase
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def test_variable_vs_static
|
8
|
-
|
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,
|
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:
|
5
|
-
prerelease:
|
4
|
+
hash: 3
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
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-
|
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.
|
164
|
+
- README.md
|
165
165
|
files:
|
166
166
|
- .gitignore
|
167
167
|
- .rspec
|
168
168
|
- CHANGELOG
|
169
169
|
- Gemfile
|
170
|
-
- README.
|
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.
|
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
|