qoobaa-rack 1.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.
Files changed (116) hide show
  1. data/COPYING +18 -0
  2. data/KNOWN-ISSUES +18 -0
  3. data/RDOX +0 -0
  4. data/README +353 -0
  5. data/Rakefile +164 -0
  6. data/SPEC +164 -0
  7. data/bin/rackup +176 -0
  8. data/contrib/rack_logo.svg +111 -0
  9. data/example/lobster.ru +4 -0
  10. data/example/protectedlobster.rb +14 -0
  11. data/example/protectedlobster.ru +8 -0
  12. data/lib/rack/adapter/camping.rb +22 -0
  13. data/lib/rack/auth/abstract/handler.rb +37 -0
  14. data/lib/rack/auth/abstract/request.rb +37 -0
  15. data/lib/rack/auth/basic.rb +58 -0
  16. data/lib/rack/auth/digest/md5.rb +124 -0
  17. data/lib/rack/auth/digest/nonce.rb +51 -0
  18. data/lib/rack/auth/digest/params.rb +55 -0
  19. data/lib/rack/auth/digest/request.rb +40 -0
  20. data/lib/rack/auth/openid.rb +487 -0
  21. data/lib/rack/builder.rb +63 -0
  22. data/lib/rack/cascade.rb +41 -0
  23. data/lib/rack/chunked.rb +49 -0
  24. data/lib/rack/commonlogger.rb +52 -0
  25. data/lib/rack/conditionalget.rb +47 -0
  26. data/lib/rack/content_length.rb +29 -0
  27. data/lib/rack/content_type.rb +23 -0
  28. data/lib/rack/deflater.rb +96 -0
  29. data/lib/rack/directory.rb +153 -0
  30. data/lib/rack/file.rb +88 -0
  31. data/lib/rack/handler/cgi.rb +61 -0
  32. data/lib/rack/handler/evented_mongrel.rb +8 -0
  33. data/lib/rack/handler/fastcgi.rb +88 -0
  34. data/lib/rack/handler/lsws.rb +60 -0
  35. data/lib/rack/handler/mongrel.rb +87 -0
  36. data/lib/rack/handler/scgi.rb +62 -0
  37. data/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  38. data/lib/rack/handler/thin.rb +18 -0
  39. data/lib/rack/handler/webrick.rb +71 -0
  40. data/lib/rack/handler.rb +69 -0
  41. data/lib/rack/head.rb +19 -0
  42. data/lib/rack/lint.rb +546 -0
  43. data/lib/rack/lobster.rb +65 -0
  44. data/lib/rack/lock.rb +16 -0
  45. data/lib/rack/methodoverride.rb +27 -0
  46. data/lib/rack/mime.rb +204 -0
  47. data/lib/rack/mock.rb +187 -0
  48. data/lib/rack/recursive.rb +57 -0
  49. data/lib/rack/reloader.rb +107 -0
  50. data/lib/rack/request.rb +248 -0
  51. data/lib/rack/response.rb +183 -0
  52. data/lib/rack/rewindable_input.rb +100 -0
  53. data/lib/rack/session/abstract/id.rb +142 -0
  54. data/lib/rack/session/cookie.rb +91 -0
  55. data/lib/rack/session/memcache.rb +109 -0
  56. data/lib/rack/session/pool.rb +100 -0
  57. data/lib/rack/showexceptions.rb +349 -0
  58. data/lib/rack/showstatus.rb +106 -0
  59. data/lib/rack/static.rb +38 -0
  60. data/lib/rack/urlmap.rb +55 -0
  61. data/lib/rack/utils.rb +528 -0
  62. data/lib/rack.rb +90 -0
  63. data/rack.gemspec +60 -0
  64. data/test/cgi/lighttpd.conf +20 -0
  65. data/test/cgi/test +9 -0
  66. data/test/cgi/test.fcgi +8 -0
  67. data/test/cgi/test.ru +7 -0
  68. data/test/multipart/binary +0 -0
  69. data/test/multipart/empty +10 -0
  70. data/test/multipart/file1.txt +1 -0
  71. data/test/multipart/ie +6 -0
  72. data/test/multipart/nested +10 -0
  73. data/test/multipart/none +9 -0
  74. data/test/multipart/text +10 -0
  75. data/test/spec_rack_auth_basic.rb +73 -0
  76. data/test/spec_rack_auth_digest.rb +226 -0
  77. data/test/spec_rack_auth_openid.rb +84 -0
  78. data/test/spec_rack_builder.rb +84 -0
  79. data/test/spec_rack_camping.rb +51 -0
  80. data/test/spec_rack_cascade.rb +48 -0
  81. data/test/spec_rack_cgi.rb +89 -0
  82. data/test/spec_rack_chunked.rb +62 -0
  83. data/test/spec_rack_commonlogger.rb +61 -0
  84. data/test/spec_rack_conditionalget.rb +41 -0
  85. data/test/spec_rack_content_length.rb +43 -0
  86. data/test/spec_rack_content_type.rb +30 -0
  87. data/test/spec_rack_deflater.rb +127 -0
  88. data/test/spec_rack_directory.rb +61 -0
  89. data/test/spec_rack_fastcgi.rb +89 -0
  90. data/test/spec_rack_file.rb +75 -0
  91. data/test/spec_rack_handler.rb +43 -0
  92. data/test/spec_rack_head.rb +30 -0
  93. data/test/spec_rack_lint.rb +521 -0
  94. data/test/spec_rack_lobster.rb +45 -0
  95. data/test/spec_rack_lock.rb +38 -0
  96. data/test/spec_rack_methodoverride.rb +60 -0
  97. data/test/spec_rack_mock.rb +243 -0
  98. data/test/spec_rack_mongrel.rb +189 -0
  99. data/test/spec_rack_recursive.rb +77 -0
  100. data/test/spec_rack_request.rb +504 -0
  101. data/test/spec_rack_response.rb +218 -0
  102. data/test/spec_rack_rewindable_input.rb +118 -0
  103. data/test/spec_rack_session_cookie.rb +82 -0
  104. data/test/spec_rack_session_memcache.rb +250 -0
  105. data/test/spec_rack_session_pool.rb +172 -0
  106. data/test/spec_rack_showexceptions.rb +21 -0
  107. data/test/spec_rack_showstatus.rb +72 -0
  108. data/test/spec_rack_static.rb +37 -0
  109. data/test/spec_rack_thin.rb +91 -0
  110. data/test/spec_rack_urlmap.rb +185 -0
  111. data/test/spec_rack_utils.rb +467 -0
  112. data/test/spec_rack_webrick.rb +130 -0
  113. data/test/testrequest.rb +57 -0
  114. data/test/unregistered_handler/rack/handler/unregistered.rb +7 -0
  115. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
  116. metadata +276 -0
