kastner-rack 0.3.171

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/AUTHORS +8 -0
  2. data/COPYING +18 -0
  3. data/KNOWN-ISSUES +18 -0
  4. data/README +273 -0
  5. data/Rakefile +185 -0
  6. data/bin/rackup +172 -0
  7. data/contrib/rack_logo.svg +111 -0
  8. data/example/lobster.ru +4 -0
  9. data/example/protectedlobster.rb +14 -0
  10. data/example/protectedlobster.ru +8 -0
  11. data/lib/rack.rb +85 -0
  12. data/lib/rack/adapter/camping.rb +22 -0
  13. data/lib/rack/auth/abstract/handler.rb +28 -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 +437 -0
  21. data/lib/rack/builder.rb +67 -0
  22. data/lib/rack/cascade.rb +36 -0
  23. data/lib/rack/commonlogger.rb +61 -0
  24. data/lib/rack/conditionalget.rb +42 -0
  25. data/lib/rack/deflater.rb +63 -0
  26. data/lib/rack/directory.rb +149 -0
  27. data/lib/rack/file.rb +84 -0
  28. data/lib/rack/handler.rb +46 -0
  29. data/lib/rack/handler/cgi.rb +57 -0
  30. data/lib/rack/handler/evented_mongrel.rb +8 -0
  31. data/lib/rack/handler/fastcgi.rb +86 -0
  32. data/lib/rack/handler/lsws.rb +52 -0
  33. data/lib/rack/handler/mongrel.rb +78 -0
  34. data/lib/rack/handler/scgi.rb +57 -0
  35. data/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  36. data/lib/rack/handler/webrick.rb +61 -0
  37. data/lib/rack/head.rb +19 -0
  38. data/lib/rack/lint.rb +463 -0
  39. data/lib/rack/lobster.rb +65 -0
  40. data/lib/rack/methodoverride.rb +21 -0
  41. data/lib/rack/mime.rb +204 -0
  42. data/lib/rack/mock.rb +160 -0
  43. data/lib/rack/recursive.rb +57 -0
  44. data/lib/rack/reloader.rb +64 -0
  45. data/lib/rack/request.rb +217 -0
  46. data/lib/rack/response.rb +171 -0
  47. data/lib/rack/session/abstract/id.rb +140 -0
  48. data/lib/rack/session/cookie.rb +89 -0
  49. data/lib/rack/session/memcache.rb +97 -0
  50. data/lib/rack/session/pool.rb +73 -0
  51. data/lib/rack/showexceptions.rb +348 -0
  52. data/lib/rack/showstatus.rb +105 -0
  53. data/lib/rack/static.rb +38 -0
  54. data/lib/rack/urlmap.rb +48 -0
  55. data/lib/rack/utils.rb +318 -0
  56. data/rack.gemspec +31 -0
  57. data/test/cgi/lighttpd.conf +20 -0
  58. data/test/cgi/test +9 -0
  59. data/test/cgi/test.fcgi +8 -0
  60. data/test/cgi/test.ru +7 -0
  61. data/test/spec_rack_auth_basic.rb +69 -0
  62. data/test/spec_rack_auth_digest.rb +169 -0
  63. data/test/spec_rack_auth_openid.rb +137 -0
  64. data/test/spec_rack_builder.rb +84 -0
  65. data/test/spec_rack_camping.rb +51 -0
  66. data/test/spec_rack_cascade.rb +50 -0
  67. data/test/spec_rack_cgi.rb +89 -0
  68. data/test/spec_rack_commonlogger.rb +32 -0
  69. data/test/spec_rack_conditionalget.rb +41 -0
  70. data/test/spec_rack_deflater.rb +70 -0
  71. data/test/spec_rack_directory.rb +56 -0
  72. data/test/spec_rack_fastcgi.rb +89 -0
  73. data/test/spec_rack_file.rb +57 -0
  74. data/test/spec_rack_handler.rb +24 -0
  75. data/test/spec_rack_head.rb +30 -0
  76. data/test/spec_rack_lint.rb +371 -0
  77. data/test/spec_rack_lobster.rb +45 -0
  78. data/test/spec_rack_methodoverride.rb +31 -0
  79. data/test/spec_rack_mock.rb +152 -0
  80. data/test/spec_rack_mongrel.rb +170 -0
  81. data/test/spec_rack_recursive.rb +77 -0
  82. data/test/spec_rack_request.rb +426 -0
  83. data/test/spec_rack_response.rb +173 -0
  84. data/test/spec_rack_session_cookie.rb +78 -0
  85. data/test/spec_rack_session_memcache.rb +132 -0
  86. data/test/spec_rack_session_pool.rb +84 -0
  87. data/test/spec_rack_showexceptions.rb +21 -0
  88. data/test/spec_rack_showstatus.rb +72 -0
  89. data/test/spec_rack_static.rb +37 -0
  90. data/test/spec_rack_urlmap.rb +175 -0
  91. data/test/spec_rack_utils.rb +174 -0
  92. data/test/spec_rack_webrick.rb +123 -0
  93. data/test/testrequest.rb +45 -0
  94. metadata +177 -0
