rack 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (82) hide show
  1. data/COPYING +1 -1
  2. data/KNOWN-ISSUES +3 -0
  3. data/RDOX +0 -428
  4. data/README +61 -26
  5. data/SPEC +8 -1
  6. data/bin/rackup +2 -174
  7. data/lib/rack.rb +10 -8
  8. data/lib/rack/builder.rb +17 -0
  9. data/lib/rack/cascade.rb +17 -12
  10. data/lib/rack/chunked.rb +2 -2
  11. data/lib/rack/commonlogger.rb +31 -43
  12. data/lib/rack/config.rb +15 -0
  13. data/lib/rack/content_type.rb +1 -1
  14. data/lib/rack/directory.rb +6 -2
  15. data/lib/rack/etag.rb +23 -0
  16. data/lib/rack/file.rb +4 -2
  17. data/lib/rack/handler.rb +19 -0
  18. data/lib/rack/handler/cgi.rb +1 -1
  19. data/lib/rack/handler/fastcgi.rb +2 -3
  20. data/lib/rack/handler/lsws.rb +4 -1
  21. data/lib/rack/handler/mongrel.rb +8 -5
  22. data/lib/rack/handler/scgi.rb +4 -4
  23. data/lib/rack/handler/webrick.rb +2 -4
  24. data/lib/rack/lint.rb +44 -15
  25. data/lib/rack/logger.rb +20 -0
  26. data/lib/rack/mime.rb +3 -1
  27. data/lib/rack/mock.rb +30 -4
  28. data/lib/rack/nulllogger.rb +18 -0
  29. data/lib/rack/reloader.rb +4 -1
  30. data/lib/rack/request.rb +40 -15
  31. data/lib/rack/response.rb +5 -39
  32. data/lib/rack/runtime.rb +27 -0
  33. data/lib/rack/sendfile.rb +142 -0
  34. data/lib/rack/server.rb +212 -0
  35. data/lib/rack/session/abstract/id.rb +3 -5
  36. data/lib/rack/session/cookie.rb +3 -4
  37. data/lib/rack/session/memcache.rb +53 -43
  38. data/lib/rack/session/pool.rb +1 -1
  39. data/lib/rack/urlmap.rb +9 -8
  40. data/lib/rack/utils.rb +230 -11
  41. data/rack.gemspec +33 -49
  42. data/test/spec_rack_cascade.rb +3 -5
  43. data/test/spec_rack_cgi.rb +3 -3
  44. data/test/spec_rack_commonlogger.rb +39 -10
  45. data/test/spec_rack_config.rb +24 -0
  46. data/test/spec_rack_directory.rb +1 -1
  47. data/test/spec_rack_etag.rb +17 -0
  48. data/test/spec_rack_fastcgi.rb +2 -2
  49. data/test/spec_rack_file.rb +1 -1
  50. data/test/spec_rack_lint.rb +26 -19
  51. data/test/spec_rack_logger.rb +21 -0
  52. data/test/spec_rack_mock.rb +87 -1
  53. data/test/spec_rack_mongrel.rb +4 -4
  54. data/test/spec_rack_nulllogger.rb +13 -0
  55. data/test/spec_rack_request.rb +47 -6
  56. data/test/spec_rack_response.rb +3 -0
  57. data/test/spec_rack_runtime.rb +35 -0
  58. data/test/spec_rack_sendfile.rb +86 -0
  59. data/test/spec_rack_session_cookie.rb +1 -10
  60. data/test/spec_rack_session_memcache.rb +53 -20
  61. data/test/spec_rack_urlmap.rb +30 -0
  62. data/test/spec_rack_utils.rb +171 -6
  63. data/test/spec_rack_webrick.rb +4 -4
  64. data/test/spec_rackup.rb +154 -0
  65. metadata +37 -79
  66. data/Rakefile +0 -164
  67. data/lib/rack/auth/openid.rb +0 -480
  68. data/test/cgi/lighttpd.conf +0 -20
  69. data/test/cgi/test +0 -9
  70. data/test/cgi/test.fcgi +0 -8
  71. data/test/cgi/test.ru +0 -7
  72. data/test/multipart/binary +0 -0
  73. data/test/multipart/empty +0 -10
  74. data/test/multipart/ie +0 -6
  75. data/test/multipart/nested +0 -10
  76. data/test/multipart/none +0 -9
  77. data/test/multipart/semicolon +0 -6
  78. data/test/multipart/text +0 -10
  79. data/test/spec_rack_auth_openid.rb +0 -84
  80. data/test/testrequest.rb +0 -57
  81. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  82. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,54 +1,38 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
