edgar-rack 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. data/COPYING +18 -0
  2. data/KNOWN-ISSUES +21 -0
  3. data/README +401 -0
  4. data/Rakefile +101 -0
  5. data/SPEC +171 -0
  6. data/bin/rackup +4 -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 +81 -0
  12. data/lib/rack/auth/abstract/handler.rb +37 -0
  13. data/lib/rack/auth/abstract/request.rb +43 -0
  14. data/lib/rack/auth/basic.rb +58 -0
  15. data/lib/rack/auth/digest/md5.rb +124 -0
  16. data/lib/rack/auth/digest/nonce.rb +51 -0
  17. data/lib/rack/auth/digest/params.rb +53 -0
  18. data/lib/rack/auth/digest/request.rb +40 -0
  19. data/lib/rack/builder.rb +80 -0
  20. data/lib/rack/cascade.rb +41 -0
  21. data/lib/rack/chunked.rb +52 -0
  22. data/lib/rack/commonlogger.rb +49 -0
  23. data/lib/rack/conditionalget.rb +63 -0
  24. data/lib/rack/config.rb +15 -0
  25. data/lib/rack/content_length.rb +29 -0
  26. data/lib/rack/content_type.rb +23 -0
  27. data/lib/rack/deflater.rb +96 -0
  28. data/lib/rack/directory.rb +157 -0
  29. data/lib/rack/etag.rb +59 -0
  30. data/lib/rack/file.rb +118 -0
  31. data/lib/rack/handler.rb +88 -0
  32. data/lib/rack/handler/cgi.rb +61 -0
  33. data/lib/rack/handler/evented_mongrel.rb +8 -0
  34. data/lib/rack/handler/fastcgi.rb +90 -0
  35. data/lib/rack/handler/lsws.rb +61 -0
  36. data/lib/rack/handler/mongrel.rb +90 -0
  37. data/lib/rack/handler/scgi.rb +59 -0
  38. data/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  39. data/lib/rack/handler/thin.rb +17 -0
  40. data/lib/rack/handler/webrick.rb +73 -0
  41. data/lib/rack/head.rb +19 -0
  42. data/lib/rack/lint.rb +567 -0
  43. data/lib/rack/lobster.rb +65 -0
  44. data/lib/rack/lock.rb +44 -0
  45. data/lib/rack/logger.rb +18 -0
  46. data/lib/rack/methodoverride.rb +27 -0
  47. data/lib/rack/mime.rb +210 -0
  48. data/lib/rack/mock.rb +185 -0
  49. data/lib/rack/nulllogger.rb +18 -0
  50. data/lib/rack/recursive.rb +61 -0
  51. data/lib/rack/reloader.rb +109 -0
  52. data/lib/rack/request.rb +307 -0
  53. data/lib/rack/response.rb +151 -0
  54. data/lib/rack/rewindable_input.rb +104 -0
  55. data/lib/rack/runtime.rb +27 -0
  56. data/lib/rack/sendfile.rb +139 -0
  57. data/lib/rack/server.rb +289 -0
  58. data/lib/rack/session/abstract/id.rb +348 -0
  59. data/lib/rack/session/cookie.rb +152 -0
  60. data/lib/rack/session/memcache.rb +93 -0
  61. data/lib/rack/session/pool.rb +79 -0
  62. data/lib/rack/showexceptions.rb +378 -0
  63. data/lib/rack/showstatus.rb +113 -0
  64. data/lib/rack/static.rb +53 -0
  65. data/lib/rack/urlmap.rb +55 -0
  66. data/lib/rack/utils.rb +698 -0
  67. data/rack.gemspec +39 -0
  68. data/test/cgi/lighttpd.conf +25 -0
  69. data/test/cgi/rackup_stub.rb +6 -0
  70. data/test/cgi/sample_rackup.ru +5 -0
  71. data/test/cgi/test +9 -0
  72. data/test/cgi/test.fcgi +8 -0
  73. data/test/cgi/test.ru +5 -0
  74. data/test/gemloader.rb +6 -0
  75. data/test/multipart/bad_robots +259 -0
  76. data/test/multipart/binary +0 -0
  77. data/test/multipart/empty +10 -0
  78. data/test/multipart/fail_16384_nofile +814 -0
  79. data/test/multipart/file1.txt +1 -0
  80. data/test/multipart/filename_and_modification_param +7 -0
  81. data/test/multipart/filename_with_escaped_quotes +6 -0
  82. data/test/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
  83. data/test/multipart/filename_with_percent_escaped_quotes +6 -0
  84. data/test/multipart/filename_with_unescaped_quotes +6 -0
  85. data/test/multipart/ie +6 -0
  86. data/test/multipart/nested +10 -0
  87. data/test/multipart/none +9 -0
  88. data/test/multipart/semicolon +6 -0
  89. data/test/multipart/text +15 -0
  90. data/test/rackup/config.ru +31 -0
  91. data/test/spec_auth_basic.rb +70 -0
  92. data/test/spec_auth_digest.rb +241 -0
  93. data/test/spec_builder.rb +123 -0
  94. data/test/spec_cascade.rb +45 -0
  95. data/test/spec_cgi.rb +102 -0
  96. data/test/spec_chunked.rb +60 -0
  97. data/test/spec_commonlogger.rb +56 -0
  98. data/test/spec_conditionalget.rb +86 -0
  99. data/test/spec_config.rb +23 -0
  100. data/test/spec_content_length.rb +36 -0
  101. data/test/spec_content_type.rb +29 -0
  102. data/test/spec_deflater.rb +125 -0
  103. data/test/spec_directory.rb +57 -0
  104. data/test/spec_etag.rb +75 -0
  105. data/test/spec_fastcgi.rb +107 -0
  106. data/test/spec_file.rb +92 -0
  107. data/test/spec_handler.rb +49 -0
  108. data/test/spec_head.rb +30 -0
  109. data/test/spec_lint.rb +515 -0
  110. data/test/spec_lobster.rb +43 -0
  111. data/test/spec_lock.rb +142 -0
  112. data/test/spec_logger.rb +28 -0
  113. data/test/spec_methodoverride.rb +58 -0
  114. data/test/spec_mock.rb +241 -0
  115. data/test/spec_mongrel.rb +182 -0
  116. data/test/spec_nulllogger.rb +12 -0
  117. data/test/spec_recursive.rb +69 -0
  118. data/test/spec_request.rb +774 -0
  119. data/test/spec_response.rb +245 -0
  120. data/test/spec_rewindable_input.rb +118 -0
  121. data/test/spec_runtime.rb +39 -0
  122. data/test/spec_sendfile.rb +83 -0
  123. data/test/spec_server.rb +8 -0
  124. data/test/spec_session_abstract_id.rb +43 -0
  125. data/test/spec_session_cookie.rb +171 -0
  126. data/test/spec_session_memcache.rb +289 -0
  127. data/test/spec_session_pool.rb +200 -0
  128. data/test/spec_showexceptions.rb +87 -0
  129. data/test/spec_showstatus.rb +79 -0
  130. data/test/spec_static.rb +48 -0
  131. data/test/spec_thin.rb +86 -0
  132. data/test/spec_urlmap.rb +213 -0
  133. data/test/spec_utils.rb +678 -0
  134. data/test/spec_webrick.rb +141 -0
  135. data/test/testrequest.rb +78 -0
  136. data/test/unregistered_handler/rack/handler/unregistered.rb +7 -0
  137. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
  138. metadata +329 -0
