edgar-rack 1.2.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 (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