1
  Gem::Specification.new do |s|
4
- s.name = %q{rack}
5
- s.version = "1.0.1"
2
+ s.name = "rack"
3
+ s.version = "1.1.0"
4
+ s.platform = Gem::Platform::RUBY
5
+ s.summary = "a modular Ruby webserver interface"
6
+
7
+ s.description = <<-EOF
8
+ Rack provides minimal, modular and adaptable interface for developing
9
+ web applications in Ruby. By wrapping HTTP requests and responses in
10
+ the simplest way possible, it unifies and distills the API for web
11
+ servers, web frameworks, and software in between (the so-called
12
+ middleware) into a single method call.
13
+
14
+ Also see http://rack.rubyforge.org.
15
+ EOF
16
+
17
+ s.files = Dir['{bin/*,contrib/*,example/*,lib/**/*}'] +
18
+ %w(COPYING KNOWN-ISSUES rack.gemspec RDOX README SPEC)
19
+ s.bindir = 'bin'
20
+ s.executables << 'rackup'
21
+ s.require_path = 'lib'
22
+ s.has_rdoc = true
23
+ s.extra_rdoc_files = ['README', 'SPEC', 'KNOWN-ISSUES']
24
+ s.test_files = Dir['test/{test,spec}_*.rb']
6
25
 
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Christian Neukirchen"]
9
- s.date = %q{2009-10-18}
10
- s.default_executable = %q{rackup}
11
- s.description = %q{Rack provides minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call. Also see http://rack.rubyforge.org.}
12
- s.email = %q{chneukirchen@gmail.com}
13
- s.executables = ["rackup"]
14
- s.extra_rdoc_files = ["README", "SPEC", "RDOX", "KNOWN-ISSUES"]
15
- s.files = ["COPYING", "KNOWN-ISSUES", "README", "Rakefile", "bin/rackup", "contrib/rack_logo.svg", "example/lobster.ru", "example/protectedlobster.rb", "example/protectedlobster.ru", "lib/rack.rb", "lib/rack/adapter/camping.rb", "lib/rack/auth/abstract/handler.rb", "lib/rack/auth/abstract/request.rb", "lib/rack/auth/basic.rb", "lib/rack/auth/digest/md5.rb", "lib/rack/auth/digest/nonce.rb", "lib/rack/auth/digest/params.rb", "lib/rack/auth/digest/request.rb", "lib/rack/auth/openid.rb", "lib/rack/builder.rb", "lib/rack/cascade.rb", "lib/rack/chunked.rb", "lib/rack/commonlogger.rb", "lib/rack/conditionalget.rb", "lib/rack/content_length.rb", "lib/rack/content_type.rb", "lib/rack/deflater.rb", "lib/rack/directory.rb", "lib/rack/file.rb", "lib/rack/handler.rb", "lib/rack/handler/cgi.rb", "lib/rack/handler/evented_mongrel.rb", "lib/rack/handler/fastcgi.rb", "lib/rack/handler/lsws.rb", "lib/rack/handler/mongrel.rb", "lib/rack/handler/scgi.rb", "lib/rack/handler/swiftiplied_mongrel.rb", "lib/rack/handler/thin.rb", "lib/rack/handler/webrick.rb", "lib/rack/head.rb", "lib/rack/lint.rb", "lib/rack/lobster.rb", "lib/rack/lock.rb", "lib/rack/methodoverride.rb", "lib/rack/mime.rb", "lib/rack/mock.rb", "lib/rack/recursive.rb", "lib/rack/reloader.rb", "lib/rack/request.rb", "lib/rack/response.rb", "lib/rack/rewindable_input.rb", "lib/rack/session/abstract/id.rb", "lib/rack/session/cookie.rb", "lib/rack/session/memcache.rb", "lib/rack/session/pool.rb", "lib/rack/showexceptions.rb", "lib/rack/showstatus.rb", "lib/rack/static.rb", "lib/rack/urlmap.rb", "lib/rack/utils.rb", "test/cgi/lighttpd.conf", "test/cgi/test", "test/cgi/test.fcgi", "test/cgi/test.ru", "test/multipart/binary", "test/multipart/empty", "test/multipart/ie", "test/multipart/nested", "test/multipart/none", "test/multipart/semicolon", "test/multipart/text", "test/spec_rack_auth_basic.rb", "test/spec_rack_auth_digest.rb", "test/spec_rack_auth_openid.rb", "test/spec_rack_builder.rb", "test/spec_rack_camping.rb", "test/spec_rack_cascade.rb", "test/spec_rack_cgi.rb", "test/spec_rack_chunked.rb", "test/spec_rack_commonlogger.rb", "test/spec_rack_conditionalget.rb", "test/spec_rack_content_length.rb", "test/spec_rack_content_type.rb", "test/spec_rack_deflater.rb", "test/spec_rack_directory.rb", "test/spec_rack_fastcgi.rb", "test/spec_rack_file.rb", "test/spec_rack_handler.rb", "test/spec_rack_head.rb", "test/spec_rack_lint.rb", "test/spec_rack_lobster.rb", "test/spec_rack_lock.rb", "test/spec_rack_methodoverride.rb", "test/spec_rack_mock.rb", "test/spec_rack_mongrel.rb", "test/spec_rack_recursive.rb", "test/spec_rack_request.rb", "test/spec_rack_response.rb", "test/spec_rack_rewindable_input.rb", "test/spec_rack_session_cookie.rb", "test/spec_rack_session_memcache.rb", "test/spec_rack_session_pool.rb", "test/spec_rack_showexceptions.rb", "test/spec_rack_showstatus.rb", "test/spec_rack_static.rb", "test/spec_rack_thin.rb", "test/spec_rack_urlmap.rb", "test/spec_rack_utils.rb", "test/spec_rack_webrick.rb", "test/testrequest.rb", "test/unregistered_handler/rack/handler/unregistered.rb", "test/unregistered_handler/rack/handler/unregistered_long_one.rb", "SPEC", "RDOX", "rack.gemspec"]
16
- s.has_rdoc = true
17
- s.homepage = %q{http://rack.rubyforge.org}
18
- s.require_paths = ["lib"]
19
- s.rubyforge_project = %q{rack}
20
- s.rubygems_version = %q{1.3.1}
21
- s.summary = %q{a modular Ruby webserver interface}
22
- s.test_files = ["test/spec_rack_auth_basic.rb", "test/spec_rack_auth_digest.rb", "test/spec_rack_auth_openid.rb", "test/spec_rack_builder.rb", "test/spec_rack_camping.rb", "test/spec_rack_cascade.rb", "test/spec_rack_cgi.rb", "test/spec_rack_chunked.rb", "test/spec_rack_commonlogger.rb", "test/spec_rack_conditionalget.rb", "test/spec_rack_content_length.rb", "test/spec_rack_content_type.rb", "test/spec_rack_deflater.rb", "test/spec_rack_directory.rb", "test/spec_rack_fastcgi.rb", "test/spec_rack_file.rb", "test/spec_rack_handler.rb", "test/spec_rack_head.rb", "test/spec_rack_lint.rb", "test/spec_rack_lobster.rb", "test/spec_rack_lock.rb", "test/spec_rack_methodoverride.rb", "test/spec_rack_mock.rb", "test/spec_rack_mongrel.rb", "test/spec_rack_recursive.rb", "test/spec_rack_request.rb", "test/spec_rack_response.rb", "test/spec_rack_rewindable_input.rb", "test/spec_rack_session_cookie.rb", "test/spec_rack_session_memcache.rb", "test/spec_rack_session_pool.rb", "test/spec_rack_showexceptions.rb", "test/spec_rack_showstatus.rb", "test/spec_rack_static.rb", "test/spec_rack_thin.rb", "test/spec_rack_urlmap.rb", "test/spec_rack_utils.rb", "test/spec_rack_webrick.rb"]
26
+ s.author = 'Christian Neukirchen'
27
+ s.email = 'chneukirchen@gmail.com'
28
+ s.homepage = 'http://rack.rubyforge.org'
29
+ s.rubyforge_project = 'rack'
23
30
 
24
- if s.respond_to? :specification_version then
25
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
- s.specification_version = 2
31
+ s.add_development_dependency 'test-spec'
27
32
 
28
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
- s.add_development_dependency(%q<test-spec>, [">= 0"])
30
- s.add_development_dependency(%q<camping>, [">= 0"])
31
- s.add_development_dependency(%q<fcgi>, [">= 0"])
32
- s.add_development_dependency(%q<memcache-client>, [">= 0"])
33
- s.add_development_dependency(%q<mongrel>, [">= 0"])
34
- s.add_development_dependency(%q<ruby-openid>, ["~> 2.0.0"])
35
- s.add_development_dependency(%q<thin>, [">= 0"])
36
- else
37
- s.add_dependency(%q<test-spec>, [">= 0"])
38
- s.add_dependency(%q<camping>, [">= 0"])
39
- s.add_dependency(%q<fcgi>, [">= 0"])
40
- s.add_dependency(%q<memcache-client>, [">= 0"])
41
- s.add_dependency(%q<mongrel>, [">= 0"])
42
- s.add_dependency(%q<ruby-openid>, ["~> 2.0.0"])
43
- s.add_dependency(%q<thin>, [">= 0"])
44
- end
45
- else
46
- s.add_dependency(%q<test-spec>, [">= 0"])
47
- s.add_dependency(%q<camping>, [">= 0"])
48
- s.add_dependency(%q<fcgi>, [">= 0"])
49
- s.add_dependency(%q<memcache-client>, [">= 0"])
50
- s.add_dependency(%q<mongrel>, [">= 0"])
51
- s.add_dependency(%q<ruby-openid>, ["~> 2.0.0"])
52
- s.add_dependency(%q<thin>, [">= 0"])
53
- end
33
+ s.add_development_dependency 'camping'
34
+ s.add_development_dependency 'fcgi'
35
+ s.add_development_dependency 'memcache-client'
36
+ s.add_development_dependency 'mongrel'
37
+ s.add_development_dependency 'thin'
54
38
  end
@@ -28,15 +28,13 @@ context "Rack::Cascade" do
28
28
  Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.not_found
29
29
  end
30
30
 
31
- specify "should fail if empty" do
32
- lambda { Rack::MockRequest.new(Rack::Cascade.new([])).get("/") }.
33
- should.raise(ArgumentError)
31
+ specify "should return 404 if empty" do
32
+ Rack::MockRequest.new(Rack::Cascade.new([])).get('/').should.be.not_found
34
33
  end
35
34
 
36
35
  specify "should append new app" do
37
36
  cascade = Rack::Cascade.new([], [404, 403])
38
- lambda { Rack::MockRequest.new(cascade).get('/cgi/test') }.
39
- should.raise(ArgumentError)
37
+ Rack::MockRequest.new(cascade).get('/').should.be.not_found
40
38
  cascade << app2
41
39
  Rack::MockRequest.new(cascade).get('/cgi/test').should.be.not_found
42
40
  Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.not_found
@@ -3,7 +3,7 @@ require 'testrequest'
3
3
 
4
4
  context "Rack::Handler::CGI" do
5
5
  include TestRequest::Helpers
6
-
6
+
7
7
  setup do
8
8
  @host = '0.0.0.0'
9
9
  @port = 9203
@@ -36,7 +36,7 @@ context "Rack::Handler::CGI" do
36
36
 
37
37
  specify "should have rack headers" do
38
38
  GET("/test")
39
- response["rack.version"].should.equal [1,0]
39
+ response["rack.version"].should.equal [1,1]
40
40
  response["rack.multithread"].should.be false
41
41
  response["rack.multiprocess"].should.be true
42
42
  response["rack.run_once"].should.be true
@@ -47,7 +47,7 @@ context "Rack::Handler::CGI" do
47
47
  response["REQUEST_METHOD"].should.equal "GET"
48
48
  response["SCRIPT_NAME"].should.equal "/test"
49
49
  response["REQUEST_PATH"].should.equal "/"
50
- response["PATH_INFO"].should.be.nil
50
+ response["PATH_INFO"].should.equal ""
51
51
  response["QUERY_STRING"].should.equal ""
52
52
  response["test.postdata"].should.equal ""
53
53
 
@@ -7,26 +7,55 @@ require 'rack/mock'
7
7
 
8
8
  context "Rack::CommonLogger" do
9
9
  app = lambda { |env|
10
+ [200,
11
+ {"Content-Type" => "text/html", "Content-Length" => length.to_s},
12
+ [obj]]}
13
+ app_without_length = lambda { |env|
10
14
  [200,
11
15
  {"Content-Type" => "text/html"},
12
- ["foo"]]}
16
+ []]}
17
+ app_with_zero_length = lambda { |env|
18
+ [200,
19
+ {"Content-Type" => "text/html", "Content-Length" => "0"},
20
+ []]}
13
21
 