@@ -0,0 +1,200 @@
1
+ require 'thread'
2
+ require 'rack/mock'
3
+ require 'rack/session/pool'
4
+
5
+ describe Rack::Session::Pool do
6
+ session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key]
7
+ session_match = /#{session_key}=[0-9a-fA-F]+;/
8
+
9
+ incrementor = lambda do |env|
10
+ env["rack.session"]["counter"] ||= 0
11
+ env["rack.session"]["counter"] += 1
12
+ Rack::Response.new(env["rack.session"].inspect).to_a
13
+ end
14
+
15
+ session_id = lambda do |env|
16
+ Rack::Response.new(env["rack.session"].inspect).to_a
17
+ end
18
+
19
+ nothing = lambda do |env|
20
+ Rack::Response.new("Nothing").to_a
21
+ end
22
+
23
+ drop_session = lambda do |env|
24
+ env['rack.session.options'][:drop] = true
25
+ incrementor.call(env)
26
+ end
27
+
28
+ renew_session = lambda do |env|
29
+ env['rack.session.options'][:renew] = true
30
+ incrementor.call(env)
31
+ end
32
+
33
+ defer_session = lambda do |env|
34
+ env['rack.session.options'][:defer] = true
35
+ incrementor.call(env)
36
+ end
37
+
38
+ it "creates a new cookie" do
39
+ pool = Rack::Session::Pool.new(incrementor)
40
+ res = Rack::MockRequest.new(pool).get("/")
41
+ res["Set-Cookie"].should.match session_match
42
+ res.body.should.equal '{"counter"=>1}'
43
+ end
44
+
45
+ it "determines session from a cookie" do
46
+ pool = Rack::Session::Pool.new(incrementor)
47
+ req = Rack::MockRequest.new(pool)
48
+ cookie = req.get("/")["Set-Cookie"]
49
+ req.get("/", "HTTP_COOKIE" => cookie).
50
+ body.should.equal '{"counter"=>2}'
51
+ req.get("/", "HTTP_COOKIE" => cookie).
52
+ body.should.equal '{"counter"=>3}'
53
+ end
54
+
55
+ it "survives nonexistant cookies" do
56
+ pool = Rack::Session::Pool.new(incrementor)
57
+ res = Rack::MockRequest.new(pool).
58
+ get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel")
59
+ res.body.should.equal '{"counter"=>1}'
60
+ end
61
+
62
+ it "does not send the same session id if it did not change" do
63
+ pool = Rack::Session::Pool.new(incrementor)
64
+ req = Rack::MockRequest.new(pool)
65
+
66
+ res0 = req.get("/")
67
+ cookie = res0["Set-Cookie"][session_match]
68
+ res0.body.should.equal '{"counter"=>1}'
69
+ pool.pool.size.should.equal 1
70
+
71
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
72
+ res1["Set-Cookie"].should.be.nil
73
+ res1.body.should.equal '{"counter"=>2}'
74
+ pool.pool.size.should.equal 1
75
+
76
+ res2 = req.get("/", "HTTP_COOKIE" => cookie)
77
+ res2["Set-Cookie"].should.be.nil
78
+ res2.body.should.equal '{"counter"=>3}'
79
+ pool.pool.size.should.equal 1
80
+ end
81
+
82
+ it "deletes cookies with :drop option" do
83
+ pool = Rack::Session::Pool.new(incrementor)
84
+ req = Rack::MockRequest.new(pool)
85
+ drop = Rack::Utils::Context.new(pool, drop_session)
86
+ dreq = Rack::MockRequest.new(drop)
87
+
88
+ res1 = req.get("/")
89
+ session = (cookie = res1["Set-Cookie"])[session_match]
90
+ res1.body.should.equal '{"counter"=>1}'
91
+ pool.pool.size.should.equal 1
92
+
93
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
94
+ res2["Set-Cookie"].should.be.nil
95
+ res2.body.should.equal '{"counter"=>2}'
96
+ pool.pool.size.should.equal 0
97
+
98
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
99
+ res3["Set-Cookie"][session_match].should.not.equal session
100
+ res3.body.should.equal '{"counter"=>1}'
101
+ pool.pool.size.should.equal 1
102
+ end
103
+
104
+ it "provides new session id with :renew option" do
105
+ pool = Rack::Session::Pool.new(incrementor)
106
+ req = Rack::MockRequest.new(pool)
107
+ renew = Rack::Utils::Context.new(pool, renew_session)
108
+ rreq = Rack::MockRequest.new(renew)
109
+
110
+ res1 = req.get("/")
111
+ session = (cookie = res1["Set-Cookie"])[session_match]
112
+ res1.body.should.equal '{"counter"=>1}'
113
+ pool.pool.size.should.equal 1
114
+
115
+ res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
116
+ new_cookie = res2["Set-Cookie"]
117
+ new_session = new_cookie[session_match]
118
+ new_session.should.not.equal session
119
+ res2.body.should.equal '{"counter"=>2}'
120
+ pool.pool.size.should.equal 1
121
+
122
+ res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
123
+ res3.body.should.equal '{"counter"=>3}'
124
+ pool.pool.size.should.equal 1
125
+
126
+ res4 = req.get("/", "HTTP_COOKIE" => cookie)
127
+ res4.body.should.equal '{"counter"=>1}'
128
+ pool.pool.size.should.equal 2
129
+ end
130
+
131
+ it "omits cookie with :defer option" do
132
+ pool = Rack::Session::Pool.new(incrementor)
133
+ defer = Rack::Utils::Context.new(pool, defer_session)
134
+ dreq = Rack::MockRequest.new(defer)
135
+
136
+ res1 = dreq.get("/")
137
+ res1["Set-Cookie"].should.equal nil
138
+ res1.body.should.equal '{"counter"=>1}'
139
+ pool.pool.size.should.equal 1
140
+ end
141
+
142
+ # anyone know how to do this better?
143
+ it "should merge sessions when multithreaded" do
144
+ unless $DEBUG
145
+ 1.should.equal 1
146
+ next
147
+ end
148
+
149
+ warn 'Running multithread tests for Session::Pool'
150
+ pool = Rack::Session::Pool.new(incrementor)
151
+ req = Rack::MockRequest.new(pool)
152
+
153
+ res = req.get('/')
154
+ res.body.should.equal '{"counter"=>1}'
155
+ cookie = res["Set-Cookie"]
156
+ sess_id = cookie[/#{pool.key}=([^,;]+)/,1]
157
+
158
+ delta_incrementor = lambda do |env|
159
+ # emulate disconjoinment of threading
160
+ env['rack.session'] = env['rack.session'].dup
161
+ Thread.stop
162
+ env['rack.session'][(Time.now.usec*rand).to_i] = true
163
+ incrementor.call(env)
164
+ end
165
+ tses = Rack::Utils::Context.new pool, delta_incrementor
166
+ treq = Rack::MockRequest.new(tses)
167
+ tnum = rand(7).to_i+5
168
+ r = Array.new(tnum) do
169
+ Thread.new(treq) do |run|
170
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
171
+ end
172
+ end.reverse.map{|t| t.run.join.value }
173
+ r.each do |resp|
174
+ resp['Set-Cookie'].should.equal cookie
175
+ resp.body.should.include '"counter"=>2'
176
+ end
177
+
178
+ session = pool.pool[sess_id]
179
+ session.size.should.equal tnum+1 # counter
180
+ session['counter'].should.equal 2 # meeeh
181
+ end
182
+
183
+ it "does not return a cookie if cookie was not read/written" do
184
+ app = Rack::Session::Cookie.new(nothing)
185
+ res = Rack::MockRequest.new(app).get("/")
186
+ res["Set-Cookie"].should.be.nil
187
+ end
188
+
189
+ it "does not return a cookie if cookie was not written (only read)" do
190
+ app = Rack::Session::Cookie.new(session_id)
191
+ res = Rack::MockRequest.new(app).get("/")
192
+ res["Set-Cookie"].should.be.nil
193
+ end
194
+
195
+ it "returns even if not read/written if :expire_after is set" do
196
+ app = Rack::Session::Cookie.new(nothing, :expire_after => 3600)
197
+ res = Rack::MockRequest.new(app).get("/")
198
+ res["Set-Cookie"].should.not.be.nil
199
+ end
200
+ end
@@ -0,0 +1,87 @@
1
+ require 'rack/showexceptions'
2
+ require 'rack/mock'
3
+
4
+ describe Rack::ShowExceptions do
5
+ it "catches exceptions" do
6
+ res = nil
7
+
8
+ req = Rack::MockRequest.new(
9
+ Rack::ShowExceptions.new(
10
+ lambda{|env| raise RuntimeError }
11
+ ))
12
+
13
+ lambda{
14
+ res = req.get("/")
15
+ }.should.not.raise
16
+
17
+ res.should.be.a.server_error
18
+ res.status.should.equal 500
19
+
20
+ res.should =~ /RuntimeError/
21
+ res.should =~ /ShowExceptions/
22
+ end
23
+
24
+ it "responds with plain text on AJAX requests accepting anything but HTML" do
25
+ res = nil
26
+
27
+ req = Rack::MockRequest.new(
28
+ Rack::ShowExceptions.new(
29
+ lambda{|env| raise RuntimeError, "It was never supposed to work" }
30
+ ))
31
+
32
+ lambda{
33
+ res = req.get("/", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest")
34
+ }.should.not.raise
35
+
36
+ res.should.be.a.server_error
37
+ res.status.should.equal 500
38
+
39
+ res.content_type.should.equal "text/plain"
40
+
41
+ res.body.should.include "RuntimeError: It was never supposed to work\n"
42
+ res.body.should.include __FILE__
43
+ end
44
+
45
+ it "responds with HTML on AJAX requests accepting HTML" do
46
+ res = nil
47
+
48
+ req = Rack::MockRequest.new(
49
+ Rack::ShowExceptions.new(
50
+ lambda{|env| raise RuntimeError, "It was never supposed to work" }
51
+ ))
52
+
53
+ lambda{
54
+ res = req.get("/", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest", "HTTP_ACCEPT" => "text/html")
55
+ }.should.not.raise
56
+
57
+ res.should.be.a.server_error
58
+ res.status.should.equal 500
59
+
60
+ res.content_type.should.equal "text/html"
61
+
62
+ res.body.should.include "RuntimeError"
63
+ res.body.should.include "It was never supposed to work"
64
+ res.body.should.include Rack::Utils.escape_html(__FILE__)
65
+ end
66
+
67
+ it "handles exceptions without a backtrace" do
68
+ res = nil
69
+
70
+ req = Rack::MockRequest.new(
71
+ Rack::ShowExceptions.new(
72
+ lambda{|env| raise RuntimeError, "", [] }
73
+ )
74
+ )
75
+
76
+ lambda{
77
+ res = req.get("/")
78
+ }.should.not.raise
79
+
80
+ res.should.be.a.server_error
81
+ res.status.should.equal 500
82
+
83
+ res.should =~ /RuntimeError/
84
+ res.should =~ /ShowExceptions/
85
+ res.should =~ /unknown location/
86
+ end
87
+ end
@@ -0,0 +1,79 @@
1
+ require 'rack/showstatus'
2
+ require 'rack/mock'
3
+
4
+ describe Rack::ShowStatus do
5
+ should "provide a default status message" do
6
+ req = Rack::MockRequest.new(
7
+ Rack::ShowStatus.new(lambda{|env|
8
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
9
+ }))
10
+
11
+ res = req.get("/", :lint => true)
12
+ res.should.be.not_found
13
+ res.should.be.not.empty
14
+
15
+ res["Content-Type"].should.equal("text/html")
16
+ res.should =~ /404/
17
+ res.should =~ /Not Found/
18
+ end
19
+
20
+ should "let the app provide additional information" do
21
+ req = Rack::MockRequest.new(
22
+ Rack::ShowStatus.new(
23
+ lambda{|env|
24
+ env["rack.showstatus.detail"] = "gone too meta."
25
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
26
+ }))
27
+
28
+ res = req.get("/", :lint => true)
29
+ res.should.be.not_found
30
+ res.should.be.not.empty
31
+
32
+ res["Content-Type"].should.equal("text/html")
33
+ res.should =~ /404/
34
+ res.should =~ /Not Found/
35
+ res.should =~ /too meta/
36
+ end
37
+
38
+ should "not replace existing messages" do
39
+ req = Rack::MockRequest.new(
40
+ Rack::ShowStatus.new(
41
+ lambda{|env|
42
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
43
+ }))
44
+
45
+ res = req.get("/", :lint => true)
46
+ res.should.be.not_found
47
+
48
+ res.body.should == "foo!"
49
+ end
50
+
51
+ should "pass on original headers" do
52
+ headers = {"WWW-Authenticate" => "Basic blah"}
53
+
54
+ req = Rack::MockRequest.new(
55
+ Rack::ShowStatus.new(lambda{|env| [401, headers, []] }))
56
+ res = req.get("/", :lint => true)
57
+
58
+ res["WWW-Authenticate"].should.equal("Basic blah")
59
+ end
60
+
61
+ should "replace existing messages if there is detail" do
62
+ req = Rack::MockRequest.new(
63
+ Rack::ShowStatus.new(
64
+ lambda{|env|
65
+ env["rack.showstatus.detail"] = "gone too meta."
66
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
67
+ }))
68
+
69
+ res = req.get("/", :lint => true)
70
+ res.should.be.not_found
71
+ res.should.be.not.empty
72
+
73
+ res["Content-Type"].should.equal("text/html")
74
+ res["Content-Length"].should.not.equal("4")
75
+ res.should =~ /404/
76
+ res.should =~ /too meta/
77
+ res.body.should.not =~ /foo/
78
+ end
79
+ end
@@ -0,0 +1,48 @@
1
+ require 'rack/static'
2
+ require 'rack/mock'
3
+
4
+ class DummyApp
5
+ def call(env)
6
+ [200, {}, ["Hello World"]]
7
+ end
8
+ end
9
+
10
+ describe Rack::Static do
11
+ root = File.expand_path(File.dirname(__FILE__))
12
+
13
+ OPTIONS = {:urls => ["/cgi"], :root => root}
14
+ HASH_OPTIONS = {:urls => {"/cgi/sekret" => 'cgi/test'}, :root => root}
15
+
16
+ @request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, OPTIONS))
17
+ @hash_request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, HASH_OPTIONS))
18
+
19
+ it "serves files" do
20
+ res = @request.get("/cgi/test")
21
+ res.should.be.ok
22
+ res.body.should =~ /ruby/
23
+ end
24
+
25
+ it "404s if url root is known but it can't find the file" do
26
+ res = @request.get("/cgi/foo")
27
+ res.should.be.not_found
28
+ end
29
+
30
+ it "calls down the chain if url root is not known" do
31
+ res = @request.get("/something/else")
32
+ res.should.be.ok
33
+ res.body.should == "Hello World"
34
+ end
35
+
36
+ it "serves hidden files" do
37
+ res = @hash_request.get("/cgi/sekret")
38
+ res.should.be.ok
39
+ res.body.should =~ /ruby/
40
+ end
41
+
42
+ it "calls down the chain if the URI is not specified" do
43
+ res = @hash_request.get("/something/else")
44
+ res.should.be.ok
45
+ res.body.should == "Hello World"
46
+ end
47
+
48
+ end
@@ -0,0 +1,86 @@
1
+ begin
2
+ require 'rack/handler/thin'
3
+ require File.expand_path('../testrequest', __FILE__)
4
+ require 'timeout'
5
+
6
+ describe Rack::Handler::Thin do
7
+ extend TestRequest::Helpers
8
+
9
+ @app = Rack::Lint.new(TestRequest.new)
10
+ @server = nil
11
+ Thin::Logging.silent = true
12
+
13
+ @thread = Thread.new do
14
+ Rack::Handler::Thin.run(@app, :Host => @host='0.0.0.0', :Port => @port=9204) do |server|
15
+ @server = server
16
+ end
17
+ end
18
+
19
+ Thread.pass until @server && @server.running?
20
+
21
+ should "respond" do
22
+ GET("/")
23
+ response.should.not.be.nil
24
+ end
25
+
26
+ should "be a Thin" do
27
+ GET("/")
28
+ status.should.equal 200
29
+ response["SERVER_SOFTWARE"].should =~ /thin/
30
+ response["HTTP_VERSION"].should.equal "HTTP/1.1"
31
+ response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
32
+ response["SERVER_PORT"].should.equal "9204"
33
+ response["SERVER_NAME"].should.equal "0.0.0.0"
34
+ end
35
+
36
+ should "have rack headers" do
37
+ GET("/")
38
+ response["rack.version"].should.equal [1,0]
39
+ response["rack.multithread"].should.equal false
40
+ response["rack.multiprocess"].should.equal false
41
+ response["rack.run_once"].should.equal false
42
+ end
43
+
44
+ should "have CGI headers on GET" do
45
+ GET("/")
46
+ response["REQUEST_METHOD"].should.equal "GET"
47
+ response["REQUEST_PATH"].should.equal "/"
48
+ response["PATH_INFO"].should.be.equal "/"
49
+ response["QUERY_STRING"].should.equal ""
50
+ response["test.postdata"].should.equal ""
51
+
52
+ GET("/test/foo?quux=1")
53
+ response["REQUEST_METHOD"].should.equal "GET"
54
+ response["REQUEST_PATH"].should.equal "/test/foo"
55
+ response["PATH_INFO"].should.equal "/test/foo"
56
+ response["QUERY_STRING"].should.equal "quux=1"
57
+ end
58
+
59
+ should "have CGI headers on POST" do
60
+ POST("/", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
61
+ status.should.equal 200
62
+ response["REQUEST_METHOD"].should.equal "POST"
63
+ response["REQUEST_PATH"].should.equal "/"
64
+ response["QUERY_STRING"].should.equal ""
65
+ response["HTTP_X_TEST_HEADER"].should.equal "42"
66
+ response["test.postdata"].should.equal "rack-form-data=23"
67
+ end
68
+
69
+ should "support HTTP auth" do
70
+ GET("/test", {:user => "ruth", :passwd => "secret"})
71
+ response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
72
+ end
73
+
74
+ should "set status" do
75
+ GET("/test?secret")
76
+ status.should.equal 403
77
+ response["rack.url_scheme"].should.equal "http"
78
+ end
79
+
80
+ @server.stop!
81
+ @thread.kill
82
+ end
83
+
84
+ rescue LoadError
85
+ $stderr.puts "Skipping Rack::Handler::Thin tests (Thin is required). `gem install thin` and try again."
86
+ end