http_router 0.0.1

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.
@@ -0,0 +1,176 @@
1
+ describe "HttpRouter#recognize" do
2
+ before(:each) do
3
+ @router = HttpRouter.new
4
+ end
5
+
6
+ context("static paths") do
7
+ ['/', '/test', '/test/time', '/one/more/what', '/test.html'].each do |path|
8
+ it "should recognize #{path.inspect}" do
9
+ route = @router.add(path)
10
+ @router.recognize(Rack::MockRequest.env_for(path)).route.should == route
11
+ end
12
+ end
13
+
14
+ context("with optional parts") do
15
+ it "work either way" do
16
+ route = @router.add("/test(/optional)")
17
+ @router.recognize(Rack::MockRequest.env_for('/test')).route.should == route
18
+ @router.recognize(Rack::MockRequest.env_for('/test/optional')).route.should == route
19
+ end
20
+ end
21
+
22
+ context("partial matching") do
23
+ it "should match partially or completely" do
24
+ route = @router.add("/test*")
25
+ @router.recognize(Rack::MockRequest.env_for('/test')).route.should == route
26
+ response = @router.recognize(Rack::MockRequest.env_for('/test/optional'))
27
+ response.route.should == route
28
+ response.remaining_path.should == '/optional'
29
+ end
30
+ end
31
+
32
+ context("trailing slashes") do
33
+ it "should ignore a trailing slash" do
34
+ route = @router.add("/test")
35
+ @router.recognize(Rack::MockRequest.env_for('/test/')).route.should == route
36
+ end
37
+
38
+ it "should not recognize a trailing slash when used with the /? syntax and ignore_trailing_slash disabled" do
39
+ @router = HttpRouter.new(:ignore_trailing_slash => false)
40
+ route = @router.add("/test/?")
41
+ @router.recognize(Rack::MockRequest.env_for('/test/')).route.should == route
42
+ end
43
+
44
+ it "should recognize a trailing slash when used with the /? syntax and ignore_trailing_slash enabled" do
45
+ @router = HttpRouter.new(:ignore_trailing_slash => false)
46
+ route = @router.add("/test")
47
+ @router.recognize(Rack::MockRequest.env_for('/test/')).should be_nil
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ context "request methods" do
54
+ it "should pick a specific request_method" do
55
+ route = @router.add("/test", :conditions => {:request_method => 'POST'})
56
+ @router.recognize(Rack::MockRequest.env_for('/test', :method => 'POST')).route.should == route
57
+ @router.recognize(Rack::MockRequest.env_for('/test', :method => 'GET')).status.should == 405
58
+ @router.recognize(Rack::MockRequest.env_for('/test', :method => 'GET')).headers['Allow'].should == "POST"
59
+ end
60
+
61
+ it "should pick a specific request_method with other paths all through it" do
62
+ @router.add("/test", :conditions => {:request_method => 'POST'}).name(:test_post)
63
+ @router.add("/test/post", :conditions => {:request_method => 'POST'}).name(:test_post_post)
64
+ @router.add("/test", :conditions => {:request_method => 'GET'}).name(:test_get)
65
+ @router.add("/test/post", :conditions => {:request_method => 'GET'}).name(:test_post_get)
66
+ @router.add("/test/post").name(:test_post_catchall)
67
+ @router.add("/test").name(:test_catchall)
68
+ @router.recognize(Rack::MockRequest.env_for('/test', :method => 'POST')).route.named.should == :test_post
69
+ @router.recognize(Rack::MockRequest.env_for('/test', :method => 'GET')).route.named.should == :test_get
70
+ @router.recognize(Rack::MockRequest.env_for('/test', :method => 'PUT')).route.named.should == :test_catchall
71
+ @router.recognize(Rack::MockRequest.env_for('/test/post', :method => 'POST')).route.named.should == :test_post_post
72
+ @router.recognize(Rack::MockRequest.env_for('/test/post', :method => 'GET')).route.named.should == :test_post_get
73
+ @router.recognize(Rack::MockRequest.env_for('/test/post', :method => 'PUT')).route.named.should == :test_post_catchall
74
+ end
75
+
76
+ it "should move an endpoint to the non-specific request method when a more specific route gets added" do
77
+ @router.add("/test").name(:test_catchall)
78
+ @router.add("/test", :conditions => {:request_method => 'POST'}).name(:test_post)
79
+ @router.recognize(Rack::MockRequest.env_for('/test', :method => 'POST')).route.named.should == :test_post
80
+ @router.recognize(Rack::MockRequest.env_for('/test', :method => 'PUT')).route.named.should == :test_catchall
81
+ end
82
+
83
+ end
84
+
85
+ context("dynamic paths") do
86
+ it "should recognize '/:variable'" do
87
+ route = @router.add('/:variable')
88
+ response = @router.recognize(Rack::MockRequest.env_for('/value'))
89
+ response.route.should == route
90
+ response.params.should == ['value']
91
+ response.params_as_hash[:variable].should == 'value'
92
+ end
93
+
94
+ it "should recognize '/test.:format'" do
95
+ route = @router.add('/test.:format')
96
+ response = @router.recognize(Rack::MockRequest.env_for('/test.html'))
97
+ response.route.should == route
98
+ response.extension.should == 'html'
99
+ response.params_as_hash[:format].should == 'html'
100
+ end
101
+
102
+ it "should recognize '/test(.:format)'" do
103
+ route = @router.add('/test(.:format)')
104
+ response = @router.recognize(Rack::MockRequest.env_for('/test.html'))
105
+ response.route.should == route
106
+ response.extension.should == 'html'
107
+ response.params_as_hash[:format].should == 'html'
108
+ response = @router.recognize(Rack::MockRequest.env_for('/test'))
109
+ response.route.should == route
110
+ response.extension.should be_nil
111
+ response.params_as_hash[:format].should be_nil
112
+ end
113
+
114
+ it "should recognize '/:test.:format'" do
115
+ route = @router.add('/:test.:format')
116
+ response = @router.recognize(Rack::MockRequest.env_for('/hey.html'))
117
+ response.route.should == route
118
+ response.extension.should == 'html'
119
+ response.params_as_hash[:format].should == 'html'
120
+ response.params_as_hash[:test].should == 'hey'
121
+ end
122
+
123
+ it "should recognize '/:test(.:format)'" do
124
+ route = @router.add('/:test(.:format)')
125
+ response = @router.recognize(Rack::MockRequest.env_for('/hey.html'))
126
+ response.route.should == route
127
+ response.extension.should == 'html'
128
+ response.params_as_hash[:format].should == 'html'
129
+ response.params_as_hash[:test].should == 'hey'
130
+ response = @router.recognize(Rack::MockRequest.env_for('/hey'))
131
+ response.route.should == route
132
+ response.extension.should be_nil
133
+ response.params_as_hash[:format].should be_nil
134
+ response.params_as_hash[:test].should == 'hey'
135
+ end
136
+
137
+ context "globs" do
138
+ it "should recognize a glob" do
139
+ route = @router.add('/test/*variable')
140
+ response = @router.recognize(Rack::MockRequest.env_for('/test/one/two/three'))
141
+ response.route.should == route
142
+ response.params.should == [['one', 'two', 'three']]
143
+ end
144
+ it "should recognize a glob with a regexp" do
145
+ route = @router.add('/test/*variable/anymore', :matches_with => {:variable => /^\d+$/})
146
+ response = @router.recognize(Rack::MockRequest.env_for('/test/123/345/567/anymore'))
147
+ response.route.should == route
148
+ response.params.should == [['123', '345', '567']]
149
+ response = @router.recognize(Rack::MockRequest.env_for('/test/123/345/567'))
150
+ response.should be_nil
151
+ end
152
+ end
153
+
154
+ end
155
+
156
+ context("interstitial variables") do
157
+ it "should recognize interstitial variables" do
158
+ route = @router.add('/one-:variable-time')
159
+ response = @router.recognize(Rack::MockRequest.env_for('/one-value-time'))
160
+ response.route.should == route
161
+ response.params_as_hash[:variable].should == 'value'
162
+ end
163
+ end
164
+
165
+ context("dynamic greedy paths") do
166
+ it "should recognize greedy variables" do
167
+ route = @router.add('/:variable', :matches_with => { :variable => /\d+/})
168
+ response = @router.recognize(Rack::MockRequest.env_for('/123'))
169
+ response.route.should == route
170
+ response.params.should == ['123']
171
+ response.params_as_hash[:variable].should == '123'
172
+ response = @router.recognize(Rack::MockRequest.env_for('/asd'))
173
+ response.should be_nil
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,140 @@
1
+ require "sinatra"
2
+ require "http_router/sinatra"
3
+
4
+ describe "Usher (for Sinatra) route recognition" do
5
+ before(:each) do
6
+ @app = Sinatra.new { register HttpRouter::Interface::Sinatra::Extension }
7
+ @app.extend(CallWithMockRequestMixin)
8
+ @app.reset!
9
+ end
10
+
11
+ describe "basic functionality" do
12
+ it "should map not found" do
13
+ response = @app.call_with_mock_request('/bar')
14
+ response.status.should == 404
15
+ end
16
+
17
+ it "should map index" do
18
+ @app.get("/") { "index" }
19
+ response = @app.call_with_mock_request('/')
20
+ response.status.should == 200
21
+ response.body.should == "index"
22
+ end
23
+
24
+ it "should ignore trailing delimiters" do
25
+ @app.get("/foo") { "foo" }
26
+ response = @app.call_with_mock_request('/foo')
27
+ response.status.should == 200
28
+ response.body.should == "foo"
29
+ response = @app.call_with_mock_request('/foo/')
30
+ response.status.should == 200
31
+ response.body.should == "foo"
32
+ end
33
+
34
+ it "should ignore trailing delimiters in a more advanced route" do
35
+ @app.get("/foo") { "foo" }
36
+ @app.get("/foo/bar") { "bar" }
37
+ response = @app.call_with_mock_request('/foo')
38
+ response.status.should == 200
39
+ response.body.should == "foo"
40
+ response = @app.call_with_mock_request('/foo/bar')
41
+ response.status.should == 200
42
+ response.body.should == "bar"
43
+ response = @app.call_with_mock_request('/foo/')
44
+ response.status.should == 200
45
+ response.body.should == "foo"
46
+ response = @app.call_with_mock_request('/foo/bar/')
47
+ response.status.should == 200
48
+ response.body.should == "bar"
49
+ end
50
+
51
+ it "should ignore trailing delimiters with an optional param" do
52
+ @app.get("/foo/(:bar)") { params[:bar] }
53
+ @app.get("/bar(/:foo)") { params[:foo] }
54
+ response = @app.call_with_mock_request('/foo/bar')
55
+ response.status.should == 200
56
+ response.body.should == "bar"
57
+ response = @app.call_with_mock_request('/bar/foo')
58
+ response.status.should == 200
59
+ response.body.should == "foo"
60
+ response = @app.call_with_mock_request('/bar')
61
+ response.status.should == 200
62
+ response.body.should == ""
63
+ response = @app.call_with_mock_request('/bar/')
64
+ response.status.should == 200
65
+ response.body.should == ""
66
+ end
67
+
68
+ it "should use sinatra optionals trailing delimiters" do
69
+ @app.get("/foo/?") { "foo" }
70
+ response = @app.call_with_mock_request('/foo')
71
+ response.status.should == 200
72
+ response.body.should == "foo"
73
+ response = @app.call_with_mock_request('/foo/')
74
+ response.status.should == 200
75
+ response.body.should == "foo"
76
+ end
77
+ end
78
+
79
+ describe "mapping functionality" do
80
+
81
+ it "should map a basic route" do
82
+ @app.get('/hi', :name => :hi) { generate(:hi) }
83
+ response = @app.call_with_mock_request('/hi')
84
+ response.status.should == 200
85
+ response.body.should == "/hi"
86
+ end
87
+
88
+ it "should map a basic route ignoring trailing delimiters" do
89
+ @app.get('/hi', :name => :hi) { generate(:hi) }
90
+ response = @app.call_with_mock_request('/hi/')
91
+ response.status.should == 200
92
+ response.body.should == "/hi"
93
+ end
94
+
95
+ it "should map a basic route with params" do
96
+ @app.get('/hi/:id', :name => :hi) { generate(:hi, :id => 18) }
97
+ response = @app.call_with_mock_request('/hi/1')
98
+ response.status.should == 200
99
+ response.body.should == "/hi/18"
100
+ end
101
+
102
+ it "should map route with params" do
103
+ @app.get('/hi-:id', :name => :hi) { generate(:hi, :id => 18) }
104
+ response = @app.call_with_mock_request('/hi-1')
105
+ response.status.should == 200
106
+ response.body.should == "/hi-18"
107
+ end
108
+
109
+ it "should map route with complex params" do
110
+ @app.get('/hi/:foo/:bar/:baz(.:format)') { "/#{params[:foo]}/#{params[:bar]}/#{params[:baz]}/#{params[:format]}" }
111
+ response = @app.call_with_mock_request('/hi/foo/bar/baz')
112
+ response.status.should == 200
113
+ response.body.should == "/foo/bar/baz/"
114
+ response = @app.call_with_mock_request('/hi/foo/bar-bax/baz')
115
+ response.status.should == 200
116
+ response.body.should == "/foo/bar-bax/baz/"
117
+ end
118
+ end
119
+
120
+ describe "not found" do
121
+
122
+ it "should correctly generate a not found page without images" do
123
+ response = @app.call_with_mock_request('/bar')
124
+ response.status.should == 404
125
+ response.body.should_not match(/__sinatra__/)
126
+ end
127
+ end
128
+
129
+ describe "method not allowed" do
130
+
131
+ it "should correctly generate a not found page without images and return a 405" do
132
+ @app.post('/bar') { 'found' }
133
+ @app.put('/bar') { 'found' }
134
+ response = @app.call_with_mock_request('/bar')
135
+ response.status.should == 405
136
+ response.headers['Allow'].should == 'POST, PUT'
137
+ response.body.should_not match(/__sinatra__/)
138
+ end
139
+ end
140
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,7 @@
1
+ --colour
2
+ --format
3
+ specdoc
4
+ --loadby
5
+ mtime
6
+ --reverse
7
+ --backtrace
@@ -0,0 +1,24 @@
1
+ require 'rack'
2
+
3
+ module CallWithMockRequestMixin
4
+ def call_with_mock_request(url = "/sample", method = "GET", params = Hash.new)
5
+ params.merge!(:method => method)
6
+ request = Rack::MockRequest.new(self)
7
+ request.request(method, url, params)
8
+ end
9
+ end
10
+
11
+ class MockApp
12
+ attr_accessor :status, :headers, :body, :env
13
+ def initialize(body)
14
+ @status = 200
15
+ @headers = {"Content-Type" => "text/html"}
16
+ @body = body
17
+ end
18
+
19
+ def call(env)
20
+ @env = env
21
+ @headers.merge("Content-Length" => @body.length.to_s)
22
+ [@status, @headers, [@body]]
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: http_router
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Joshua Hull
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-25 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: A kick-ass HTTP router for use in Rack & Sinatra
22
+ email: joshbuddy@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README.rdoc
29
+ files:
30
+ - README.rdoc
31
+ - Rakefile
32
+ - VERSION
33
+ - lib/http_router.rb
34
+ - lib/http_router/glob.rb
35
+ - lib/http_router/node.rb
36
+ - lib/http_router/path.rb
37
+ - lib/http_router/response.rb
38
+ - lib/http_router/root.rb
39
+ - lib/http_router/route.rb
40
+ - lib/http_router/sinatra.rb
41
+ - lib/http_router/variable.rb
42
+ - lib/rack/uri_escape.rb
43
+ - spec/generate_spec.rb
44
+ - spec/rack/dispatch_spec.rb
45
+ - spec/rack/generate_spec.rb
46
+ - spec/rack/route_spec.rb
47
+ - spec/recognize_spec.rb
48
+ - spec/sinatra/recognize_spec.rb
49
+ - spec/spec.opts
50
+ - spec/spec_helper.rb
51
+ has_rdoc: true
52
+ homepage: http://github.com/joshbuddy/http_router
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --charset=UTF-8
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.3.6
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: A kick-ass HTTP router for use in Rack & Sinatra
81
+ test_files:
82
+ - spec/generate_spec.rb
83
+ - spec/rack/dispatch_spec.rb
84
+ - spec/rack/generate_spec.rb
85
+ - spec/rack/route_spec.rb
86
+ - spec/recognize_spec.rb
87
+ - spec/sinatra/recognize_spec.rb
88
+ - spec/spec_helper.rb