14
22
  specify "should log to rack.errors by default" do
15
- log = StringIO.new
16
23
  res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
17
24
 
18
25
  res.errors.should.not.be.empty
19
- res.errors.should =~ /GET /
20
- res.errors.should =~ / 200 / # status
21
- res.errors.should =~ / 3 / # length
26
+ res.errors.should =~ /"GET \/ " 200 #{length} /
22
27
  end
23
28
 
24
- specify "should log to anything with <<" do
25
- log = ""
29
+ specify "should log to anything with +write+" do
30
+ log = StringIO.new
26
31
  res = Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
27
32
 
28
- log.should =~ /GET /
29
- log.should =~ / 200 / # status
30
- log.should =~ / 3 / # length
33
+ log.string.should =~ /"GET \/ " 200 #{length} /
34
+ end
35
+
36
+ specify "should log - content length if header is missing" do
37
+ res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
38
+
39
+ res.errors.should.not.be.empty
40
+ res.errors.should =~ /"GET \/ " 200 - /
41
+ end
42
+
43
+ specify "should log - content length if header is zero" do
44
+ res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
45
+
46
+ res.errors.should.not.be.empty
47
+ res.errors.should =~ /"GET \/ " 200 - /
48
+ end
49
+
50
+ def length
51
+ self.class.length
52
+ end
53
+
54
+ def self.length
55
+ 123
56
+ end
57
+
58
+ def self.obj
59
+ "hello world"
31
60
  end
