http_router 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +13 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +21 -5
- data/Rakefile +10 -0
- data/Tumbler +4 -0
- data/examples/static/config.ru +26 -0
- data/examples/static/favicon.ico +0 -0
- data/examples/static/images/cat1.jpg +0 -0
- data/examples/static/images/cat2.jpg +0 -0
- data/examples/static/images/cat3.jpg +0 -0
- data/http_router.gemspec +9 -10
- data/lib/ext/rack/rack_urlmap.rb +10 -0
- data/lib/http_router.rb +16 -3
- data/lib/http_router/node.rb +15 -12
- data/lib/http_router/response.rb +3 -3
- data/lib/http_router/root.rb +10 -4
- data/lib/http_router/route.rb +8 -5
- data/lib/http_router/version.rb +4 -0
- data/spec/rack/dispatch_spec.rb +8 -0
- data/spec/rack/urlmap_spec.rb +13 -0
- data/spec/recognize_spec.rb +35 -1
- metadata +98 -16
- data/VERSION +0 -1
data/CHANGELOG
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
== 0.2.5
|
2
|
+
|
3
|
+
* Walk entire tree looking for possible request_methods to return on 405 if a match isn't achieved. (Joshua Hull, 3e8631f)
|
4
|
+
* Upgraded deps + spec running (Joshua Hull, fcefce9)
|
5
|
+
* Simplified route cloning (Joshua Hull, 4b0ff59)
|
6
|
+
* Added partial matching to route cloning (Joshua Hull, d1a57d8)
|
7
|
+
* Merge branch 'master' of github.com:joshbuddy/http_router (Joshua Hull, 7f42a27)
|
8
|
+
* Convert to Tumbler (Joshua Hull, 295e6a2)
|
9
|
+
* Updates cloning (Daniel Neighman, 37178bf)
|
10
|
+
* Add Rack::urlmap replacement (Joshua Hull, 2868044)
|
11
|
+
* Added scheme example (Joshua Hull, f23da20)
|
12
|
+
* Added static example (Joshua Hull, df54ee0)
|
13
|
+
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
---
|
2
2
|
dependencies:
|
3
|
+
url_mount:
|
4
|
+
group:
|
5
|
+
- :default
|
6
|
+
version: ">= 0.2.1"
|
3
7
|
rake:
|
4
8
|
group:
|
5
9
|
- :development
|
6
10
|
version: ">= 0"
|
7
|
-
|
11
|
+
tumbler:
|
8
12
|
group:
|
9
|
-
- :
|
10
|
-
version: ">= 0.
|
13
|
+
- :development
|
14
|
+
version: ">= 0.0.11"
|
11
15
|
rspec:
|
12
16
|
group:
|
13
17
|
- :development
|
@@ -27,17 +31,29 @@ dependencies:
|
|
27
31
|
specs:
|
28
32
|
- rake:
|
29
33
|
version: 0.8.7
|
34
|
+
- blockenspiel:
|
35
|
+
version: 0.3.3
|
36
|
+
- bundler:
|
37
|
+
version: 0.9.26
|
38
|
+
- callsite:
|
39
|
+
version: 0.0.2
|
40
|
+
- json:
|
41
|
+
version: 1.4.3
|
30
42
|
- rack:
|
31
|
-
version: 1.1
|
43
|
+
version: 1.2.1
|
32
44
|
- rbench:
|
33
45
|
version: 0.2.3
|
34
46
|
- rspec:
|
35
47
|
version: 1.3.0
|
36
48
|
- sinatra:
|
37
49
|
version: "1.0"
|
50
|
+
- versionomy:
|
51
|
+
version: 0.4.0
|
52
|
+
- tumbler:
|
53
|
+
version: 0.0.11
|
38
54
|
- url_mount:
|
39
55
|
version: 0.2.1
|
40
|
-
hash:
|
56
|
+
hash: df813dada9b96e269c9f2dc81627e29f1dcec5f4
|
41
57
|
sources:
|
42
58
|
- Rubygems:
|
43
59
|
uri: http://gemcutter.org
|
data/Rakefile
CHANGED
@@ -7,6 +7,10 @@ Spec::Rake::SpecTask.new(:spec) do |t|
|
|
7
7
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
8
8
|
end
|
9
9
|
|
10
|
+
task 'tumbler:preflight' do
|
11
|
+
Rake::Task["spec"].invoke
|
12
|
+
end
|
13
|
+
|
10
14
|
begin
|
11
15
|
require 'code_stats'
|
12
16
|
CodeStats::Tasks.new
|
@@ -20,3 +24,9 @@ Rake::RDocTask.new do |rd|
|
|
20
24
|
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
21
25
|
rd.rdoc_dir = 'rdoc'
|
22
26
|
end
|
27
|
+
|
28
|
+
|
29
|
+
# automatically added Tumbler tasks
|
30
|
+
|
31
|
+
require 'tumbler'
|
32
|
+
Tumbler.use_rake_tasks
|
data/Tumbler
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# static serving example
|
2
|
+
|
3
|
+
require 'http_router'
|
4
|
+
|
5
|
+
base = File.expand_path(File.dirname(__FILE__))
|
6
|
+
|
7
|
+
run HttpRouter.new {
|
8
|
+
get('/favicon.ico').static("#{base}/favicon.ico") # from a single file
|
9
|
+
get('/images').static("#{base}/images") # or from a directory
|
10
|
+
}
|
11
|
+
|
12
|
+
# crapbook-pro:~ joshua$ curl -I http://localhost:3000/favicon.ico
|
13
|
+
# HTTP/1.1 200 OK
|
14
|
+
# Last-Modified: Fri, 11 Jun 2010 21:02:22 GMT
|
15
|
+
# Content-Type: image/vnd.microsoft.icon
|
16
|
+
# Content-Length: 1150
|
17
|
+
# Connection: keep-alive
|
18
|
+
# Server: thin 1.2.7 codename No Hup
|
19
|
+
#
|
20
|
+
# crapbook-pro:~ joshua$ curl -I http://localhost:3000/images/cat1.jpg
|
21
|
+
# HTTP/1.1 200 OK
|
22
|
+
# Last-Modified: Fri, 11 Jun 2010 21:54:16 GMT
|
23
|
+
# Content-Type: image/jpeg
|
24
|
+
# Content-Length: 29817
|
25
|
+
# Connection: keep-alive
|
26
|
+
# Server: thin 1.2.7 codename No Hup
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/http_router.gemspec
CHANGED
@@ -1,28 +1,27 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
+
require 'tumbler/gemspec'
|
4
|
+
|
3
5
|
Gem::Specification.new do |s|
|
4
|
-
s.name =
|
5
|
-
s.version =
|
6
|
+
s.name = Tumbler::Gemspec.name
|
7
|
+
s.version = Tumbler::Gemspec.version
|
6
8
|
|
7
9
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
10
|
s.authors = ["Joshua Hull"]
|
9
|
-
s.date =
|
11
|
+
s.date = Tumbler::Gemspec.date
|
10
12
|
s.description = %q{A kick-ass HTTP router for use in Rack & Sinatra}
|
11
13
|
s.email = %q{joshbuddy@gmail.com}
|
12
|
-
s.extra_rdoc_files =
|
13
|
-
|
14
|
-
]
|
15
|
-
s.files = `git ls-files`.split("\n")
|
14
|
+
s.extra_rdoc_files = Tumbler::Gemspec.files('README.rdoc')
|
15
|
+
s.files = Tumbler::Gemspec.files
|
16
16
|
s.homepage = %q{http://github.com/joshbuddy/http_router}
|
17
17
|
s.rdoc_options = ["--charset=UTF-8"]
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
s.rubygems_version = %q{1.3.7}
|
20
20
|
s.summary = %q{A kick-ass HTTP router for use in Rack & Sinatra}
|
21
|
-
s.test_files =
|
21
|
+
s.test_files = Tumbler::Gemspec.files(/^spec/)
|
22
22
|
|
23
23
|
# dependencies
|
24
|
-
s
|
25
|
-
s.add_dependency "url_mount", ">=0.2"
|
24
|
+
Tumbler::Gemspec.inject_dependencies(s)
|
26
25
|
|
27
26
|
if s.respond_to? :specification_version then
|
28
27
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Rack::URLMap
|
2
|
+
def initialize(map = {})
|
3
|
+
@router = HttpRouter.new
|
4
|
+
map.each { |path, app| (path =~ /^(https?):\/\/(.*?)(\/.*)/ ? @router.add($3).host($2).scheme($1) : @router.add(path)).partial.to(app) }
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
@router.call(env)
|
9
|
+
end
|
10
|
+
end
|
data/lib/http_router.rb
CHANGED
@@ -12,6 +12,7 @@ require 'http_router/response'
|
|
12
12
|
require 'http_router/path'
|
13
13
|
require 'http_router/optional_compiler'
|
14
14
|
require 'http_router/parts'
|
15
|
+
require 'http_router/version'
|
15
16
|
|
16
17
|
class HttpRouter
|
17
18
|
# Raised when a Route is not able to be generated.
|
@@ -40,6 +41,12 @@ class HttpRouter
|
|
40
41
|
require File.join('ext', 'rack', 'rack_mapper')
|
41
42
|
end
|
42
43
|
|
44
|
+
# Monkey-patches Rack::Builder to use HttpRouter.
|
45
|
+
# See examples/rack_mapper.rb
|
46
|
+
def self.override_rack_urlmap!
|
47
|
+
require File.join('ext', 'rack', 'rack_urlmap')
|
48
|
+
end
|
49
|
+
|
43
50
|
# Creates a new HttpRouter.
|
44
51
|
# Can be called with either <tt>HttpRouter.new(proc{|env| ... }, { .. options .. })</tt> or with the first argument omitted.
|
45
52
|
# If there is a proc first, then it's used as the default app in the case of a non-match.
|
@@ -104,7 +111,7 @@ class HttpRouter
|
|
104
111
|
#
|
105
112
|
# Returns the route object.
|
106
113
|
def add(path, options = nil)
|
107
|
-
add_route
|
114
|
+
add_route route(path.dup).with_options(options)
|
108
115
|
end
|
109
116
|
|
110
117
|
# Adds a route to be recognized. This must be a HttpRouter::Route object. Returns the route just added.
|
@@ -191,6 +198,7 @@ class HttpRouter
|
|
191
198
|
elsif !response.matched?
|
192
199
|
return [response.status, response.headers, []]
|
193
200
|
end
|
201
|
+
process_params(env, response)
|
194
202
|
end
|
195
203
|
env['router.response'] = response
|
196
204
|
@default_app.call(env)
|
@@ -221,9 +229,14 @@ class HttpRouter
|
|
221
229
|
Glob.new(self, *args)
|
222
230
|
end
|
223
231
|
|
232
|
+
# Returns a new glob
|
233
|
+
def route(*args)
|
234
|
+
Route.new(self, *args)
|
235
|
+
end
|
236
|
+
|
224
237
|
# Creates a deep-copy of the router.
|
225
|
-
def clone
|
226
|
-
cloned_router =
|
238
|
+
def clone(klass = self.class)
|
239
|
+
cloned_router = klass.new(@default_app, @options)
|
227
240
|
@routes.each do |route|
|
228
241
|
new_route = route.clone(cloned_router)
|
229
242
|
cloned_router.add_route(new_route).compile
|
data/lib/http_router/node.rb
CHANGED
@@ -137,10 +137,10 @@ class HttpRouter
|
|
137
137
|
current_nodes
|
138
138
|
end
|
139
139
|
|
140
|
-
def find_on_parts(request, parts, params)
|
140
|
+
def find_on_parts(request, parts, params, alternate_request_methods)
|
141
141
|
if parts and !parts.empty?
|
142
142
|
if parts.size == 1 and parts.first == ''
|
143
|
-
potential_match = find_on_parts(request, [], params)
|
143
|
+
potential_match = find_on_parts(request, [], params, alternate_request_methods)
|
144
144
|
if potential_match and (router.ignore_trailing_slash? or potential_match.value && potential_match.value.route.trailing_slash_ignore?)
|
145
145
|
parts.shift
|
146
146
|
return potential_match
|
@@ -153,10 +153,10 @@ class HttpRouter
|
|
153
153
|
if tester.respond_to?(:matches?) and match = tester.matches?(parts)
|
154
154
|
dupped_parts = parts.dup
|
155
155
|
params << tester.consume(match, dupped_parts)
|
156
|
-
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params)
|
156
|
+
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params, alternate_request_methods)
|
157
157
|
elsif tester.respond_to?(:match) and match = tester.match(parts.whole_path) and match.begin(0) == 0
|
158
158
|
dupped_parts = router.split(parts.whole_path[match[0].size, parts.whole_path.size])
|
159
|
-
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params)
|
159
|
+
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params, alternate_request_methods)
|
160
160
|
else
|
161
161
|
nil
|
162
162
|
end
|
@@ -165,14 +165,14 @@ class HttpRouter
|
|
165
165
|
end
|
166
166
|
if match = @lookup && @lookup[parts.first]
|
167
167
|
parts.shift
|
168
|
-
return match.find_on_parts(request, parts, params)
|
168
|
+
return match.find_on_parts(request, parts, params, alternate_request_methods)
|
169
169
|
elsif @catchall
|
170
170
|
params << @catchall.variable.consume(nil, parts)
|
171
|
-
return @catchall.find_on_parts(request, parts, params)
|
171
|
+
return @catchall.find_on_parts(request, parts, params, alternate_request_methods)
|
172
172
|
end
|
173
173
|
end
|
174
174
|
if request_node
|
175
|
-
request_node.find_on_request_methods(request)
|
175
|
+
request_node.find_on_request_methods(request, alternate_request_methods)
|
176
176
|
elsif arbitrary_node
|
177
177
|
arbitrary_node.find_on_arbitrary(request)
|
178
178
|
elsif @value
|
@@ -207,19 +207,19 @@ class HttpRouter
|
|
207
207
|
RequestMethods = [:request_method, :host, :port, :scheme]
|
208
208
|
attr_accessor :request_method
|
209
209
|
|
210
|
-
def find_on_request_methods(request)
|
210
|
+
def find_on_request_methods(request, alternate_request_methods)
|
211
211
|
if @request_method
|
212
212
|
request_value = request.send(request_method)
|
213
213
|
if @linear && !@linear.empty?
|
214
214
|
next_node = @linear.find do |(regexp, node)|
|
215
215
|
regexp === request_value
|
216
216
|
end
|
217
|
-
next_node &&= next_node.find_on_request_methods(request)
|
217
|
+
next_node &&= next_node.find_on_request_methods(request, alternate_request_methods)
|
218
218
|
return next_node if next_node
|
219
219
|
end
|
220
|
-
if @lookup and next_node = (@lookup[request_value] && @lookup[request_value].find_on_request_methods(request))
|
220
|
+
if @lookup and next_node = (@lookup[request_value] && @lookup[request_value].find_on_request_methods(request, alternate_request_methods))
|
221
221
|
return next_node
|
222
|
-
elsif next_node = (@catchall && @catchall.find_on_request_methods(request))
|
222
|
+
elsif next_node = (@catchall && @catchall.find_on_request_methods(request, alternate_request_methods))
|
223
223
|
return next_node
|
224
224
|
end
|
225
225
|
end
|
@@ -229,7 +229,10 @@ class HttpRouter
|
|
229
229
|
elsif @value
|
230
230
|
self
|
231
231
|
else
|
232
|
-
|
232
|
+
if request_method == :request_method
|
233
|
+
alternate_request_methods.concat(@lookup.keys)
|
234
|
+
end
|
235
|
+
nil
|
233
236
|
end
|
234
237
|
end
|
235
238
|
|
data/lib/http_router/response.rb
CHANGED
@@ -31,14 +31,14 @@ class HttpRouter
|
|
31
31
|
def route
|
32
32
|
path.route
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def dest
|
36
36
|
route.dest
|
37
37
|
end
|
38
38
|
alias_method :destination, :dest
|
39
|
-
|
39
|
+
|
40
40
|
def partial_match?
|
41
|
-
remaining_path
|
41
|
+
remaining_path || route.partially_match?
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
data/lib/http_router/root.rb
CHANGED
@@ -10,16 +10,18 @@ class HttpRouter
|
|
10
10
|
parts = router.split(path)
|
11
11
|
parts << '' if path[path.size - 1] == ?/
|
12
12
|
params = []
|
13
|
+
alternate_request_methods = []
|
13
14
|
process_response(
|
14
|
-
find_on_parts(request, parts, params),
|
15
|
+
find_on_parts(request, parts, params, alternate_request_methods),
|
15
16
|
parts,
|
16
17
|
params,
|
17
|
-
request
|
18
|
+
request,
|
19
|
+
alternate_request_methods
|
18
20
|
)
|
19
21
|
end
|
20
22
|
|
21
23
|
private
|
22
|
-
def process_response(node, parts, params, request)
|
24
|
+
def process_response(node, parts, params, request, alternate_request_methods)
|
23
25
|
if node.respond_to?(:matched?) && !node.matched?
|
24
26
|
node
|
25
27
|
elsif node && node.value
|
@@ -32,7 +34,11 @@ class HttpRouter
|
|
32
34
|
nil
|
33
35
|
end
|
34
36
|
else
|
35
|
-
|
37
|
+
if alternate_request_methods.empty?
|
38
|
+
nil
|
39
|
+
else
|
40
|
+
Response.unmatched(405, {"Allow" => alternate_request_methods.join(", ")})
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
data/lib/http_router/route.rb
CHANGED
@@ -26,7 +26,7 @@ class HttpRouter
|
|
26
26
|
|
27
27
|
# Returns the options used to create this route.
|
28
28
|
def as_options
|
29
|
-
{:matching => @matches_with, :conditions => @conditions, :default_values => @default_values, :name => @name}
|
29
|
+
{:matching => @matches_with, :conditions => @conditions, :default_values => @default_values, :name => @name, :partial => @partially_match}
|
30
30
|
end
|
31
31
|
|
32
32
|
# Creates a deep uncompiled copy of this route.
|
@@ -41,10 +41,13 @@ class HttpRouter
|
|
41
41
|
# *conditions -- Maps to #conditions method.
|
42
42
|
# *default_value -- Maps to #default_value method.
|
43
43
|
def with_options(options)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
if options
|
45
|
+
name(options[:name]) if options[:name]
|
46
|
+
matching(options[:matching]) if options[:matching]
|
47
|
+
condition(options[:conditions]) if options[:conditions]
|
48
|
+
default(options[:default_values]) if options[:default_values]
|
49
|
+
partial(options[:partial]) if options[:partial]
|
50
|
+
end
|
48
51
|
self
|
49
52
|
end
|
50
53
|
|
data/spec/rack/dispatch_spec.rb
CHANGED
@@ -35,6 +35,14 @@ describe "HttpRouter route dispatching" do
|
|
35
35
|
response = @route_set.call_with_mock_request
|
36
36
|
@app.env["router.params"].should == {}
|
37
37
|
end
|
38
|
+
|
39
|
+
it "should write router.params for default values" do
|
40
|
+
@route_set.add("/foobar", :default_values => {:hi => :there}).compile
|
41
|
+
response = @route_set.call_with_mock_request("/foobar")
|
42
|
+
env = Rack::MockRequest.env_for("/foobar")
|
43
|
+
@route_set.call(env)
|
44
|
+
env['router.params'].should == {:hi => :there}
|
45
|
+
end
|
38
46
|
end
|
39
47
|
|
40
48
|
describe "HTTP POST" do
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Rack::Urlmap replacement" do
|
4
|
+
it "should map urls" do
|
5
|
+
HttpRouter.override_rack_urlmap!
|
6
|
+
map = Rack::URLMap.new(
|
7
|
+
"http://www.example.org/test" => proc {|env| [200, {}, ['test']]},
|
8
|
+
"http://www.example.org/:test" => proc {|env| [200, {}, ['variable']]}
|
9
|
+
)
|
10
|
+
map.call(Rack::MockRequest.env_for('http://www.example.org/test')).last.join.should == 'test'
|
11
|
+
map.call(Rack::MockRequest.env_for('http://www.example.org/whhhaaa')).last.join.should == 'variable'
|
12
|
+
end
|
13
|
+
end
|
data/spec/recognize_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe "HttpRouter#recognize" do
|
|
5
5
|
end
|
6
6
|
|
7
7
|
context("with static paths") do
|
8
|
-
['/', '/test', '/test/time', '/one/more/what', '/test.html'].each do |path|
|
8
|
+
['/', '/test', '/test/time', '/one/more/what', '/test.html', '/.html'].each do |path|
|
9
9
|
it "should recognize #{path.inspect}" do
|
10
10
|
route = @router.add(path).to(path)
|
11
11
|
@router.recognize(Rack::MockRequest.env_for(path)).route.should == route
|
@@ -37,6 +37,7 @@ describe "HttpRouter#recognize" do
|
|
37
37
|
response.route.should == route
|
38
38
|
response.remaining_path.should == '/optional'
|
39
39
|
end
|
40
|
+
|
40
41
|
end
|
41
42
|
|
42
43
|
context("with proc acceptance") do
|
@@ -124,6 +125,21 @@ describe "HttpRouter#recognize" do
|
|
124
125
|
@router.recognize(Rack::MockRequest.env_for('/test', :method => 'GET')).headers['Allow'].should == "POST"
|
125
126
|
end
|
126
127
|
|
128
|
+
it "should recognize with optional parts and correctly return a 405 when the method isn't found" do
|
129
|
+
@router.get("/test(.:format)").to(:get)
|
130
|
+
@router.post("/test(.:format)").to(:post)
|
131
|
+
@router.delete("/test(.:format)").to(:delete)
|
132
|
+
@router.recognize(Rack::MockRequest.env_for('/test', :method => 'POST')).destination.should == :post
|
133
|
+
@router.recognize(Rack::MockRequest.env_for('/test', :method => 'GET')).destination.should == :get
|
134
|
+
@router.recognize(Rack::MockRequest.env_for('/test', :method => 'DELETE')).destination.should == :delete
|
135
|
+
@router.recognize(Rack::MockRequest.env_for('/test', :method => 'PUT')).status.should == 405
|
136
|
+
@router.recognize(Rack::MockRequest.env_for('/test', :method => 'PUT')).headers['Allow'].should == "DELETE, GET, POST"
|
137
|
+
@router.recognize(Rack::MockRequest.env_for('/test.html', :method => 'POST')).destination.should == :post
|
138
|
+
@router.recognize(Rack::MockRequest.env_for('/test.html', :method => 'GET')).destination.should == :get
|
139
|
+
@router.recognize(Rack::MockRequest.env_for('/test.html', :method => 'DELETE')).destination.should == :delete
|
140
|
+
@router.recognize(Rack::MockRequest.env_for('/test.html', :method => 'PUT')).status.should == 405
|
141
|
+
end
|
142
|
+
|
127
143
|
it "should recognize deeply" do
|
128
144
|
@router.post("/test").to(:test_post)
|
129
145
|
@router.post("/test/post").to(:test_post_post)
|
@@ -152,6 +168,14 @@ describe "HttpRouter#recognize" do
|
|
152
168
|
@router.recognize(Rack::MockRequest.env_for('http://host2/test', :method => 'POST')).dest.should == :any_post2
|
153
169
|
end
|
154
170
|
|
171
|
+
it "should match on scheme" do
|
172
|
+
@router.get("/test").scheme('http').to(:http)
|
173
|
+
@router.get("/test").scheme('https').to(:https)
|
174
|
+
@router.recognize(Rack::MockRequest.env_for('http://example.org/test')).dest.should == :http
|
175
|
+
@router.recognize(Rack::MockRequest.env_for('https://example.org/test')).dest.should == :https
|
176
|
+
@router.recognize(Rack::MockRequest.env_for('https://example.org/test', :method => 'POST')).matched?.should be_false
|
177
|
+
end
|
178
|
+
|
155
179
|
end
|
156
180
|
|
157
181
|
context("with dynamic paths") do
|
@@ -181,6 +205,16 @@ describe "HttpRouter#recognize" do
|
|
181
205
|
response.params_as_hash[:format].should be_nil
|
182
206
|
end
|
183
207
|
|
208
|
+
it "should recognize '/(.:format)'" do
|
209
|
+
route = @router.add('/(.:format)').to(:test)
|
210
|
+
response = @router.recognize(Rack::MockRequest.env_for('/.html'))
|
211
|
+
response.route.should == route
|
212
|
+
response.params_as_hash[:format].should == 'html'
|
213
|
+
response = @router.recognize(Rack::MockRequest.env_for('/'))
|
214
|
+
response.route.should == route
|
215
|
+
response.params_as_hash[:format].should be_nil
|
216
|
+
end
|
217
|
+
|
184
218
|
it "should recognize '/:test.:format'" do
|
185
219
|
route = @router.add('/:test.:format').to(:test)
|
186
220
|
response = @router.recognize(Rack::MockRequest.env_for('/hey.html'))
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http_router
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 5
|
10
|
+
version: 0.2.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Joshua Hull
|
@@ -15,40 +15,112 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-06-18 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name: rack
|
23
22
|
prerelease: false
|
24
|
-
|
23
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
25
24
|
none: false
|
26
25
|
requirements:
|
27
26
|
- - ">="
|
28
27
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
28
|
+
hash: 15
|
30
29
|
segments:
|
31
30
|
- 1
|
32
31
|
- 0
|
33
|
-
|
34
|
-
|
32
|
+
version: "1.0"
|
33
|
+
requirement: *id001
|
35
34
|
type: :runtime
|
36
|
-
|
35
|
+
name: rack
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
|
-
name: url_mount
|
39
37
|
prerelease: false
|
40
|
-
|
38
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
42
40
|
requirements:
|
43
41
|
- - ">="
|
44
42
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
43
|
+
hash: 21
|
46
44
|
segments:
|
47
45
|
- 0
|
48
46
|
- 2
|
49
|
-
|
47
|
+
- 1
|
48
|
+
version: 0.2.1
|
49
|
+
requirement: *id002
|
50
50
|
type: :runtime
|
51
|
-
|
51
|
+
name: url_mount
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
prerelease: false
|
54
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirement: *id003
|
64
|
+
type: :development
|
65
|
+
name: rspec
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
requirement: *id004
|
78
|
+
type: :development
|
79
|
+
name: rake
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
prerelease: false
|
82
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
requirement: *id005
|
92
|
+
type: :development
|
93
|
+
name: sinatra
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
prerelease: false
|
96
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
hash: 3
|
102
|
+
segments:
|
103
|
+
- 0
|
104
|
+
version: "0"
|
105
|
+
requirement: *id006
|
106
|
+
type: :development
|
107
|
+
name: rbench
|
108
|
+
- !ruby/object:Gem::Dependency
|
109
|
+
prerelease: false
|
110
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
hash: 9
|
116
|
+
segments:
|
117
|
+
- 0
|
118
|
+
- 0
|
119
|
+
- 11
|
120
|
+
version: 0.0.11
|
121
|
+
requirement: *id007
|
122
|
+
type: :development
|
123
|
+
name: tumbler
|
52
124
|
description: A kick-ass HTTP router for use in Rack & Sinatra
|
53
125
|
email: joshbuddy@gmail.com
|
54
126
|
executables: []
|
@@ -59,11 +131,12 @@ extra_rdoc_files:
|
|
59
131
|
- README.rdoc
|
60
132
|
files:
|
61
133
|
- .gitignore
|
134
|
+
- CHANGELOG
|
62
135
|
- Gemfile
|
63
136
|
- Gemfile.lock
|
64
137
|
- README.rdoc
|
65
138
|
- Rakefile
|
66
|
-
-
|
139
|
+
- Tumbler
|
67
140
|
- benchmarks/gen2.rb
|
68
141
|
- benchmarks/generation_bm.rb
|
69
142
|
- benchmarks/rack_mount.rb
|
@@ -74,10 +147,16 @@ files:
|
|
74
147
|
- examples/middleware.ru
|
75
148
|
- examples/rack_mapper.ru
|
76
149
|
- examples/simple.ru
|
150
|
+
- examples/static/config.ru
|
151
|
+
- examples/static/favicon.ico
|
152
|
+
- examples/static/images/cat1.jpg
|
153
|
+
- examples/static/images/cat2.jpg
|
154
|
+
- examples/static/images/cat3.jpg
|
77
155
|
- examples/variable.ru
|
78
156
|
- examples/variable_with_regex.ru
|
79
157
|
- http_router.gemspec
|
80
158
|
- lib/ext/rack/rack_mapper.rb
|
159
|
+
- lib/ext/rack/rack_urlmap.rb
|
81
160
|
- lib/ext/rack/uri_escape.rb
|
82
161
|
- lib/http_router.rb
|
83
162
|
- lib/http_router/glob.rb
|
@@ -90,6 +169,7 @@ files:
|
|
90
169
|
- lib/http_router/root.rb
|
91
170
|
- lib/http_router/route.rb
|
92
171
|
- lib/http_router/variable.rb
|
172
|
+
- lib/http_router/version.rb
|
93
173
|
- spec/generate_spec.rb
|
94
174
|
- spec/misc_spec.rb
|
95
175
|
- spec/mounting_spec.rb
|
@@ -97,6 +177,7 @@ files:
|
|
97
177
|
- spec/rack/generate_spec.rb
|
98
178
|
- spec/rack/middleware_spec.rb
|
99
179
|
- spec/rack/route_spec.rb
|
180
|
+
- spec/rack/urlmap_spec.rb
|
100
181
|
- spec/recognize_spec.rb
|
101
182
|
- spec/sinatra/recognize_spec.rb
|
102
183
|
- spec/spec.opts
|
@@ -143,6 +224,7 @@ test_files:
|
|
143
224
|
- spec/rack/generate_spec.rb
|
144
225
|
- spec/rack/middleware_spec.rb
|
145
226
|
- spec/rack/route_spec.rb
|
227
|
+
- spec/rack/urlmap_spec.rb
|
146
228
|
- spec/recognize_spec.rb
|
147
229
|
- spec/sinatra/recognize_spec.rb
|
148
230
|
- spec/spec.opts
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.2.4
|