@@ -0,0 +1,78 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/session/cookie'
4
+ require 'rack/mock'
5
+ require 'rack/response'
6
+
7
+ context "Rack::Session::Cookie" do
8
+ incrementor = lambda { |env|
9
+ env["rack.session"]["counter"] ||= 0
10
+ env["rack.session"]["counter"] += 1
11
+ Rack::Response.new(env["rack.session"].inspect).to_a
12
+ }
13
+
14
+ specify "creates a new cookie" do
15
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/")
16
+ res["Set-Cookie"].should.match("rack.session=")
17
+ res.body.should.equal '{"counter"=>1}'
18
+ end
19
+
20
+ specify "loads from a cookie" do
21
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/")
22
+ cookie = res["Set-Cookie"]
23
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
24
+ get("/", "HTTP_COOKIE" => cookie)
25
+ res.body.should.equal '{"counter"=>2}'
26
+ cookie = res["Set-Cookie"]
27
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
28
+ get("/", "HTTP_COOKIE" => cookie)
29
+ res.body.should.equal '{"counter"=>3}'
30
+ end
31
+
32
+ specify "survives broken cookies" do
33
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
34
+ get("/", "HTTP_COOKIE" => "rack.session=blarghfasel")
35
+ res.body.should.equal '{"counter"=>1}'
36
+ end
37
+
38
+ bigcookie = lambda { |env|
39
+ env["rack.session"]["cookie"] = "big" * 3000
40
+ Rack::Response.new(env["rack.session"].inspect).to_a
41
+ }
42
+
43
+ specify "barks on too big cookies" do
44
+ lambda {
45
+ Rack::MockRequest.new(Rack::Session::Cookie.new(bigcookie)).
46
+ get("/", :fatal => true)
47
+ }.should.raise(Rack::MockRequest::FatalWarning)
48
+ end
49
+
50
+ specify "creates a new cookie with integrity hash" do
51
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).get("/")
52
+ res["Set-Cookie"].should.match("rack.session=BAh7BiIMY291bnRlcmkG%0A--1439b4d37b9d4b04c603848382f712d6fcd31088")
53
+ end
54
+
55
+ specify "loads from a cookie wih integrity hash" do
56
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).get("/")
57
+ cookie = res["Set-Cookie"]
58
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).
59
+ get("/", "HTTP_COOKIE" => cookie)
60
+ res.body.should.equal '{"counter"=>2}'
61
+ cookie = res["Set-Cookie"]
62
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).
63
+ get("/", "HTTP_COOKIE" => cookie)
64
+ res.body.should.equal '{"counter"=>3}'
65
+ end
66
+
67
+ specify "ignores tampered with session cookies" do
68
+ app = Rack::Session::Cookie.new(incrementor, :secret => 'test')
69
+ response1 = Rack::MockRequest.new(app).get("/")
70
+ _, digest = response1["Set-Cookie"].split("--")
71
+ tampered_with_cookie = "hackerman-was-here" + "--" + digest
72
+ response2 = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" =>
73
+ tampered_with_cookie)
74
+
75
+ # The tampered-with cookie is ignored, so we get back an identical Set-Cookie
76
+ response2["Set-Cookie"].should.equal(response1["Set-Cookie"])
77
+ end
78
+ end
@@ -0,0 +1,132 @@
1
+ require 'test/spec'
2
+
3
+ begin
4
+ require 'rack/session/memcache'
5
+ require 'rack/mock'
6
+ require 'rack/response'
7
+ require 'thread'
8
+
9
+ context "Rack::Session::Memcache" do
10
+ incrementor = lambda { |env|
11
+ env["rack.session"]["counter"] ||= 0
12
+ env["rack.session"]["counter"] += 1
13
+ Rack::Response.new(env["rack.session"].inspect).to_a
14
+ }
15
+
16
+ # Keep this first.
17
+ specify "startup" do
18
+ $pid = fork {
19
+ exec "memcached"
20
+ }
21
+ sleep 1
22
+ end
23
+
24
+ specify "faults on no connection" do
25
+ lambda do
26
+ Rack::Session::Memcache.new(incrementor, :memcache_server => '')
27
+ end.should.raise
28
+ end
29
+
30
+ specify "creates a new cookie" do
31
+ cache = Rack::Session::Memcache.new(incrementor)
32
+ res = Rack::MockRequest.new(cache).get("/")
33
+ res["Set-Cookie"].should.match("rack.session=")
34
+ res.body.should.equal '{"counter"=>1}'
35
+ end
36
+
37
+ specify "determines session from a cookie" do
38
+ cache = Rack::Session::Memcache.new(incrementor)
39
+ res = Rack::MockRequest.new(cache).get("/")
40
+ cookie = res["Set-Cookie"]
41
+ res = Rack::MockRequest.new(cache).get("/", "HTTP_COOKIE" => cookie)
42
+ res.body.should.equal '{"counter"=>2}'
43
+ res = Rack::MockRequest.new(cache).get("/", "HTTP_COOKIE" => cookie)
44
+ res.body.should.equal '{"counter"=>3}'
45
+ end
46
+
47
+ specify "survives broken cookies" do
48
+ cache = Rack::Session::Memcache.new(incrementor)
49
+ res = Rack::MockRequest.new(cache).
50
+ get("/", "HTTP_COOKIE" => "rack.session=blarghfasel")
51
+ res.body.should.equal '{"counter"=>1}'
52
+ end
53
+
54
+ specify "maintains freshness" do
55
+ cache = Rack::Session::Memcache.new(incrementor, :expire_after => 3)
56
+ res = Rack::MockRequest.new(cache).get('/')
57
+ res.body.should.include '"counter"=>1'
58
+ cookie = res["Set-Cookie"]
59
+ res = Rack::MockRequest.new(cache).get('/', "HTTP_COOKIE" => cookie)
60
+ res["Set-Cookie"].should.equal cookie
61
+ res.body.should.include '"counter"=>2'
62
+ puts 'Sleeping to expire session' if $DEBUG
63
+ sleep 4
64
+ res = Rack::MockRequest.new(cache).get('/', "HTTP_COOKIE" => cookie)
65
+ res["Set-Cookie"].should.not.equal cookie
66
+ res.body.should.include '"counter"=>1'
67
+ end
68
+
69
+ specify "multithread: should cleanly merge sessions" do
70
+ cache = Rack::Session::Memcache.new(incrementor)
71
+ drop_counter = Rack::Session::Memcache.new(proc do |env|
72
+ env['rack.session'].delete 'counter'
73
+ env['rack.session']['foo'] = 'bar'
74
+ [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect]
75
+ end)
76
+
77
+ res = Rack::MockRequest.new(cache).get('/')
78
+ res.body.should.equal '{"counter"=>1}'
79
+ cookie = res["Set-Cookie"]
80
+ sess_id = cookie[/#{cache.key}=([^,;]+)/, 1]
81
+
82
+ res = Rack::MockRequest.new(cache).get('/', "HTTP_COOKIE" => cookie)
83
+ res.body.should.equal '{"counter"=>2}'
84
+
85
+ r = Array.new(rand(7).to_i+2) do |i|
86
+ app = proc do |env|
87
+ env['rack.session'][i] = Time.now
88
+ sleep 2
89
+ env['rack.session'] = env['rack.session'].dup
90
+ env['rack.session'][i] -= Time.now
91
+ incrementor.call(env)
92
+ end
93
+ Thread.new(cache.context(app)) do |run|
94
+ Rack::MockRequest.new(run).
95
+ get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
96
+ end
97
+ end
98
+
99
+ r.reverse!
100
+
101
+ r.map! do |t|
102
+ p t if $DEBUG
103
+ t.join.value
104
+ end
105
+
106
+ r.each do |res|
107
+ res['Set-Cookie'].should.equal cookie
108
+ res.body.should.include '"counter"=>3'
109
+ end
110
+
111
+ session = cache.pool[sess_id]
112
+ session.size.should.be r.size+1
113
+ session['counter'].should.be 3
114
+
115
+ res = Rack::MockRequest.new(drop_counter).get('/', "HTTP_COOKIE" => cookie)
116
+ res.body.should.include '"foo"=>"bar"'
117
+
118
+ session = cache.pool[sess_id]
119
+ session.size.should.be r.size+1
120
+ session['counter'].should.be.nil?
121
+ session['foo'].should.equal 'bar'
122
+ end
123
+
124
+ # Keep this last.
125
+ specify "shutdown" do
126
+ Process.kill 15, $pid
127
+ Process.wait($pid).should.equal $pid
128
+ end
129
+ end
130
+ rescue LoadError
131
+ $stderr.puts "Skipping Rack::Session::Memcache tests (Memcache is required). `gem install memcache-client` and try again."
132
+ end
@@ -0,0 +1,84 @@
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
+ incrementor = lambda { |env|
10
+ env["rack.session"]["counter"] ||= 0
11
+ env["rack.session"]["counter"] += 1
12
+ Rack::Response.new(env["rack.session"].inspect).to_a
13
+ }
14
+
15
+ specify "creates a new cookie" do
16
+ pool = Rack::Session::Pool.new(incrementor)
17
+ res = Rack::MockRequest.new(pool).get("/")
18
+ res["Set-Cookie"].should.match("rack.session=")
19
+ res.body.should.equal '{"counter"=>1}'
20
+ end
21
+
22
+ specify "determines session from a cookie" do
23
+ pool = Rack::Session::Pool.new(incrementor)
24
+ res = Rack::MockRequest.new(pool).get("/")
25
+ cookie = res["Set-Cookie"]
26
+ res = Rack::MockRequest.new(pool).get("/", "HTTP_COOKIE" => cookie)
27
+ res.body.should.equal '{"counter"=>2}'
28
+ res = Rack::MockRequest.new(pool).get("/", "HTTP_COOKIE" => cookie)
29
+ res.body.should.equal '{"counter"=>3}'
30
+ end
31
+
32
+ specify "survives broken cookies" do
33
+ pool = Rack::Session::Pool.new(incrementor)
34
+ res = Rack::MockRequest.new(pool).
35
+ get("/", "HTTP_COOKIE" => "rack.session=blarghfasel")
36
+ res.body.should.equal '{"counter"=>1}'
37
+ end
38
+
39
+ specify "maintains freshness" do
40
+ pool = Rack::Session::Pool.new(incrementor, :expire_after => 3)
41
+ res = Rack::MockRequest.new(pool).get('/')
42
+ res.body.should.include '"counter"=>1'
43
+ cookie = res["Set-Cookie"]
44
+ res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
45
+ res["Set-Cookie"].should.equal cookie
46
+ res.body.should.include '"counter"=>2'
47
+ sleep 4
48
+ res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
49
+ res["Set-Cookie"].should.not.equal cookie
50
+ res.body.should.include '"counter"=>1'
51
+ end
52
+
53
+ specify "multithread: should merge sessions" do
54
+ delta_incrementor = lambda do |env|
55
+ # emulate disconjoinment of threading
56
+ env['rack.session'] = env['rack.session'].dup
57
+ Thread.stop
58
+ env['rack.session'][(Time.now.usec*rand).to_i] = true
59
+ incrementor.call(env)
60
+ end
61
+ pool = Rack::Session::Pool.new(incrementor)
62
+ res = Rack::MockRequest.new(pool).get('/')
63
+ res.body.should.equal '{"counter"=>1}'
64
+ cookie = res["Set-Cookie"]
65
+ sess_id = cookie[/#{pool.key}=([^,;]+)/,1]
66
+
67
+ pool = pool.context(delta_incrementor)
68
+ r = Array.new(rand(7).to_i+3).
69
+ map! do
70
+ Thread.new do
71
+ Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
72
+ end
73
+ end.
74
+ reverse!.
75
+ map!{|t| t.run.join.value }
76
+ session = pool.for.pool[sess_id] # for is needed by Utils::Context
77
+ session.size.should.be r.size+1 # counter
78
+ session['counter'].should.be 2 # meeeh
79
+ r.each do |res|
80
+ res['Set-Cookie'].should.equal cookie
81
+ res.body.should.include '"counter"=>2'
82
+ end
83
+ end
84
+ 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,175 @@
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://bar.org/" => lambda { |env|
72
+ [200,
73
+ { "Content-Type" => "text/plain",
74
+ "X-Position" => "bar.org",
75
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
76
+ }, [""]]},
77
+ "/" => lambda { |env|
78
+ [200,
79
+ { "Content-Type" => "text/plain",
80
+ "X-Position" => "default.org",
81
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
82
+ }, [""]]}
83
+ )
84
+
85
+ res = Rack::MockRequest.new(map).get("/")
86
+ res.should.be.ok
87
+ res["X-Position"].should.equal "default.org"
88
+
89
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org")
90
+ res.should.be.ok
91
+ res["X-Position"].should.equal "bar.org"
92
+
93
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org")
94
+ res.should.be.ok
95
+ res["X-Position"].should.equal "foo.org"
96
+
97
+ res = Rack::MockRequest.new(map).get("http://foo.org/")
98
+ res.should.be.ok
99
+ res["X-Position"].should.equal "default.org"
100
+
101
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org")
102
+ res.should.be.ok
103
+ res["X-Position"].should.equal "default.org"
104
+
105
+ res = Rack::MockRequest.new(map).get("/",
106
+ "HTTP_HOST" => "example.org:9292",
107
+ "SERVER_PORT" => "9292")
108
+ res.should.be.ok
109
+ res["X-Position"].should.equal "default.org"
110
+ end
111
+
112
+ specify "should be nestable" do
113
+ map = Rack::URLMap.new("/foo" =>
114
+ Rack::URLMap.new("/bar" =>
115
+ Rack::URLMap.new("/quux" => lambda { |env|
116
+ [200,
117
+ { "Content-Type" => "text/plain",
118
+ "X-Position" => "/foo/bar/quux",
119
+ "X-PathInfo" => env["PATH_INFO"],
120
+ "X-ScriptName" => env["SCRIPT_NAME"],
121
+ }, [""]]}
122
+ )))
123
+
124
+ res = Rack::MockRequest.new(map).get("/foo/bar")
125
+ res.should.be.not_found
126
+
127
+ res = Rack::MockRequest.new(map).get("/foo/bar/quux")
128
+ res.should.be.ok
129
+ res["X-Position"].should.equal "/foo/bar/quux"
130
+ res["X-PathInfo"].should.equal ""
131
+ res["X-ScriptName"].should.equal "/foo/bar/quux"
132
+ end
133
+
134
+ specify "should route root apps correctly" do
135
+ map = Rack::URLMap.new("/" => lambda { |env|
136
+ [200,
137
+ { "Content-Type" => "text/plain",
138
+ "X-Position" => "root",
139
+ "X-PathInfo" => env["PATH_INFO"],
140
+ "X-ScriptName" => env["SCRIPT_NAME"]
141
+ }, [""]]},
142
+ "/foo" => lambda { |env|
143
+ [200,
144
+ { "Content-Type" => "text/plain",
145
+ "X-Position" => "foo",
146
+ "X-PathInfo" => env["PATH_INFO"],
147
+ "X-ScriptName" => env["SCRIPT_NAME"]
148
+ }, [""]]}
149
+ )
150
+
151
+ res = Rack::MockRequest.new(map).get("/foo/bar")
152
+ res.should.be.ok
153
+ res["X-Position"].should.equal "foo"
154
+ res["X-PathInfo"].should.equal "/bar"
155
+ res["X-ScriptName"].should.equal "/foo"
156
+
157
+ res = Rack::MockRequest.new(map).get("/foo")
158
+ res.should.be.ok
159
+ res["X-Position"].should.equal "foo"
160
+ res["X-PathInfo"].should.equal ""
161
+ res["X-ScriptName"].should.equal "/foo"
162
+
163
+ res = Rack::MockRequest.new(map).get("/bar")
164
+ res.should.be.ok
165
+ res["X-Position"].should.equal "root"
166
+ res["X-PathInfo"].should.equal "/bar"
167
+ res["X-ScriptName"].should.equal ""
168
+
169
+ res = Rack::MockRequest.new(map).get("")
170
+ res.should.be.ok
171
+ res["X-Position"].should.equal "root"
172
+ res["X-PathInfo"].should.equal "/"
173
+ res["X-ScriptName"].should.equal ""
174
+ end
175
+ end