32
61
  end
@@ -0,0 +1,24 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/builder'
4
+ require 'rack/content_length'
5
+ require 'rack/config'
6
+
7
+ context "Rack::Config" do
8
+
9
+ specify "should accept a block that modifies the environment" do
10
+ app = Rack::Builder.new do
11
+ use Rack::Lint
12
+ use Rack::ContentLength
13
+ use Rack::Config do |env|
14
+ env['greeting'] = 'hello'
15
+ end
16
+ run lambda { |env|
17
+ [200, {'Content-Type' => 'text/plain'}, [env['greeting'] || '']]
18
+ }
19
+ end
20
+ response = Rack::MockRequest.new(app).get('/')
21
+ response.body.should.equal('hello')
22
+ end
23
+
24
+ end
@@ -6,7 +6,7 @@ require 'rack/lint'
6
6
  require 'rack/mock'
7
7
 
8
8
  context "Rack::Directory" do
9
- DOCROOT = File.expand_path(File.dirname(__FILE__))
9
+ DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
10
10
  FILE_CATCH = proc{|env| [200, {'Content-Type'=>'text/plain', "Content-Length" => "7"}, ['passed!']] }
11
11
  app = Rack::Directory.new DOCROOT, FILE_CATCH
12
12
 
@@ -0,0 +1,17 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/etag'
4
+
5
+ context "Rack::ETag" do
6
+ specify "sets ETag if none is set" do
7
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
8
+ response = Rack::ETag.new(app).call({})
9
+ response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\""
10
+ end
11
+
12
+ specify "does not change ETag if it is already set" do
13
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] }
14
+ response = Rack::ETag.new(app).call({})
15
+ response[1]['ETag'].should.equal "\"abc\""
16
+ end
17
+ end
@@ -36,7 +36,7 @@ context "Rack::Handler::FastCGI" do
36
36
 