@@ -0,0 +1,172 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/session/pool'
4
+ require 'rack/mock'
5
+ require 'rack/response'
6
+ require 'thread'
7
+
8
+ context "Rack::Session::Pool" do
9
+ session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key]
10
+ session_match = /#{session_key}=[0-9a-fA-F]+;/
11
+ incrementor = lambda do |env|
12
+ env["rack.session"]["counter"] ||= 0
13
+ env["rack.session"]["counter"] += 1
14
+ Rack::Response.new(env["rack.session"].inspect).to_a
15
+ end
16
+ drop_session = proc do |env|
17
+ env['rack.session.options'][:drop] = true
18
+ incrementor.call(env)
19
+ end
20
+ renew_session = proc do |env|
21
+ env['rack.session.options'][:renew] = true
22
+ incrementor.call(env)
23
+ end
24
+ defer_session = proc do |env|
25
+ env['rack.session.options'][:defer] = true
26
+ incrementor.call(env)
27
+ end
28
+
29
+ specify "creates a new cookie" do
30
+ pool = Rack::Session::Pool.new(incrementor)
31
+ res = Rack::MockRequest.new(pool).get("/")
32
+ res["Set-Cookie"].should.match session_match
33
+ res.body.should.equal '{"counter"=>1}'
34
+ end
35
+
36
+ specify "determines session from a cookie" do
37
+ pool = Rack::Session::Pool.new(incrementor)
38
+ req = Rack::MockRequest.new(pool)
39
+ cookie = req.get("/")["Set-Cookie"]
40
+ req.get("/", "HTTP_COOKIE" => cookie).
41
+ body.should.equal '{"counter"=>2}'
42
+ req.get("/", "HTTP_COOKIE" => cookie).
43
+ body.should.equal '{"counter"=>3}'
44
+ end
45
+
46
+ specify "survives nonexistant cookies" do
47
+ pool = Rack::Session::Pool.new(incrementor)
48
+ res = Rack::MockRequest.new(pool).
49
+ get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel")
50
+ res.body.should.equal '{"counter"=>1}'
51
+ end
52
+
53
+ specify "deletes cookies with :drop option" do
54
+ pool = Rack::Session::Pool.new(incrementor)
55
+ req = Rack::MockRequest.new(pool)
56
+ drop = Rack::Utils::Context.new(pool, drop_session)
57
+ dreq = Rack::MockRequest.new(drop)
58
+
59
+ res0 = req.get("/")
60
+ session = (cookie = res0["Set-Cookie"])[session_match]
61
+ res0.body.should.equal '{"counter"=>1}'
62
+ pool.pool.size.should.be 1
63
+
64
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
65
+ res1["Set-Cookie"][session_match].should.equal session
66
+ res1.body.should.equal '{"counter"=>2}'
67
+ pool.pool.size.should.be 1
68
+
69
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
70
+ res2["Set-Cookie"].should.equal nil
71
+ res2.body.should.equal '{"counter"=>3}'
72
+ pool.pool.size.should.be 0
73
+
74
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
75
+ res3["Set-Cookie"][session_match].should.not.equal session
76
+ res3.body.should.equal '{"counter"=>1}'
77
+ pool.pool.size.should.be 1
78
+ end
79
+
80
+ specify "provides new session id with :renew option" do
81
+ pool = Rack::Session::Pool.new(incrementor)
82
+ req = Rack::MockRequest.new(pool)
83
+ renew = Rack::Utils::Context.new(pool, renew_session)
84
+ rreq = Rack::MockRequest.new(renew)
85
+
86
+ res0 = req.get("/")
87
+ session = (cookie = res0["Set-Cookie"])[session_match]
88
+ res0.body.should.equal '{"counter"=>1}'
89
+ pool.pool.size.should.be 1
90
+
91
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
92
+ res1["Set-Cookie"][session_match].should.equal session
93
+ res1.body.should.equal '{"counter"=>2}'
94
+ pool.pool.size.should.be 1
95
+
96
+ res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
97
+ new_cookie = res2["Set-Cookie"]
98
+ new_session = new_cookie[session_match]
99
+ new_session.should.not.equal session
100
+ res2.body.should.equal '{"counter"=>3}'
101
+ pool.pool.size.should.be 1
102
+
103
+ res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
104
+ res3["Set-Cookie"][session_match].should.equal new_session
105
+ res3.body.should.equal '{"counter"=>4}'
106
+ pool.pool.size.should.be 1
107
+ end
108
+
109
+ specify "omits cookie with :defer option" do
110
+ pool = Rack::Session::Pool.new(incrementor)
111
+ req = Rack::MockRequest.new(pool)
112
+ defer = Rack::Utils::Context.new(pool, defer_session)
113
+ dreq = Rack::MockRequest.new(defer)
114
+
115
+ res0 = req.get("/")
116
+ session = (cookie = res0["Set-Cookie"])[session_match]
117
+ res0.body.should.equal '{"counter"=>1}'
118
+ pool.pool.size.should.be 1
119
+
120
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
121
+ res1["Set-Cookie"][session_match].should.equal session
122
+ res1.body.should.equal '{"counter"=>2}'
123
+ pool.pool.size.should.be 1
124
+
125
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
126
+ res2["Set-Cookie"].should.equal nil
127
+ res2.body.should.equal '{"counter"=>3}'
128
+ pool.pool.size.should.be 1
129
+
130
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
131
+ res3["Set-Cookie"][session_match].should.equal session
132
+ res3.body.should.equal '{"counter"=>4}'
133
+ pool.pool.size.should.be 1
134
+ end
135
+
136
+ # anyone know how to do this better?
137
+ specify "multithread: should merge sessions" do
138
+ next unless $DEBUG
139
+ warn 'Running multithread tests for Session::Pool'
140
+ pool = Rack::Session::Pool.new(incrementor)
141
+ req = Rack::MockRequest.new(pool)
142
+
143
+ res = req.get('/')
144
+ res.body.should.equal '{"counter"=>1}'
145
+ cookie = res["Set-Cookie"]
146
+ sess_id = cookie[/#{pool.key}=([^,;]+)/,1]
147
+
148
+ delta_incrementor = lambda do |env|
149
+ # emulate disconjoinment of threading
150
+ env['rack.session'] = env['rack.session'].dup
151
+ Thread.stop
152
+ env['rack.session'][(Time.now.usec*rand).to_i] = true
153
+ incrementor.call(env)
154
+ end
155
+ tses = Rack::Utils::Context.new pool, delta_incrementor
156
+ treq = Rack::MockRequest.new(tses)
157
+ tnum = rand(7).to_i+5
158
+ r = Array.new(tnum) do
159
+ Thread.new(treq) do |run|
160
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
161
+ end
162
+ end.reverse.map{|t| t.run.join.value }
163
+ r.each do |res|
164
+ res['Set-Cookie'].should.equal cookie
165
+ res.body.should.include '"counter"=>2'
166
+ end
167
+
168
+ session = pool.pool[sess_id]
169
+ session.size.should.be tnum+1 # counter
170
+ session['counter'].should.be 2 # meeeh
171
+ end
172
+ end
@@ -0,0 +1,21 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/showexceptions'
4
+ require 'rack/mock'
5
+
6
+ context "Rack::ShowExceptions" do
7
+ specify "catches exceptions" do
8
+ res = nil
9
+ req = Rack::MockRequest.new(Rack::ShowExceptions.new(lambda { |env|
10
+ raise RuntimeError
11
+ }))
12
+ lambda {
13
+ res = req.get("/")
14
+ }.should.not.raise
15
+ res.should.be.a.server_error
16
+ res.status.should.equal 500
17
+
18
+ res.should =~ /RuntimeError/
19
+ res.should =~ /ShowExceptions/
20
+ end
21
+ end
@@ -0,0 +1,72 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/showstatus'
4
+ require 'rack/mock'
5
+
6
+ context "Rack::ShowStatus" do
7
+ specify "should provide a default status message" do
8
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env|
9
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
10
+ }))
11
+
12
+ res = req.get("/", :lint => true)
13
+ res.should.be.not_found
14
+ res.should.be.not.empty
15
+
16
+ res["Content-Type"].should.equal("text/html")
17
+ res.should =~ /404/
18
+ res.should =~ /Not Found/
19
+ end
20
+
21
+ specify "should let the app provide additional information" do
22
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env|
23
+ env["rack.showstatus.detail"] = "gone too meta."
24
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
25
+ }))
26
+
27
+ res = req.get("/", :lint => true)
28
+ res.should.be.not_found
29
+ res.should.be.not.empty
30
+
31
+ res["Content-Type"].should.equal("text/html")
32
+ res.should =~ /404/
33
+ res.should =~ /Not Found/
34
+ res.should =~ /too meta/
35
+ end
36
+
37
+ specify "should not replace existing messages" do
38
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env|
39
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
40
+ }))
41
+ res = req.get("/", :lint => true)
42
+ res.should.be.not_found
43
+
44
+ res.body.should == "foo!"
45
+ end
46
+
47
+ specify "should pass on original headers" do
48
+ headers = {"WWW-Authenticate" => "Basic blah"}
49
+
50
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env| [401, headers, []] }))
51
+ res = req.get("/", :lint => true)
52
+
53
+ res["WWW-Authenticate"].should.equal("Basic blah")
54
+ end
55
+
56
+ specify "should replace existing messages if there is detail" do
57
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env|
58
+ env["rack.showstatus.detail"] = "gone too meta."
59
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
60
+ }))
61
+
62
+ res = req.get("/", :lint => true)
63
+ res.should.be.not_found
64
+ res.should.be.not.empty
65
+
66
+ res["Content-Type"].should.equal("text/html")
67
+ res["Content-Length"].should.not.equal("4")
68
+ res.should =~ /404/
69
+ res.should =~ /too meta/
70
+ res.body.should.not =~ /foo/
71
+ end
72
+ end
@@ -0,0 +1,37 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/static'
4
+ require 'rack/mock'
5
+
6
+ class DummyApp
7
+ def call(env)
8
+ [200, {}, ["Hello World"]]
9
+ end
10
+ end
11
+
12
+ context "Rack::Static" do
13
+ root = File.expand_path(File.dirname(__FILE__))
14
+ OPTIONS = {:urls => ["/cgi"], :root => root}
15
+
16
+ setup do
17
+ @request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, OPTIONS))
18
+ end
19
+
20
+ specify "serves files" do
21
+ res = @request.get("/cgi/test")
22
+ res.should.be.ok
23
+ res.body.should =~ /ruby/
24
+ end
25
+
26
+ specify "404s if url root is known but it can't find the file" do
27
+ res = @request.get("/cgi/foo")
28
+ res.should.be.not_found
29
+ end
30
+
31
+ specify "calls down the chain if url root is not known" do
32
+ res = @request.get("/something/else")
33
+ res.should.be.ok
34
+ res.body.should == "Hello World"
35
+ end
36
+
37
+ end
@@ -0,0 +1,91 @@
1
+ require 'test/spec'
2
+
3
+ begin
4
+ require 'rack/handler/thin'
5
+ require 'testrequest'
6
+ require 'timeout'
7
+
8
+ context "Rack::Handler::Thin" do
9
+ include TestRequest::Helpers
10
+
11
+ setup do
12
+ @app = Rack::Lint.new(TestRequest.new)
13
+ @server = nil
14
+ Thin::Logging.silent = true
15
+ @thread = Thread.new do
16
+ Rack::Handler::Thin.run(@app, :Host => @host='0.0.0.0', :Port => @port=9204) do |server|
17
+ @server = server
18
+ end
19
+ end
20
+ Thread.pass until @server && @server.running?
21
+ end
22
+
23
+ specify "should respond" do
24
+ lambda {
25
+ GET("/")
26
+ }.should.not.raise
27
+ end
28
+
29
+ specify "should be a Thin" do
30
+ GET("/")
31
+ status.should.be 200
32
+ response["SERVER_SOFTWARE"].should =~ /thin/
33
+ response["HTTP_VERSION"].should.equal "HTTP/1.1"
34
+ response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
35
+ response["SERVER_PORT"].should.equal "9204"
36
+ response["SERVER_NAME"].should.equal "0.0.0.0"
37
+ end
38
+
39
+ specify "should have rack headers" do
40
+ GET("/")
41
+ response["rack.version"].should.equal [0,3]
42
+ response["rack.multithread"].should.be false
43
+ response["rack.multiprocess"].should.be false
44
+ response["rack.run_once"].should.be false
45
+ end
46
+
47
+ specify "should have CGI headers on GET" do
48
+ GET("/")
49
+ response["REQUEST_METHOD"].should.equal "GET"
50
+ response["REQUEST_PATH"].should.equal "/"
51
+ response["PATH_INFO"].should.be.equal "/"
52
+ response["QUERY_STRING"].should.equal ""
53
+ response["test.postdata"].should.equal ""
54
+
55
+ GET("/test/foo?quux=1")
56
+ response["REQUEST_METHOD"].should.equal "GET"
57
+ response["REQUEST_PATH"].should.equal "/test/foo"
58
+ response["PATH_INFO"].should.equal "/test/foo"
59
+ response["QUERY_STRING"].should.equal "quux=1"
60
+ end
61
+
62
+ specify "should have CGI headers on POST" do
63
+ POST("/", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
64
+ status.should.equal 200
65
+ response["REQUEST_METHOD"].should.equal "POST"
66
+ response["REQUEST_PATH"].should.equal "/"
67
+ response["QUERY_STRING"].should.equal ""
68
+ response["HTTP_X_TEST_HEADER"].should.equal "42"
69
+ response["test.postdata"].should.equal "rack-form-data=23"
70
+ end
71
+
72
+ specify "should support HTTP auth" do
73
+ GET("/test", {:user => "ruth", :passwd => "secret"})
74
+ response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
75
+ end
76
+
77
+ specify "should set status" do
78
+ GET("/test?secret")
79
+ status.should.equal 403
80
+ response["rack.url_scheme"].should.equal "http"
81
+ end
82
+
83
+ teardown do
84
+ @server.stop!
85
+ @thread.kill
86
+ end
87
+ end
88
+
89
+ rescue LoadError
90
+ $stderr.puts "Skipping Rack::Handler::Thin tests (Thin is required). `gem install thin` and try again."
91
+ end
@@ -0,0 +1,185 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/urlmap'
4
+ require 'rack/mock'
5
+
6
+ context "Rack::URLMap" do
7
+ specify "dispatches paths correctly" do
8
+ app = lambda { |env|
9
+ [200, {
10
+ 'X-ScriptName' => env['SCRIPT_NAME'],
11
+ 'X-PathInfo' => env['PATH_INFO'],
12
+ 'Content-Type' => 'text/plain'
13
+ }, [""]]
14
+ }
15
+ map = Rack::URLMap.new({
16
+ 'http://foo.org/bar' => app,
17
+ '/foo' => app,
18
+ '/foo/bar' => app
19
+ })
20
+
21
+ res = Rack::MockRequest.new(map).get("/")
22
+ res.should.be.not_found
23
+
24
+ res = Rack::MockRequest.new(map).get("/qux")
25
+ res.should.be.not_found
26
+
27
+ res = Rack::MockRequest.new(map).get("/foo")
28
+ res.should.be.ok
29
+ res["X-ScriptName"].should.equal "/foo"
30
+ res["X-PathInfo"].should.equal ""
31
+
32
+ res = Rack::MockRequest.new(map).get("/foo/")
33
+ res.should.be.ok
34
+ res["X-ScriptName"].should.equal "/foo"
35
+ res["X-PathInfo"].should.equal "/"
36
+
37
+ res = Rack::MockRequest.new(map).get("/foo/bar")
38
+ res.should.be.ok
39
+ res["X-ScriptName"].should.equal "/foo/bar"
40
+ res["X-PathInfo"].should.equal ""
41
+
42
+ res = Rack::MockRequest.new(map).get("/foo/bar/")
43
+ res.should.be.ok
44
+ res["X-ScriptName"].should.equal "/foo/bar"
45
+ res["X-PathInfo"].should.equal "/"
46
+
47
+ res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
48
+ res.should.be.ok
49
+ res["X-ScriptName"].should.equal "/bleh/foo"
50
+ res["X-PathInfo"].should.equal "/quux"
51
+
52
+ res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org')
53
+ res.should.be.ok
54
+ res["X-ScriptName"].should.equal "/bar"
55
+ res["X-PathInfo"].should.be.empty
56
+
57
+ res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org')
58
+ res.should.be.ok
59
+ res["X-ScriptName"].should.equal "/bar"
60
+ res["X-PathInfo"].should.equal '/'
61
+ end
62
+
63
+
64
+ specify "dispatches hosts correctly" do
65
+ map = Rack::URLMap.new("http://foo.org/" => lambda { |env|
66
+ [200,
67
+ { "Content-Type" => "text/plain",
68
+ "X-Position" => "foo.org",
69
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
70
+ }, [""]]},
71
+ "http://subdomain.foo.org/" => lambda { |env|
72
+ [200,
73
+ { "Content-Type" => "text/plain",
74
+ "X-Position" => "subdomain.foo.org",
75
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
76
+ }, [""]]},
77
+ "http://bar.org/" => lambda { |env|
78
+ [200,
79
+ { "Content-Type" => "text/plain",
80
+ "X-Position" => "bar.org",
81
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
82
+ }, [""]]},
83
+ "/" => lambda { |env|
84
+ [200,
85
+ { "Content-Type" => "text/plain",
86
+ "X-Position" => "default.org",
87
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
88
+ }, [""]]}
89
+ )
90
+
91
+ res = Rack::MockRequest.new(map).get("/")
92
+ res.should.be.ok
93
+ res["X-Position"].should.equal "default.org"
94
+
95
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org")
96
+ res.should.be.ok
97
+ res["X-Position"].should.equal "bar.org"
98
+
99
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org")
100
+ res.should.be.ok
101
+ res["X-Position"].should.equal "foo.org"
102
+
103
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org")
104
+ res.should.be.ok
105
+ res["X-Position"].should.equal "subdomain.foo.org"
106
+
107
+ res = Rack::MockRequest.new(map).get("http://foo.org/")
108
+ res.should.be.ok
109
+ res["X-Position"].should.equal "default.org"
110
+
111
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org")
112
+ res.should.be.ok
113
+ res["X-Position"].should.equal "default.org"
114
+
115
+ res = Rack::MockRequest.new(map).get("/",
116
+ "HTTP_HOST" => "example.org:9292",
117
+ "SERVER_PORT" => "9292")
118
+ res.should.be.ok
119
+ res["X-Position"].should.equal "default.org"
120
+ end
121
+
122
+ specify "should be nestable" do
123
+ map = Rack::URLMap.new("/foo" =>
124
+ Rack::URLMap.new("/bar" =>
125
+ Rack::URLMap.new("/quux" => lambda { |env|
126
+ [200,
127
+ { "Content-Type" => "text/plain",
128
+ "X-Position" => "/foo/bar/quux",
129
+ "X-PathInfo" => env["PATH_INFO"],
130
+ "X-ScriptName" => env["SCRIPT_NAME"],
131
+ }, [""]]}
132
+ )))
133
+
134
+ res = Rack::MockRequest.new(map).get("/foo/bar")
135
+ res.should.be.not_found
136
+
137
+ res = Rack::MockRequest.new(map).get("/foo/bar/quux")
138
+ res.should.be.ok
139
+ res["X-Position"].should.equal "/foo/bar/quux"
140
+ res["X-PathInfo"].should.equal ""
141
+ res["X-ScriptName"].should.equal "/foo/bar/quux"
142
+ end
143
+
144
+ specify "should route root apps correctly" do
145
+ map = Rack::URLMap.new("/" => lambda { |env|
146
+ [200,
147
+ { "Content-Type" => "text/plain",
148
+ "X-Position" => "root",
149
+ "X-PathInfo" => env["PATH_INFO"],
150
+ "X-ScriptName" => env["SCRIPT_NAME"]
151
+ }, [""]]},
152
+ "/foo" => lambda { |env|
153
+ [200,
154
+ { "Content-Type" => "text/plain",
155
+ "X-Position" => "foo",
156
+ "X-PathInfo" => env["PATH_INFO"],
157
+ "X-ScriptName" => env["SCRIPT_NAME"]
158
+ }, [""]]}
159
+ )
160
+
161
+ res = Rack::MockRequest.new(map).get("/foo/bar")
162
+ res.should.be.ok
163
+ res["X-Position"].should.equal "foo"
164
+ res["X-PathInfo"].should.equal "/bar"
165
+ res["X-ScriptName"].should.equal "/foo"
166
+
167
+ res = Rack::MockRequest.new(map).get("/foo")
168
+ res.should.be.ok
169
+ res["X-Position"].should.equal "foo"
170
+ res["X-PathInfo"].should.equal ""
171
+ res["X-ScriptName"].should.equal "/foo"
172
+
173
+ res = Rack::MockRequest.new(map).get("/bar")
174
+ res.should.be.ok
175
+ res["X-Position"].should.equal "root"
176
+ res["X-PathInfo"].should.equal "/bar"
177
+ res["X-ScriptName"].should.equal ""
178
+
179
+ res = Rack::MockRequest.new(map).get("")
180
+ res.should.be.ok
181
+ res["X-Position"].should.equal "root"
182
+ res["X-PathInfo"].should.equal "/"
183
+ res["X-ScriptName"].should.equal ""
184
+ end
185
+ end