eac-rack 1.1.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 (111) hide show
  1. data/COPYING +18 -0
  2. data/KNOWN-ISSUES +21 -0
  3. data/README +399 -0
  4. data/bin/rackup +4 -0
  5. data/contrib/rack_logo.svg +111 -0
  6. data/example/lobster.ru +4 -0
  7. data/example/protectedlobster.rb +14 -0
  8. data/example/protectedlobster.ru +8 -0
  9. data/lib/rack.rb +92 -0
  10. data/lib/rack/adapter/camping.rb +22 -0
  11. data/lib/rack/auth/abstract/handler.rb +37 -0
  12. data/lib/rack/auth/abstract/request.rb +37 -0
  13. data/lib/rack/auth/basic.rb +58 -0
  14. data/lib/rack/auth/digest/md5.rb +124 -0
  15. data/lib/rack/auth/digest/nonce.rb +51 -0
  16. data/lib/rack/auth/digest/params.rb +55 -0
  17. data/lib/rack/auth/digest/request.rb +40 -0
  18. data/lib/rack/builder.rb +80 -0
  19. data/lib/rack/cascade.rb +41 -0
  20. data/lib/rack/chunked.rb +49 -0
  21. data/lib/rack/commonlogger.rb +49 -0
  22. data/lib/rack/conditionalget.rb +47 -0
  23. data/lib/rack/config.rb +15 -0
  24. data/lib/rack/content_length.rb +29 -0
  25. data/lib/rack/content_type.rb +23 -0
  26. data/lib/rack/deflater.rb +96 -0
  27. data/lib/rack/directory.rb +157 -0
  28. data/lib/rack/etag.rb +23 -0
  29. data/lib/rack/file.rb +90 -0
  30. data/lib/rack/handler.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 +89 -0
  34. data/lib/rack/handler/lsws.rb +63 -0
  35. data/lib/rack/handler/mongrel.rb +90 -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 +69 -0
  40. data/lib/rack/head.rb +19 -0
  41. data/lib/rack/lint.rb +575 -0
  42. data/lib/rack/lobster.rb +65 -0
  43. data/lib/rack/lock.rb +16 -0
  44. data/lib/rack/logger.rb +20 -0
  45. data/lib/rack/methodoverride.rb +27 -0
  46. data/lib/rack/mime.rb +206 -0
  47. data/lib/rack/mock.rb +189 -0
  48. data/lib/rack/nulllogger.rb +18 -0
  49. data/lib/rack/recursive.rb +57 -0
  50. data/lib/rack/reloader.rb +109 -0
  51. data/lib/rack/request.rb +271 -0
  52. data/lib/rack/response.rb +149 -0
  53. data/lib/rack/rewindable_input.rb +100 -0
  54. data/lib/rack/runtime.rb +27 -0
  55. data/lib/rack/sendfile.rb +142 -0
  56. data/lib/rack/server.rb +212 -0
  57. data/lib/rack/session/abstract/id.rb +140 -0
  58. data/lib/rack/session/cookie.rb +90 -0
  59. data/lib/rack/session/memcache.rb +119 -0
  60. data/lib/rack/session/pool.rb +100 -0
  61. data/lib/rack/showexceptions.rb +349 -0
  62. data/lib/rack/showstatus.rb +106 -0
  63. data/lib/rack/static.rb +38 -0
  64. data/lib/rack/urlmap.rb +56 -0
  65. data/lib/rack/utils.rb +614 -0
  66. data/rack.gemspec +38 -0
  67. data/test/spec_rack_auth_basic.rb +73 -0
  68. data/test/spec_rack_auth_digest.rb +226 -0
  69. data/test/spec_rack_builder.rb +84 -0
  70. data/test/spec_rack_camping.rb +51 -0
  71. data/test/spec_rack_cascade.rb +48 -0
  72. data/test/spec_rack_cgi.rb +89 -0
  73. data/test/spec_rack_chunked.rb +62 -0
  74. data/test/spec_rack_commonlogger.rb +61 -0
  75. data/test/spec_rack_conditionalget.rb +41 -0
  76. data/test/spec_rack_config.rb +24 -0
  77. data/test/spec_rack_content_length.rb +43 -0
  78. data/test/spec_rack_content_type.rb +30 -0
  79. data/test/spec_rack_deflater.rb +127 -0
  80. data/test/spec_rack_directory.rb +61 -0
  81. data/test/spec_rack_etag.rb +17 -0
  82. data/test/spec_rack_fastcgi.rb +89 -0
  83. data/test/spec_rack_file.rb +75 -0
  84. data/test/spec_rack_handler.rb +43 -0
  85. data/test/spec_rack_head.rb +30 -0
  86. data/test/spec_rack_lint.rb +528 -0
  87. data/test/spec_rack_lobster.rb +45 -0
  88. data/test/spec_rack_lock.rb +38 -0
  89. data/test/spec_rack_logger.rb +21 -0
  90. data/test/spec_rack_methodoverride.rb +60 -0
  91. data/test/spec_rack_mock.rb +243 -0
  92. data/test/spec_rack_mongrel.rb +189 -0
  93. data/test/spec_rack_nulllogger.rb +13 -0
  94. data/test/spec_rack_recursive.rb +77 -0
  95. data/test/spec_rack_request.rb +545 -0
  96. data/test/spec_rack_response.rb +221 -0
  97. data/test/spec_rack_rewindable_input.rb +118 -0
  98. data/test/spec_rack_runtime.rb +35 -0
  99. data/test/spec_rack_sendfile.rb +86 -0
  100. data/test/spec_rack_session_cookie.rb +73 -0
  101. data/test/spec_rack_session_memcache.rb +273 -0
  102. data/test/spec_rack_session_pool.rb +172 -0
  103. data/test/spec_rack_showexceptions.rb +21 -0
  104. data/test/spec_rack_showstatus.rb +72 -0
  105. data/test/spec_rack_static.rb +37 -0
  106. data/test/spec_rack_thin.rb +91 -0
  107. data/test/spec_rack_urlmap.rb +215 -0
  108. data/test/spec_rack_utils.rb +554 -0
  109. data/test/spec_rack_webrick.rb +130 -0
  110. data/test/spec_rackup.rb +154 -0
  111. metadata +311 -0