37
37
  specify "should have rack headers" do
38
38
  GET("/test.fcgi")
39
- response["rack.version"].should.equal [1,0]
39
+ response["rack.version"].should.equal [1,1]
40
40
  response["rack.multithread"].should.be false
41
41
  response["rack.multiprocess"].should.be true
42
42
  response["rack.run_once"].should.be false
@@ -47,7 +47,7 @@ context "Rack::Handler::FastCGI" do
47
47
  response["REQUEST_METHOD"].should.equal "GET"
48
48
  response["SCRIPT_NAME"].should.equal "/test.fcgi"
49
49
  response["REQUEST_PATH"].should.equal "/"
50
- response["PATH_INFO"].should.be.nil
50
+ response["PATH_INFO"].should.equal ""
51
51
  response["QUERY_STRING"].should.equal ""
52
52
  response["test.postdata"].should.equal ""
53
53
 
@@ -6,7 +6,7 @@ require 'rack/lint'
6
6
  require 'rack/mock'
7
7
 
8
8
  context "Rack::File" do
9
- DOCROOT = File.expand_path(File.dirname(__FILE__))
9
+ DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
10
10
 
11
11
  specify "serves files" do
12
12
  res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
@@ -71,6 +71,11 @@ context "Rack::Lint" do
71
71
  }.should.raise(Rack::Lint::LintError).
72
72
  message.should.equal("session [] must respond to store and []=")
73
73
 
74
+ lambda {
75
+ Rack::Lint.new(nil).call(env("rack.logger" => []))
76
+ }.should.raise(Rack::Lint::LintError).
77
+ message.should.equal("logger [] must respond to info")
78
+
74
79
  lambda {
75
80
  Rack::Lint.new(nil).call(env("REQUEST_METHOD" => "FUCKUP?"))
76
81
  }.should.raise(Rack::Lint::LintError).
@@ -110,7 +115,7 @@ context "Rack::Lint" do
110
115
  Rack::Lint.new(nil).call(env("rack.input" => ""))
111
116
  }.should.raise(Rack::Lint::LintError).
112
117
  message.should.match(/does not respond to #gets/)
113
-
118
+
114
119
  lambda {
115
120
  input = Object.new
116
121
  def input.binmode?
@@ -119,7 +124,7 @@ context "Rack::Lint" do
119
124
  Rack::Lint.new(nil).call(env("rack.input" => input))
120
125
  }.should.raise(Rack::Lint::LintError).
121
126
  message.should.match(/is not opened in binary mode/)
122
-
127
+
123
128
  lambda {
124
129
  input = Object.new
125
130
  def input.external_encoding
@@ -347,25 +352,25 @@ context "Rack::Lint" do
347
352
  yield 23
348
353
  yield 42
349
354
  end
350
-
355
+
351
356
  def rewind
352
357
  raise Errno::ESPIPE, "Errno::ESPIPE"
353
358
  end
354
359
  end
355
-
360
+
356
361
  eof_weirdio = Object.new
357
362
  class << eof_weirdio
358
363
  def gets
359
364
  nil
360
365
  end
361
-
366
+
362
367
  def read(*args)
363
368
  nil
364
369
  end
365
-
370
+
366
371
  def each
367
372
  end
368
-
373
+
369
374
  def rewind
370
375
  end
371
376
  end
@@ -452,48 +457,50 @@ context "Rack::Lint" do
452
457
  }.should.raise(Rack::Lint::LintError).
453
458
  message.should.match(/body was given for HEAD/)
454
459
  end
455
-
460
+
456
461
  specify "passes valid read calls" do
462
+ hello_str = "hello world"
463
+ hello_str.force_encoding("ASCII-8BIT") if hello_str.respond_to? :force_encoding
457
464
  lambda {
458
465
  Rack::Lint.new(lambda { |env|
459
466
  env["rack.input"].read
460
467
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
461
- }).call(env({"rack.input" => StringIO.new("hello world")}))
468
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
462
469
  }.should.not.raise(Rack::Lint::LintError)
463
-
470
+
464
471
  lambda {
465
472
  Rack::Lint.new(lambda { |env|
466
473
  env["rack.input"].read(0)
467
474
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
468
- }).call(env({"rack.input" => StringIO.new("hello world")}))
475
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
469
476
  }.should.not.raise(Rack::Lint::LintError)
470
-
477
+
471
478
  lambda {
472
479
  Rack::Lint.new(lambda { |env|
473
480
  env["rack.input"].read(1)
474
481
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
475
- }).call(env({"rack.input" => StringIO.new("hello world")}))
482
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
476
483
  }.should.not.raise(Rack::Lint::LintError)
477
-
484
+
478
485
  lambda {
479
486
  Rack::Lint.new(lambda { |env|
480
487
  env["rack.input"].read(nil)
481
488
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
482
- }).call(env({"rack.input" => StringIO.new("hello world")}))
489
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
483
490
  }.should.not.raise(Rack::Lint::LintError)
484
-
491
+
485
492
  lambda {
486
493
  Rack::Lint.new(lambda { |env|
487
494
  env["rack.input"].read(nil, '')
488
495
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
489
- }).call(env({"rack.input" => StringIO.new("hello world")}))
496
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
490
497
  }.should.not.raise(Rack::Lint::LintError)
491
-
498
+
492
499
  lambda {
493
500
  Rack::Lint.new(lambda { |env|
494
501
  env["rack.input"].read(1, '')
495
502
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
496
- }).call(env({"rack.input" => StringIO.new("hello world")}))
503
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
497
504
  }.should.not.raise(Rack::Lint::LintError)
498
505
  end
499
506
  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
@@ -93,6 +93,92 @@ context "Rack::MockRequest" do
93
93
  env["rack.url_scheme"].should.equal "https"
94
94
  end
95
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
+
96
182
  specify "should behave valid according to the Rack spec" do
97
183
  lambda {
98
184
  res = Rack::MockRequest.new(app).
@@ -130,7 +216,7 @@ context "Rack::MockResponse" do
130
216
  res.original_headers["Content-Type"].should.equal "text/yaml"
131
217
  res["Content-Type"].should.equal "text/yaml"
132
218
  res.content_type.should.equal "text/yaml"
133
- res.content_length.should.be 401 # needs change often.
219
+ res.content_length.should.be 414 # needs change often.
134
220
  res.location.should.be.nil
135
221
  end
136
222