@@ -0,0 +1,45 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/lobster'
4
+ require 'rack/mock'
5
+
6
+ context "Rack::Lobster::LambdaLobster" do
7
+ specify "should be a single lambda" do
8
+ Rack::Lobster::LambdaLobster.should.be.kind_of Proc
9
+ end
10
+
11
+ specify "should look like a lobster" do
12
+ res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/")
13
+ res.should.be.ok
14
+ res.body.should.include "(,(,,(,,,("
15
+ res.body.should.include "?flip"
16
+ end
17
+
18
+ specify "should be flippable" do
19
+ res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/?flip")
20
+ res.should.be.ok
21
+ res.body.should.include "(,,,(,,(,("
22
+ end
23
+ end
24
+
25
+ context "Rack::Lobster" do
26
+ specify "should look like a lobster" do
27
+ res = Rack::MockRequest.new(Rack::Lobster.new).get("/")
28
+ res.should.be.ok
29
+ res.body.should.include "(,(,,(,,,("
30
+ res.body.should.include "?flip"
31
+ res.body.should.include "crash"
32
+ end
33
+
34
+ specify "should be flippable" do
35
+ res = Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=left")
36
+ res.should.be.ok
37
+ res.body.should.include "(,,,(,,(,("
38
+ end
39
+
40
+ specify "should provide crashing for testing purposes" do
41
+ lambda {
42
+ Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=crash")
43
+ }.should.raise
44
+ end
45
+ end
@@ -0,0 +1,38 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/mock'
4
+ require 'rack/lock'
5
+
6
+ context "Rack::Lock" do
7
+ class Lock
8
+ attr_reader :synchronized
9
+
10
+ def initialize
11
+ @synchronized = false
12
+ end
13
+
14
+ def synchronize
15
+ @synchronized = true
16
+ yield
17
+ end
18
+ end
19
+
20
+ specify "should call synchronize on lock" do
21
+ lock = Lock.new
22
+ env = Rack::MockRequest.env_for("/")
23
+ app = Rack::Lock.new(lambda { |env| }, lock)
24
+ lock.synchronized.should.equal false
25
+ app.call(env)
26
+ lock.synchronized.should.equal true
27
+ end
28
+
29
+ specify "should set multithread flag to false" do
30
+ app = Rack::Lock.new(lambda { |env| env['rack.multithread'] })
31
+ app.call(Rack::MockRequest.env_for("/")).should.equal false
32
+ end
33
+
34
+ specify "should reset original multithread flag when exiting lock" do
35
+ app = Rack::Lock.new(lambda { |env| env })
36
+ app.call(Rack::MockRequest.env_for("/"))['rack.multithread'].should.equal true
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ require 'rack/logger'
2
+ require 'rack/lint'
3
+ require 'stringio'
4
+
5
+ context "Rack::Logger" do
6
+ specify "logs to rack.errors" do
7
+ app = lambda { |env|
8
+ log = env['rack.logger']
9
+ log.debug("Created logger")
10
+ log.info("Program started")
11
+ log.warn("Nothing to do!")
12
+
13
+ [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
14
+ }
15
+
16
+ errors = StringIO.new
17
+ Rack::Logger.new(app).call({'rack.errors' => errors})
18
+ errors.string.should.match "INFO -- : Program started"
19
+ errors.string.should.match "WARN -- : Nothing to do"
20
+ end
21
+ end
@@ -0,0 +1,60 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/mock'
4
+ require 'rack/methodoverride'
5
+ require 'stringio'
6
+
7
+ context "Rack::MethodOverride" do
8
+ specify "should not affect GET requests" do
9
+ env = Rack::MockRequest.env_for("/?_method=delete", :method => "GET")
10
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
11
+ req = app.call(env)
12
+
13
+ req.env["REQUEST_METHOD"].should.equal "GET"
14
+ end
15
+
16
+ specify "_method parameter should modify REQUEST_METHOD for POST requests" do
17
+ env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=put")
18
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
19
+ req = app.call(env)
20
+
21
+ req.env["REQUEST_METHOD"].should.equal "PUT"
22
+ end
23
+
24
+ specify "X-HTTP-Method-Override header should modify REQUEST_METHOD for POST requests" do
25
+ env = Rack::MockRequest.env_for("/",
26
+ :method => "POST",
27
+ "HTTP_X_HTTP_METHOD_OVERRIDE" => "PUT"
28
+ )
29
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
30
+ req = app.call(env)
31
+
32
+ req.env["REQUEST_METHOD"].should.equal "PUT"
33
+ end
34
+
35
+ specify "should not modify REQUEST_METHOD if the method is unknown" do
36
+ env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=foo")
37
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
38
+ req = app.call(env)
39
+
40
+ req.env["REQUEST_METHOD"].should.equal "POST"
41
+ end
42
+
43
+ specify "should not modify REQUEST_METHOD when _method is nil" do
44
+ env = Rack::MockRequest.env_for("/", :method => "POST", :input => "foo=bar")
45
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
46
+ req = app.call(env)
47
+
48
+ req.env["REQUEST_METHOD"].should.equal "POST"
49
+ end
50
+
51
+ specify "should store the original REQUEST_METHOD prior to overriding" do
52
+ env = Rack::MockRequest.env_for("/",
53
+ :method => "POST",
54
+ :input => "_method=options")
55
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
56
+ req = app.call(env)
57
+
58
+ req.env["rack.methodoverride.original_method"].should.equal "POST"
59
+ end
60
+ end
@@ -0,0 +1,243 @@
1
+ require 'yaml'
2
+ require 'rack/mock'
3
+ require 'rack/request'
4
+ require 'rack/response'
5
+
6
+ app = lambda { |env|
7
+ req = Rack::Request.new(env)
8
+
9
+ env["mock.postdata"] = env["rack.input"].read
10
+ if req.GET["error"]
11
+ env["rack.errors"].puts req.GET["error"]
12
+ env["rack.errors"].flush
13
+ end
14
+
15
+ Rack::Response.new(env.to_yaml,
16
+ req.GET["status"] || 200,
17
+ "Content-Type" => "text/yaml").finish
18
+ }
19
+
20
+ context "Rack::MockRequest" do
21
+ specify "should return a MockResponse" do
22
+ res = Rack::MockRequest.new(app).get("")
23
+ res.should.be.kind_of Rack::MockResponse
24
+ end
25
+
26
+ specify "should be able to only return the environment" do
27
+ env = Rack::MockRequest.env_for("")
28
+ env.should.be.kind_of Hash
29
+ env.should.include "rack.version"
30
+ end
31
+
32
+ specify "should provide sensible defaults" do
33
+ res = Rack::MockRequest.new(app).request
34
+
35
+ env = YAML.load(res.body)
36
+ env["REQUEST_METHOD"].should.equal "GET"
37
+ env["SERVER_NAME"].should.equal "example.org"
38
+ env["SERVER_PORT"].should.equal "80"
39
+ env["QUERY_STRING"].should.equal ""
40
+ env["PATH_INFO"].should.equal "/"
41
+ env["SCRIPT_NAME"].should.equal ""
42
+ env["rack.url_scheme"].should.equal "http"
43
+ env["mock.postdata"].should.be.empty
44
+ end
45
+
46
+ specify "should allow GET/POST/PUT/DELETE" do
47
+ res = Rack::MockRequest.new(app).get("", :input => "foo")
48
+ env = YAML.load(res.body)
49
+ env["REQUEST_METHOD"].should.equal "GET"
50
+
51
+ res = Rack::MockRequest.new(app).post("", :input => "foo")
52
+ env = YAML.load(res.body)
53
+ env["REQUEST_METHOD"].should.equal "POST"
54
+
55
+ res = Rack::MockRequest.new(app).put("", :input => "foo")
56
+ env = YAML.load(res.body)
57
+ env["REQUEST_METHOD"].should.equal "PUT"
58
+
59
+ res = Rack::MockRequest.new(app).delete("", :input => "foo")
60
+ env = YAML.load(res.body)
61
+ env["REQUEST_METHOD"].should.equal "DELETE"
62
+
63
+ Rack::MockRequest.env_for("/", :method => "OPTIONS")["REQUEST_METHOD"].
64
+ should.equal "OPTIONS"
65
+ end
66
+
67
+ specify "should set content length" do
68
+ env = Rack::MockRequest.env_for("/", :input => "foo")
69
+ env["CONTENT_LENGTH"].should.equal "3"
70
+ end
71
+
72
+ specify "should allow posting" do
73
+ res = Rack::MockRequest.new(app).get("", :input => "foo")
74
+ env = YAML.load(res.body)
75
+ env["mock.postdata"].should.equal "foo"
76
+
77
+ res = Rack::MockRequest.new(app).post("", :input => StringIO.new("foo"))
78
+ env = YAML.load(res.body)
79
+ env["mock.postdata"].should.equal "foo"
80
+ end
81
+
82
+ specify "should use all parts of an URL" do
83
+ res = Rack::MockRequest.new(app).
84
+ get("https://bla.example.org:9292/meh/foo?bar")
85
+ res.should.be.kind_of Rack::MockResponse
86
+
87
+ env = YAML.load(res.body)
88
+ env["REQUEST_METHOD"].should.equal "GET"
89
+ env["SERVER_NAME"].should.equal "bla.example.org"
90
+ env["SERVER_PORT"].should.equal "9292"
91
+ env["QUERY_STRING"].should.equal "bar"
92
+ env["PATH_INFO"].should.equal "/meh/foo"
93
+ env["rack.url_scheme"].should.equal "https"
94
+ end
95
+
96
+ specify "should set SSL port and HTTP flag on when using https" do
97
+ res = Rack::MockRequest.new(app).
98
+ get("https://example.org/foo")
99
+ res.should.be.kind_of Rack::MockResponse
100
+
101
+ env = YAML.load(res.body)
102
+ env["REQUEST_METHOD"].should.equal "GET"
103
+ env["SERVER_NAME"].should.equal "example.org"
104
+ env["SERVER_PORT"].should.equal "443"
105
+ env["QUERY_STRING"].should.equal ""
106
+ env["PATH_INFO"].should.equal "/foo"
107
+ env["rack.url_scheme"].should.equal "https"
108
+ env["HTTPS"].should.equal "on"
109
+ end
110
+
111
+ specify "should prepend slash to uri path" do
112
+ res = Rack::MockRequest.new(app).
113
+ get("foo")
114
+ res.should.be.kind_of Rack::MockResponse
115
+
116
+ env = YAML.load(res.body)
117
+ env["REQUEST_METHOD"].should.equal "GET"
118
+ env["SERVER_NAME"].should.equal "example.org"
119
+ env["SERVER_PORT"].should.equal "80"
120
+ env["QUERY_STRING"].should.equal ""
121
+ env["PATH_INFO"].should.equal "/foo"
122
+ env["rack.url_scheme"].should.equal "http"
123
+ end
124
+
125
+ specify "should properly convert method name to an uppercase string" do
126
+ res = Rack::MockRequest.new(app).request(:get)
127
+ env = YAML.load(res.body)
128
+ env["REQUEST_METHOD"].should.equal "GET"
129
+ end
130
+
131
+ specify "should accept params and build query string for GET requests" do
132
+ res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => {:foo => {:bar => "1"}})
133
+ env = YAML.load(res.body)
134
+ env["REQUEST_METHOD"].should.equal "GET"
135
+ env["QUERY_STRING"].should.match "baz=2"
136
+ env["QUERY_STRING"].should.match "foo[bar]=1"
137
+ env["PATH_INFO"].should.equal "/foo"
138
+ env["mock.postdata"].should.equal ""
139
+ end
140
+
141
+ specify "should accept raw input in params for GET requests" do
142
+ res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => "foo[bar]=1")
143
+ env = YAML.load(res.body)
144
+ env["REQUEST_METHOD"].should.equal "GET"
145
+ env["QUERY_STRING"].should.match "baz=2"
146
+ env["QUERY_STRING"].should.match "foo[bar]=1"
147
+ env["PATH_INFO"].should.equal "/foo"
148
+ env["mock.postdata"].should.equal ""
149
+ end
150
+
151
+ specify "should accept params and build url encoded params for POST requests" do
152
+ res = Rack::MockRequest.new(app).post("/foo", :params => {:foo => {:bar => "1"}})
153
+ env = YAML.load(res.body)
154
+ env["REQUEST_METHOD"].should.equal "POST"
155
+ env["QUERY_STRING"].should.equal ""
156
+ env["PATH_INFO"].should.equal "/foo"
157
+ env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
158
+ env["mock.postdata"].should.equal "foo[bar]=1"
159
+ end
160
+
161
+ specify "should accept raw input in params for POST requests" do
162
+ res = Rack::MockRequest.new(app).post("/foo", :params => "foo[bar]=1")
163
+ env = YAML.load(res.body)
164
+ env["REQUEST_METHOD"].should.equal "POST"
165
+ env["QUERY_STRING"].should.equal ""
166
+ env["PATH_INFO"].should.equal "/foo"
167
+ env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
168
+ env["mock.postdata"].should.equal "foo[bar]=1"
169
+ end
170
+
171
+ specify "should accept params and build multipart encoded params for POST requests" do
172
+ files = Rack::Utils::Multipart::UploadedFile.new(File.join(File.dirname(__FILE__), "multipart", "file1.txt"))
173
+ res = Rack::MockRequest.new(app).post("/foo", :params => { "submit-name" => "Larry", "files" => files })
174
+ env = YAML.load(res.body)
175
+ env["REQUEST_METHOD"].should.equal "POST"
176
+ env["QUERY_STRING"].should.equal ""
177
+ env["PATH_INFO"].should.equal "/foo"
178
+ env["CONTENT_TYPE"].should.equal "multipart/form-data; boundary=AaB03x"
179
+ env["mock.postdata"].length.should.equal 206
180
+ end
181
+
182
+ specify "should behave valid according to the Rack spec" do
183
+ lambda {
184
+ res = Rack::MockRequest.new(app).
185
+ get("https://bla.example.org:9292/meh/foo?bar", :lint => true)
186
+ }.should.not.raise(Rack::Lint::LintError)
187
+ end
188
+ end
189
+
190
+ context "Rack::MockResponse" do
191
+ specify "should provide access to the HTTP status" do
192
+ res = Rack::MockRequest.new(app).get("")
193
+ res.should.be.successful
194
+ res.should.be.ok
195
+
196
+ res = Rack::MockRequest.new(app).get("/?status=404")
197
+ res.should.not.be.successful
198
+ res.should.be.client_error
199
+ res.should.be.not_found
200
+
201
+ res = Rack::MockRequest.new(app).get("/?status=501")
202
+ res.should.not.be.successful
203
+ res.should.be.server_error
204
+
205
+ res = Rack::MockRequest.new(app).get("/?status=307")
206
+ res.should.be.redirect
207
+
208
+ res = Rack::MockRequest.new(app).get("/?status=201", :lint => true)
209
+ res.should.be.empty
210
+ end
211
+
212
+ specify "should provide access to the HTTP headers" do
213
+ res = Rack::MockRequest.new(app).get("")
214
+ res.should.include "Content-Type"
215
+ res.headers["Content-Type"].should.equal "text/yaml"
216
+ res.original_headers["Content-Type"].should.equal "text/yaml"
217
+ res["Content-Type"].should.equal "text/yaml"
218
+ res.content_type.should.equal "text/yaml"
219
+ res.content_length.should.be 414 # needs change often.
220
+ res.location.should.be.nil
221
+ end
222
+
223
+ specify "should provide access to the HTTP body" do
224
+ res = Rack::MockRequest.new(app).get("")
225
+ res.body.should =~ /rack/
226
+ res.should =~ /rack/
227
+ res.should.match(/rack/)
228
+ res.should.satisfy { |r| r.match(/rack/) }
229
+ end
230
+
231
+ specify "should provide access to the Rack errors" do
232
+ res = Rack::MockRequest.new(app).get("/?error=foo", :lint => true)
233
+ res.should.be.ok
234
+ res.errors.should.not.be.empty
235
+ res.errors.should.include "foo"
236
+ end
237
+
238
+ specify "should optionally make Rack errors fatal" do
239
+ lambda {
240
+ Rack::MockRequest.new(app).get("/?error=foo", :fatal => true)
241
+ }.should.raise(Rack::MockRequest::FatalWarning)
242
+ end
243
+ end
@@ -0,0 +1,189 @@
1
+ require 'test/spec'
2
+
3
+ begin
4
+ require 'rack/handler/mongrel'
5
+ require 'rack/urlmap'
6
+ require 'rack/lint'
7
+ require 'testrequest'
8
+ require 'timeout'
9
+
10
+ Thread.abort_on_exception = true
11
+ $tcp_defer_accept_opts = nil
12
+ $tcp_cork_opts = nil
13
+
14
+ context "Rack::Handler::Mongrel" do
15
+ include TestRequest::Helpers
16
+
17
+ setup do
18
+ server = Mongrel::HttpServer.new(@host='0.0.0.0', @port=9201)
19
+ server.register('/test',
20
+ Rack::Handler::Mongrel.new(Rack::Lint.new(TestRequest.new)))
21
+ server.register('/stream',
22
+ Rack::Handler::Mongrel.new(Rack::Lint.new(StreamingRequest)))
23
+ @acc = server.run
24
+ end
25
+
26
+ specify "should respond" do
27
+ lambda {
28
+ GET("/test")
29
+ }.should.not.raise
30
+ end
31
+
32
+ specify "should be a Mongrel" do
33
+ GET("/test")
34
+ status.should.be 200
35
+ response["SERVER_SOFTWARE"].should =~ /Mongrel/
36
+ response["HTTP_VERSION"].should.equal "HTTP/1.1"
37
+ response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
38
+ response["SERVER_PORT"].should.equal "9201"
39
+ response["SERVER_NAME"].should.equal "0.0.0.0"
40
+ end
41
+
42
+ specify "should have rack headers" do
43
+ GET("/test")
44
+ response["rack.version"].should.equal [1,1]
45
+ response["rack.multithread"].should.be true
46
+ response["rack.multiprocess"].should.be false
47
+ response["rack.run_once"].should.be false
48
+ end
49
+
50
+ specify "should have CGI headers on GET" do
51
+ GET("/test")
52
+ response["REQUEST_METHOD"].should.equal "GET"
53
+ response["SCRIPT_NAME"].should.equal "/test"
54
+ response["REQUEST_PATH"].should.equal "/test"
55
+ response["PATH_INFO"].should.be.equal ""
56
+ response["QUERY_STRING"].should.equal ""
57
+ response["test.postdata"].should.equal ""
58
+
59
+ GET("/test/foo?quux=1")
60
+ response["REQUEST_METHOD"].should.equal "GET"
61
+ response["SCRIPT_NAME"].should.equal "/test"
62
+ response["REQUEST_PATH"].should.equal "/test/foo"
63
+ response["PATH_INFO"].should.equal "/foo"
64
+ response["QUERY_STRING"].should.equal "quux=1"
65
+ end
66
+
67
+ specify "should have CGI headers on POST" do
68
+ POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
69
+ status.should.equal 200
70
+ response["REQUEST_METHOD"].should.equal "POST"
71
+ response["SCRIPT_NAME"].should.equal "/test"
72
+ response["REQUEST_PATH"].should.equal "/test"
73
+ response["QUERY_STRING"].should.equal ""
74
+ response["HTTP_X_TEST_HEADER"].should.equal "42"
75
+ response["test.postdata"].should.equal "rack-form-data=23"
76
+ end
77
+
78
+ specify "should support HTTP auth" do
79
+ GET("/test", {:user => "ruth", :passwd => "secret"})
80
+ response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
81
+ end
82
+
83
+ specify "should set status" do
84
+ GET("/test?secret")
85
+ status.should.equal 403
86
+ response["rack.url_scheme"].should.equal "http"
87
+ end
88
+
89
+ specify "should provide a .run" do
90
+ block_ran = false
91
+ Thread.new {
92
+ Rack::Handler::Mongrel.run(lambda {}, {:Port => 9211}) { |server|
93
+ server.should.be.kind_of Mongrel::HttpServer
94
+ block_ran = true
95
+ }
96
+ }
97
+ sleep 1
98
+ block_ran.should.be true
99
+ end
100
+
101
+ specify "should provide a .run that maps a hash" do
102
+ block_ran = false
103
+ Thread.new {
104
+ map = {'/'=>lambda{},'/foo'=>lambda{}}
105
+ Rack::Handler::Mongrel.run(map, :map => true, :Port => 9221) { |server|
106
+ server.should.be.kind_of Mongrel::HttpServer
107
+ server.classifier.uris.size.should.be 2
108
+ server.classifier.uris.should.not.include '/arf'
109
+ server.classifier.uris.should.include '/'
110
+ server.classifier.uris.should.include '/foo'
111
+ block_ran = true
112
+ }
113
+ }
114
+ sleep 1
115
+ block_ran.should.be true
116
+ end
117
+
118
+ specify "should provide a .run that maps a urlmap" do
119
+ block_ran = false
120
+ Thread.new {
121
+ map = Rack::URLMap.new({'/'=>lambda{},'/bar'=>lambda{}})
122
+ Rack::Handler::Mongrel.run(map, {:map => true, :Port => 9231}) { |server|
123
+ server.should.be.kind_of Mongrel::HttpServer
124
+ server.classifier.uris.size.should.be 2
125
+ server.classifier.uris.should.not.include '/arf'
126
+ server.classifier.uris.should.include '/'
127
+ server.classifier.uris.should.include '/bar'
128
+ block_ran = true
129
+ }
130
+ }
131
+ sleep 1
132
+ block_ran.should.be true
133
+ end
134
+
135
+ specify "should provide a .run that maps a urlmap restricting by host" do
136
+ block_ran = false
137
+ Thread.new {
138
+ map = Rack::URLMap.new({
139
+ '/' => lambda{},
140
+ '/foo' => lambda{},
141
+ '/bar' => lambda{},
142
+ 'http://localhost/' => lambda{},
143
+ 'http://localhost/bar' => lambda{},
144
+ 'http://falsehost/arf' => lambda{},
145
+ 'http://falsehost/qux' => lambda{}
146
+ })
147
+ opt = {:map => true, :Port => 9241, :Host => 'localhost'}
148
+ Rack::Handler::Mongrel.run(map, opt) { |server|
149
+ server.should.be.kind_of Mongrel::HttpServer
150
+ server.classifier.uris.should.include '/'
151
+ server.classifier.handler_map['/'].size.should.be 2
152
+ server.classifier.uris.should.include '/foo'
153
+ server.classifier.handler_map['/foo'].size.should.be 1
154
+ server.classifier.uris.should.include '/bar'
155
+ server.classifier.handler_map['/bar'].size.should.be 2
156
+ server.classifier.uris.should.not.include '/qux'
157
+ server.classifier.uris.should.not.include '/arf'
158
+ server.classifier.uris.size.should.be 3
159
+ block_ran = true
160
+ }
161
+ }
162
+ sleep 1
163
+ block_ran.should.be true
164
+ end
165
+
166
+ specify "should stream #each part of the response" do
167
+ body = ''
168
+ begin
169
+ Timeout.timeout(1) do
170
+ Net::HTTP.start(@host, @port) do |http|
171
+ get = Net::HTTP::Get.new('/stream')
172
+ http.request(get) do |response|
173
+ response.read_body { |part| body << part }
174
+ end
175
+ end
176
+ end
177
+ rescue Timeout::Error
178
+ end
179
+ body.should.not.be.empty
180
+ end
181
+
182
+ teardown do
183
+ @acc.raise Mongrel::StopServer
184
+ end
185
+ end
186
+
187
+ rescue LoadError
188
+ $stderr.puts "Skipping Rack::Handler::Mongrel tests (Mongrel is required). `gem install mongrel` and try again."
189
+ end