rack 1.1.0 → 1.2.0

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 (101) hide show
  1. data/README +23 -26
  2. data/SPEC +3 -3
  3. data/lib/rack/auth/digest/params.rb +1 -1
  4. data/lib/rack/content_length.rb +1 -1
  5. data/lib/rack/etag.rb +15 -6
  6. data/lib/rack/file.rb +3 -1
  7. data/lib/rack/handler/cgi.rb +8 -7
  8. data/lib/rack/handler/fastcgi.rb +1 -1
  9. data/lib/rack/handler/lsws.rb +1 -1
  10. data/lib/rack/handler/mongrel.rb +1 -1
  11. data/lib/rack/handler/scgi.rb +1 -4
  12. data/lib/rack/handler/webrick.rb +10 -6
  13. data/lib/rack/lint.rb +29 -37
  14. data/lib/rack/mime.rb +2 -0
  15. data/lib/rack/mock.rb +2 -1
  16. data/lib/rack/recursive.rb +4 -0
  17. data/lib/rack/request.rb +8 -6
  18. data/lib/rack/response.rb +1 -0
  19. data/lib/rack/rewindable_input.rb +13 -10
  20. data/lib/rack/sendfile.rb +8 -6
  21. data/lib/rack/server.rb +66 -7
  22. data/lib/rack/session/memcache.rb +1 -1
  23. data/lib/rack/urlmap.rb +6 -7
  24. data/lib/rack/utils.rb +64 -22
  25. data/lib/rack.rb +1 -12
  26. data/rack.gemspec +6 -6
  27. data/spec/cgi/lighttpd.conf +25 -0
  28. data/spec/cgi/rackup_stub.rb +6 -0
  29. data/spec/cgi/sample_rackup.ru +5 -0
  30. data/spec/cgi/test +9 -0
  31. data/spec/cgi/test.fcgi +8 -0
  32. data/spec/cgi/test.ru +5 -0
  33. data/spec/multipart/bad_robots +259 -0
  34. data/spec/multipart/binary +0 -0
  35. data/spec/multipart/empty +10 -0
  36. data/spec/multipart/fail_16384_nofile +814 -0
  37. data/spec/multipart/file1.txt +1 -0
  38. data/spec/multipart/filename_and_modification_param +7 -0
  39. data/spec/multipart/filename_with_escaped_quotes +6 -0
  40. data/spec/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
  41. data/spec/multipart/filename_with_percent_escaped_quotes +6 -0
  42. data/spec/multipart/filename_with_unescaped_quotes +6 -0
  43. data/spec/multipart/ie +6 -0
  44. data/spec/multipart/nested +10 -0
  45. data/spec/multipart/none +9 -0
  46. data/spec/multipart/semicolon +6 -0
  47. data/spec/multipart/text +10 -0
  48. data/spec/rackup/config.ru +31 -0
  49. data/{test/spec_rack_auth_basic.rb → spec/spec_auth_basic.rb} +11 -14
  50. data/{test/spec_rack_auth_digest.rb → spec/spec_auth_digest.rb} +18 -21
  51. data/{test/spec_rack_builder.rb → spec/spec_builder.rb} +49 -10
  52. data/{test/spec_rack_cascade.rb → spec/spec_cascade.rb} +7 -10
  53. data/{test/spec_rack_cgi.rb → spec/spec_cgi.rb} +34 -32
  54. data/{test/spec_rack_chunked.rb → spec/spec_chunked.rb} +8 -10
  55. data/{test/spec_rack_commonlogger.rb → spec/spec_commonlogger.rb} +10 -15
  56. data/{test/spec_rack_conditionalget.rb → spec/spec_conditionalget.rb} +5 -7
  57. data/{test/spec_rack_config.rb → spec/spec_config.rb} +6 -7
  58. data/{test/spec_rack_content_length.rb → spec/spec_content_length.rb} +7 -8
  59. data/{test/spec_rack_content_type.rb → spec/spec_content_type.rb} +5 -6
  60. data/{test/spec_rack_deflater.rb → spec/spec_deflater.rb} +11 -13
  61. data/{test/spec_rack_directory.rb → spec/spec_directory.rb} +6 -10
  62. data/{test/spec_rack_etag.rb → spec/spec_etag.rb} +3 -5
  63. data/{test/spec_rack_fastcgi.rb → spec/spec_fastcgi.rb} +36 -29
  64. data/{test/spec_rack_file.rb → spec/spec_file.rb} +9 -13
  65. data/{test/spec_rack_handler.rb → spec/spec_handler.rb} +10 -12
  66. data/{test/spec_rack_head.rb → spec/spec_head.rb} +3 -3
  67. data/{test/spec_rack_lint.rb → spec/spec_lint.rb} +19 -32
  68. data/{test/spec_rack_lobster.rb → spec/spec_lobster.rb} +9 -11
  69. data/{test/spec_rack_lock.rb → spec/spec_lock.rb} +15 -17
  70. data/{test/spec_rack_logger.rb → spec/spec_logger.rb} +6 -7
  71. data/{test/spec_rack_methodoverride.rb → spec/spec_methodoverride.rb} +15 -17
  72. data/{test/spec_rack_mock.rb → spec/spec_mock.rb} +30 -32
  73. data/{test/spec_rack_mongrel.rb → spec/spec_mongrel.rb} +40 -46
  74. data/{test/spec_rack_nulllogger.rb → spec/spec_nulllogger.rb} +4 -5
  75. data/{test/spec_rack_recursive.rb → spec/spec_recursive.rb} +28 -36
  76. data/{test/spec_rack_request.rb → spec/spec_request.rb} +84 -49
  77. data/{test/spec_rack_response.rb → spec/spec_response.rb} +48 -29
  78. data/spec/spec_rewindable_input.rb +118 -0
  79. data/{test/spec_rack_runtime.rb → spec/spec_runtime.rb} +15 -11
  80. data/{test/spec_rack_sendfile.rb → spec/spec_sendfile.rb} +11 -14
  81. data/{test/spec_rack_session_cookie.rb → spec/spec_session_cookie.rb} +15 -18
  82. data/{test/spec_rack_session_memcache.rb → spec/spec_session_memcache.rb} +32 -26
  83. data/{test/spec_rack_session_pool.rb → spec/spec_session_pool.rb} +36 -31
  84. data/spec/spec_showexceptions.rb +23 -0
  85. data/spec/spec_showstatus.rb +79 -0
  86. data/{test/spec_rack_static.rb → spec/spec_static.rb} +5 -9
  87. data/{test/spec_rack_thin.rb → spec/spec_thin.rb} +30 -35
  88. data/{test/spec_rack_urlmap.rb → spec/spec_urlmap.rb} +6 -8
  89. data/{test/spec_rack_utils.rb → spec/spec_utils.rb} +136 -71
  90. data/{test/spec_rack_webrick.rb → spec/spec_webrick.rb} +28 -36
  91. data/spec/testrequest.rb +77 -0
  92. data/spec/unregistered_handler/rack/handler/unregistered.rb +7 -0
  93. data/spec/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
  94. metadata +206 -124
  95. data/RDOX +0 -0
  96. data/lib/rack/adapter/camping.rb +0 -22
  97. data/test/spec_rack_camping.rb +0 -51
  98. data/test/spec_rack_rewindable_input.rb +0 -118
  99. data/test/spec_rack_showexceptions.rb +0 -21
  100. data/test/spec_rack_showstatus.rb +0 -72
  101. data/test/spec_rackup.rb +0 -154
@@ -1,37 +1,32 @@
1
- require 'test/spec'
2
-
3
1
  begin
2
+ require 'rack'
4
3
  require 'rack/handler/mongrel'
5
- require 'rack/urlmap'
6
- require 'rack/lint'
7
- require 'testrequest'
4
+ require File.expand_path('../testrequest', __FILE__)
8
5
  require 'timeout'
9
6
 
10
7
  Thread.abort_on_exception = true
11
8
  $tcp_defer_accept_opts = nil
12
9
  $tcp_cork_opts = nil
13
10
 
14
- context "Rack::Handler::Mongrel" do
15
- include TestRequest::Helpers
11
+ describe Rack::Handler::Mongrel do
12
+ extend TestRequest::Helpers
16
13
 
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
14
+ @server = Mongrel::HttpServer.new(@host='0.0.0.0', @port=9201)
15
+ @server.register('/test',
16
+ Rack::Handler::Mongrel.new(Rack::Lint.new(TestRequest.new)))
17
+ @server.register('/stream',
18
+ Rack::Handler::Mongrel.new(Rack::Lint.new(StreamingRequest)))
19
+ @acc = @server.run
25
20
 
26
- specify "should respond" do
21
+ should "respond" do
27
22
  lambda {
28
23
  GET("/test")
29
24
  }.should.not.raise
30
25
  end
31
26
 
32
- specify "should be a Mongrel" do
27
+ should "be a Mongrel" do
33
28
  GET("/test")
34
- status.should.be 200
29
+ status.should.equal 200
35
30
  response["SERVER_SOFTWARE"].should =~ /Mongrel/
36
31
  response["HTTP_VERSION"].should.equal "HTTP/1.1"
37
32
  response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
@@ -39,15 +34,15 @@ context "Rack::Handler::Mongrel" do
39
34
  response["SERVER_NAME"].should.equal "0.0.0.0"
40
35
  end
41
36
 
42
- specify "should have rack headers" do
37
+ should "have rack headers" do
43
38
  GET("/test")
44
39
  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
40
+ response["rack.multithread"].should.be.true
41
+ response["rack.multiprocess"].should.be.false
42
+ response["rack.run_once"].should.be.false
48
43
  end
49
44
 
50
- specify "should have CGI headers on GET" do
45
+ should "have CGI headers on GET" do
51
46
  GET("/test")
52
47
  response["REQUEST_METHOD"].should.equal "GET"
53
48
  response["SCRIPT_NAME"].should.equal "/test"
@@ -64,7 +59,7 @@ context "Rack::Handler::Mongrel" do
64
59
  response["QUERY_STRING"].should.equal "quux=1"
65
60
  end
66
61
 
67
- specify "should have CGI headers on POST" do
62
+ should "have CGI headers on POST" do
68
63
  POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
69
64
  status.should.equal 200
70
65
  response["REQUEST_METHOD"].should.equal "POST"
@@ -75,18 +70,18 @@ context "Rack::Handler::Mongrel" do
75
70
  response["test.postdata"].should.equal "rack-form-data=23"
76
71
  end
77
72
 
78
- specify "should support HTTP auth" do
73
+ should "support HTTP auth" do
79
74
  GET("/test", {:user => "ruth", :passwd => "secret"})
80
75
  response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
81
76
  end
82
77
 
83
- specify "should set status" do
78
+ should "set status" do
84
79
  GET("/test?secret")
85
80
  status.should.equal 403
86
81
  response["rack.url_scheme"].should.equal "http"
87
82
  end
88
83
 
89
- specify "should provide a .run" do
84
+ should "provide a .run" do
90
85
  block_ran = false
91
86
  Thread.new {
92
87
  Rack::Handler::Mongrel.run(lambda {}, {:Port => 9211}) { |server|
@@ -95,16 +90,16 @@ context "Rack::Handler::Mongrel" do
95
90
  }
96
91
  }
97
92
  sleep 1
98
- block_ran.should.be true
93
+ block_ran.should.be.true
99
94
  end
100
95
 
101
- specify "should provide a .run that maps a hash" do
96
+ should "provide a .run that maps a hash" do
102
97
  block_ran = false
103
98
  Thread.new {
104
99
  map = {'/'=>lambda{},'/foo'=>lambda{}}
105
100
  Rack::Handler::Mongrel.run(map, :map => true, :Port => 9221) { |server|
106
101
  server.should.be.kind_of Mongrel::HttpServer
107
- server.classifier.uris.size.should.be 2
102
+ server.classifier.uris.size.should.equal 2
108
103
  server.classifier.uris.should.not.include '/arf'
109
104
  server.classifier.uris.should.include '/'
110
105
  server.classifier.uris.should.include '/foo'
@@ -112,16 +107,16 @@ context "Rack::Handler::Mongrel" do
112
107
  }
113
108
  }
114
109
  sleep 1
115
- block_ran.should.be true
110
+ block_ran.should.be.true
116
111
  end
117
112
 
118
- specify "should provide a .run that maps a urlmap" do
113
+ should "provide a .run that maps a urlmap" do
119
114
  block_ran = false
120
115
  Thread.new {
121
116
  map = Rack::URLMap.new({'/'=>lambda{},'/bar'=>lambda{}})
122
117
  Rack::Handler::Mongrel.run(map, {:map => true, :Port => 9231}) { |server|
123
118
  server.should.be.kind_of Mongrel::HttpServer
124
- server.classifier.uris.size.should.be 2
119
+ server.classifier.uris.size.should.equal 2
125
120
  server.classifier.uris.should.not.include '/arf'
126
121
  server.classifier.uris.should.include '/'
127
122
  server.classifier.uris.should.include '/bar'
@@ -129,10 +124,10 @@ context "Rack::Handler::Mongrel" do
129
124
  }
130
125
  }
131
126
  sleep 1
132
- block_ran.should.be true
127
+ block_ran.should.be.true
133
128
  end
134
129
 
135
- specify "should provide a .run that maps a urlmap restricting by host" do
130
+ should "provide a .run that maps a urlmap restricting by host" do
136
131
  block_ran = false
137
132
  Thread.new {
138
133
  map = Rack::URLMap.new({
@@ -148,22 +143,22 @@ context "Rack::Handler::Mongrel" do
148
143
  Rack::Handler::Mongrel.run(map, opt) { |server|
149
144
  server.should.be.kind_of Mongrel::HttpServer
150
145
  server.classifier.uris.should.include '/'
151
- server.classifier.handler_map['/'].size.should.be 2
146
+ server.classifier.handler_map['/'].size.should.equal 2
152
147
  server.classifier.uris.should.include '/foo'
153
- server.classifier.handler_map['/foo'].size.should.be 1
148
+ server.classifier.handler_map['/foo'].size.should.equal 1
154
149
  server.classifier.uris.should.include '/bar'
155
- server.classifier.handler_map['/bar'].size.should.be 2
150
+ server.classifier.handler_map['/bar'].size.should.equal 2
156
151
  server.classifier.uris.should.not.include '/qux'
157
152
  server.classifier.uris.should.not.include '/arf'
158
- server.classifier.uris.size.should.be 3
153
+ server.classifier.uris.size.should.equal 3
159
154
  block_ran = true
160
155
  }
161
156
  }
162
157
  sleep 1
163
- block_ran.should.be true
158
+ block_ran.should.be.true
164
159
  end
165
160
 
166
- specify "should stream #each part of the response" do
161
+ should "stream #each part of the response" do
167
162
  body = ''
168
163
  begin
169
164
  Timeout.timeout(1) do
@@ -179,11 +174,10 @@ context "Rack::Handler::Mongrel" do
179
174
  body.should.not.be.empty
180
175
  end
181
176
 
182
- teardown do
183
- @acc.raise Mongrel::StopServer
184
- end
177
+ @acc.raise Mongrel::StopServer
185
178
  end
186
179
 
187
- rescue LoadError
188
- $stderr.puts "Skipping Rack::Handler::Mongrel tests (Mongrel is required). `gem install mongrel` and try again."
180
+ rescue LoadError => ex
181
+ warn ex
182
+ warn "Skipping Rack::Handler::Mongrel tests (Mongrel is required). `gem install mongrel` and try again."
189
183
  end
@@ -1,13 +1,12 @@
1
1
  require 'rack/nulllogger'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
2
 
5
- context "Rack::NullLogger" do
6
- specify "acks as a nop logger" do
3
+ describe Rack::NullLogger do
4
+ should "act as a noop logger" do
7
5
  app = lambda { |env|
8
6
  env['rack.logger'].warn "b00m"
9
7
  [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
10
8
  }
11
- Rack::NullLogger.new(app).call({})
9
+ logger = Rack::NullLogger.new(app)
10
+ lambda{ logger.call({}) }.should.not.raise
12
11
  end
13
12
  end
@@ -1,53 +1,45 @@
1
- require 'test/spec'
2
-
3
1
  require 'rack/recursive'
4
- require 'rack/urlmap'
5
- require 'rack/response'
6
2
  require 'rack/mock'
7
3
 
8
- context "Rack::Recursive" do
9
- setup do
10
-
11
- @app1 = lambda { |env|
12
- res = Rack::Response.new
13
- res["X-Path-Info"] = env["PATH_INFO"]
14
- res["X-Query-String"] = env["QUERY_STRING"]
15
- res.finish do |res|
16
- res.write "App1"
17
- end
18
- }
4
+ describe Rack::Recursive do
5
+ @app1 = lambda { |env|
6
+ res = Rack::Response.new
7
+ res["X-Path-Info"] = env["PATH_INFO"]
8
+ res["X-Query-String"] = env["QUERY_STRING"]
9
+ res.finish do |inner_res|
10
+ inner_res.write "App1"
11
+ end
12
+ }
19
13
 
20
- @app2 = lambda { |env|
21
- Rack::Response.new.finish do |res|
22
- res.write "App2"
23
- _, _, body = env['rack.recursive.include'].call(env, "/app1")
24
- body.each { |b|
25
- res.write b
26
- }
27
- end
28
- }
14
+ @app2 = lambda { |env|
15
+ Rack::Response.new.finish do |res|
16
+ res.write "App2"
17
+ _, _, body = env['rack.recursive.include'].call(env, "/app1")
18
+ body.each { |b|
19
+ res.write b
20
+ }
21
+ end
22
+ }
29
23
 
30
- @app3 = lambda { |env|
31
- raise Rack::ForwardRequest.new("/app1")
32
- }
24
+ @app3 = lambda { |env|
25
+ raise Rack::ForwardRequest.new("/app1")
26
+ }
33
27
 
34
- @app4 = lambda { |env|
35
- raise Rack::ForwardRequest.new("http://example.org/app1/quux?meh")
36
- }
37
-
38
- end
28
+ @app4 = lambda { |env|
29
+ raise Rack::ForwardRequest.new("http://example.org/app1/quux?meh")
30
+ }
39
31
 
40
- specify "should allow for subrequests" do
32
+ should "allow for subrequests" do
41
33
  res = Rack::MockRequest.new(Rack::Recursive.new(
42
34
  Rack::URLMap.new("/app1" => @app1,
43
35
  "/app2" => @app2))).
44
36
  get("/app2")
45
37
 
46
38
  res.should.be.ok
47
- res.body.should.equal "App2App1"
39
+ res.body.should.equal "App2App1"
48
40
  end
49
41
 
50
- specify "should raise error on requests not below the app" do
42
+ should "raise error on requests not below the app" do
51
43
  app = Rack::URLMap.new("/app1" => @app1,
52
44
  "/app" => Rack::Recursive.new(
53
45
  Rack::URLMap.new("/1" => @app1,
@@ -59,7 +51,7 @@ context "Rack::Recursive" do
59
51
  message.should =~ /can only include below/
60
52
  end
61
53
 
62
- specify "should support forwarding" do
54
+ should "support forwarding" do
63
55
  app = Rack::Recursive.new(Rack::URLMap.new("/app1" => @app1,
64
56
  "/app3" => @app3,
65
57
  "/app4" => @app4))
@@ -1,11 +1,10 @@
1
- require 'test/spec'
2
1
  require 'stringio'
3
-
2
+ require 'cgi'
4
3
  require 'rack/request'
5
4
  require 'rack/mock'
6
5
 
7
- context "Rack::Request" do
8
- specify "wraps the rack variables" do
6
+ describe Rack::Request do
7
+ should "wrap the rack variables" do
9
8
  req = Rack::Request.new(Rack::MockRequest.env_for("http://example.com:8080/"))
10
9
 
11
10
  req.body.should.respond_to? :gets
@@ -29,7 +28,7 @@ context "Rack::Request" do
29
28
  req.content_type.should.be.nil
30
29
  end
31
30
 
32
- specify "can figure out the correct host" do
31
+ should "figure out the correct host" do
33
32
  req = Rack::Request.new \
34
33
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
35
34
  req.host.should.equal "www2.example.org"
@@ -53,7 +52,7 @@ context "Rack::Request" do
53
52
  req.host.should.equal ""
54
53
  end
55
54
 
56
- specify "can parse the query string" do
55
+ should "parse the query string" do
57
56
  req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
58
57
  req.query_string.should.equal "foo=bar&quux=bla"
59
58
  req.GET.should.equal "foo" => "bar", "quux" => "bla"
@@ -61,12 +60,12 @@ context "Rack::Request" do
61
60
  req.params.should.equal "foo" => "bar", "quux" => "bla"
62
61
  end
63
62
 
64
- specify "raises if rack.input is missing" do
63
+ should "raise if rack.input is missing" do
65
64
  req = Rack::Request.new({})
66
65
  lambda { req.POST }.should.raise(RuntimeError)
67
66
  end
68
67
 
69
- specify "can parse POST data when method is POST and no Content-Type given" do
68
+ should "parse POST data when method is POST and no Content-Type given" do
70
69
  req = Rack::Request.new \
71
70
  Rack::MockRequest.env_for("/?foo=quux",
72
71
  "REQUEST_METHOD" => 'POST',
@@ -79,7 +78,7 @@ context "Rack::Request" do
79
78
  req.params.should.equal "foo" => "bar", "quux" => "bla"
80
79
  end
81
80
 
82
- specify "can parse POST data with explicit content type regardless of method" do
81
+ should "parse POST data with explicit content type regardless of method" do
83
82
  req = Rack::Request.new \
84
83
  Rack::MockRequest.env_for("/",
85
84
  "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
@@ -91,7 +90,7 @@ context "Rack::Request" do
91
90
  req.params.should.equal "foo" => "bar", "quux" => "bla"
92
91
  end
93
92
 
94
- specify "does not parse POST data when media type is not form-data" do
93
+ should "not parse POST data when media type is not form-data" do
95
94
  req = Rack::Request.new \
96
95
  Rack::MockRequest.env_for("/?foo=quux",
97
96
  "REQUEST_METHOD" => 'POST',
@@ -105,7 +104,7 @@ context "Rack::Request" do
105
104
  req.body.read.should.equal "foo=bar&quux=bla"
106
105
  end
107
106
 
108
- specify "can parse POST data on PUT when media type is form-data" do
107
+ should "parse POST data on PUT when media type is form-data" do
109
108
  req = Rack::Request.new \
110
109
  Rack::MockRequest.env_for("/?foo=quux",
111
110
  "REQUEST_METHOD" => 'PUT',
@@ -115,7 +114,7 @@ context "Rack::Request" do
115
114
  req.body.read.should.equal "foo=bar&quux=bla"
116
115
  end
117
116
 
118
- specify "rewinds input after parsing POST data" do
117
+ should "rewind input after parsing POST data" do
119
118
  input = StringIO.new("foo=bar&quux=bla")
120
119
  req = Rack::Request.new \
121
120
  Rack::MockRequest.env_for("/",
@@ -125,21 +124,21 @@ context "Rack::Request" do
125
124
  input.read.should.equal "foo=bar&quux=bla"
126
125
  end
127
126
 
128
- specify "cleans up Safari's ajax POST body" do
127
+ should "clean up Safari's ajax POST body" do
129
128
  req = Rack::Request.new \
130
129
  Rack::MockRequest.env_for("/",
131
130
  'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0")
132
131
  req.POST.should.equal "foo" => "bar", "quux" => "bla"
133
132
  end
134
133
 
135
- specify "can get value by key from params with #[]" do
134
+ should "get value by key from params with #[]" do
136
135
  req = Rack::Request.new \
137
136
  Rack::MockRequest.env_for("?foo=quux")
138
137
  req['foo'].should.equal 'quux'
139
138
  req[:foo].should.equal 'quux'
140
139
  end
141
140
 
142
- specify "can set value to key on params with #[]=" do
141
+ should "set value to key on params with #[]=" do
143
142
  req = Rack::Request.new \
144
143
  Rack::MockRequest.env_for("?foo=duh")
145
144
  req['foo'].should.equal 'duh'
@@ -157,7 +156,7 @@ context "Rack::Request" do
157
156
  req[:foo].should.equal 'jaz'
158
157
  end
159
158
 
160
- specify "values_at answers values by keys in order given" do
159
+ should "return values for the keys in the order given from values_at" do
161
160
  req = Rack::Request.new \
162
161
  Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful")
163
162
  req.values_at('foo').should.equal ['baz']
@@ -165,7 +164,7 @@ context "Rack::Request" do
165
164
  req.values_at('bar', 'foo', 'wun').should.equal ['ful', 'baz', 'der']
166
165
  end
167
166
 
168
- specify "referrer should be extracted correct" do
167
+ should "extract referrer correctly" do
169
168
  req = Rack::Request.new \
170
169
  Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path")
171
170
  req.referer.should.equal "/some/path"
@@ -175,7 +174,7 @@ context "Rack::Request" do
175
174
  req.referer.should.equal "/"
176
175
  end
177
176
 
178
- specify "user agent should be extracted correct" do
177
+ should "extract user agent correctly" do
179
178
  req = Rack::Request.new \
180
179
  Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)")
181
180
  req.user_agent.should.equal "Mozilla/4.0 (compatible)"
@@ -185,7 +184,7 @@ context "Rack::Request" do
185
184
  req.user_agent.should.equal nil
186
185
  end
187
186
 
188
- specify "can cache, but invalidates the cache" do
187
+ should "cache, but invalidates the cache" do
189
188
  req = Rack::Request.new \
190
189
  Rack::MockRequest.env_for("/?foo=quux",
191
190
  "CONTENT_TYPE" => "application/x-www-form-urlencoded",
@@ -203,7 +202,7 @@ context "Rack::Request" do
203
202
  req.POST.should.equal "foo" => "bla", "quux" => "bar"
204
203
  end
205
204
 
206
- specify "can figure out if called via XHR" do
205
+ should "figure out if called via XHR" do
207
206
  req = Rack::Request.new(Rack::MockRequest.env_for(""))
208
207
  req.should.not.be.xhr
209
208
 
@@ -212,7 +211,7 @@ context "Rack::Request" do
212
211
  req.should.be.xhr
213
212
  end
214
213
 
215
- specify "can parse cookies" do
214
+ should "parse cookies" do
216
215
  req = Rack::Request.new \
217
216
  Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
218
217
  req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
@@ -221,13 +220,13 @@ context "Rack::Request" do
221
220
  req.cookies.should.equal({})
222
221
  end
223
222
 
224
- specify "parses cookies according to RFC 2109" do
223
+ should "parse cookies according to RFC 2109" do
225
224
  req = Rack::Request.new \
226
225
  Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car')
227
226
  req.cookies.should.equal 'foo' => 'bar'
228
227
  end
229
228
 
230
- specify "provides setters" do
229
+ should "provide setters" do
231
230
  req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
232
231
  req.script_name.should.equal ""
233
232
  req.script_name = "/foo"
@@ -240,12 +239,12 @@ context "Rack::Request" do
240
239
  e["PATH_INFO"].should.equal "/foo"
241
240
  end
242
241
 
243
- specify "provides the original env" do
244
- req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
245
- req.env.should.be e
242
+ should "provide the original env" do
243
+ req = Rack::Request.new(e = Rack::MockRequest.env_for(""))
244
+ req.env.should == e
246
245
  end
247
246
 
248
- specify "can restore the URL" do
247
+ should "restore the URL" do
249
248
  Rack::Request.new(Rack::MockRequest.env_for("")).url.
250
249
  should.equal "http://example.org/"
251
250
  Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url.
@@ -263,7 +262,7 @@ context "Rack::Request" do
263
262
  should.equal "https://example.com:8080/foo?foo"
264
263
  end
265
264
 
266
- specify "can restore the full path" do
265
+ should "restore the full path" do
267
266
  Rack::Request.new(Rack::MockRequest.env_for("")).fullpath.
268
267
  should.equal "/"
269
268
  Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath.
@@ -281,7 +280,7 @@ context "Rack::Request" do
281
280
  should.equal "/foo?foo"
282
281
  end
283
282
 
284
- specify "can handle multiple media type parameters" do
283
+ should "handle multiple media type parameters" do
285
284
  req = Rack::Request.new \
286
285
  Rack::MockRequest.env_for("/",
287
286
  "CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam')
@@ -295,7 +294,7 @@ context "Rack::Request" do
295
294
  req.media_type_params['bling'].should.equal 'bam'
296
295
  end
297
296
 
298
- specify "can parse multipart form data" do
297
+ should "parse multipart form data" do
299
298
  # Adapted from RFC 1867.
300
299
  input = <<EOF
301
300
  --AaB03x\r
@@ -334,7 +333,7 @@ EOF
334
333
  f[:tempfile].size.should.equal 76
335
334
  end
336
335
 
337
- specify "can parse big multipart form data" do
336
+ should "parse big multipart form data" do
338
337
  input = <<EOF
339
338
  --AaB03x\r
340
339
  content-disposition: form-data; name="huge"; filename="huge"\r
@@ -356,7 +355,7 @@ EOF
356
355
  req.POST["mean"][:tempfile].read.should.equal "--AaB03xha"
357
356
  end
358
357
 
359
- specify "can detect invalid multipart form data" do
358
+ should "detect invalid multipart form data" do
360
359
  input = <<EOF
361
360
  --AaB03x\r
362
361
  content-disposition: form-data; name="huge"; filename="huge"\r
@@ -395,12 +394,33 @@ EOF
395
394
  lambda { req.POST }.should.raise(EOFError)
396
395
  end
397
396
 
398
- specify "shouldn't try to interpret binary as utf8" do
399
- begin
400
- original_kcode = $KCODE
401
- $KCODE='UTF8'
397
+ should "not try to interpret binary as utf8" do
398
+ if /regexp/.respond_to?(:kcode) # < 1.9
399
+ begin
400
+ original_kcode = $KCODE
401
+ $KCODE='UTF8'
402
+
403
+ input = <<EOF
404
+ --AaB03x\r
405
+ content-disposition: form-data; name="fileupload"; filename="junk.a"\r
406
+ content-type: application/octet-stream\r
407
+ \r
408
+ #{[0x36,0xCF,0x0A,0xF8].pack('c*')}\r
409
+ --AaB03x--\r
410
+ EOF
402
411
 
403
- input = <<EOF
412
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
413
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
414
+ "CONTENT_LENGTH" => input.size,
415
+ :input => input)
416
+
417
+ lambda{req.POST}.should.not.raise(EOFError)
418
+ req.POST["fileupload"][:tempfile].size.should.equal 4
419
+ ensure
420
+ $KCODE = original_kcode
421
+ end
422
+ else # >= 1.9
423
+ input = <<EOF
404
424
  --AaB03x\r
405
425
  content-disposition: form-data; name="fileupload"; filename="junk.a"\r
406
426
  content-type: application/octet-stream\r
@@ -416,13 +436,10 @@ EOF
416
436
 
417
437
  lambda{req.POST}.should.not.raise(EOFError)
418
438
  req.POST["fileupload"][:tempfile].size.should.equal 4
419
- ensure
420
- $KCODE = original_kcode
421
439
  end
422
440
  end
423
441
 
424
-
425
- specify "should work around buggy 1.8.* Tempfile equality" do
442
+ should "work around buggy 1.8.* Tempfile equality" do
426
443
  input = <<EOF
427
444
  --AaB03x\r
428
445
  content-disposition: form-data; name="huge"; filename="huge"\r
@@ -440,11 +457,11 @@ EOF
440
457
  "CONTENT_LENGTH" => input.size,
441
458
  :input => rack_input)
442
459
 
443
- lambda {req.POST}.should.not.raise
444
- lambda {req.POST}.should.blaming("input re-processed!").not.raise
460
+ lambda{ req.POST }.should.not.raise
461
+ lambda{ req.POST }.should.not.raise("input re-processed!")
445
462
  end
446
463
 
447
- specify "does conform to the Rack spec" do
464
+ should "conform to the Rack spec" do
448
465
  app = lambda { |env|
449
466
  content = Rack::Request.new(env).POST["file"].inspect
450
467
  size = content.respond_to?(:bytesize) ? content.bytesize : content.size
@@ -472,7 +489,7 @@ EOF
472
489
  res.should.be.ok
473
490
  end
474
491
 
475
- specify "should parse Accept-Encoding correctly" do
492
+ should "parse Accept-Encoding correctly" do
476
493
  parser = lambda do |x|
477
494
  Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
478
495
  end
@@ -488,7 +505,7 @@ EOF
488
505
  lambda { parser.call("gzip ; q=1.0") }.should.raise(RuntimeError)
489
506
  end
490
507
 
491
- specify 'should provide ip information' do
508
+ should 'provide ip information' do
492
509
  app = lambda { |env|
493
510
  request = Rack::Request.new(env)
494
511
  response = Rack::Response.new
@@ -510,7 +527,13 @@ EOF
510
527
  'REMOTE_ADDR' => '123.123.123.123',
511
528
  'HTTP_X_FORWARDED_FOR' => '234.234.234.234,212.212.212.212'
512
529
 
513
- res.body.should.equal '212.212.212.212'
530
+ res.body.should.equal '234.234.234.234'
531
+
532
+ res = mock.get '/',
533
+ 'REMOTE_ADDR' => '123.123.123.123',
534
+ 'HTTP_X_FORWARDED_FOR' => 'unknown,234.234.234.234,212.212.212.212'
535
+
536
+ res.body.should.equal '234.234.234.234'
514
537
  end
515
538
 
516
539
  class MyRequest < Rack::Request
@@ -519,7 +542,7 @@ EOF
519
542
  end
520
543
  end
521
544
 
522
- specify "should allow subclass request to be instantiated after parent request" do
545
+ should "allow subclass request to be instantiated after parent request" do
523
546
  env = Rack::MockRequest.env_for("/?foo=bar")
524
547
 
525
548
  req1 = Rack::Request.new(env)
@@ -531,7 +554,7 @@ EOF
531
554
  req2.params.should.equal :foo => "bar"
532
555
  end
533
556
 
534
- specify "should allow parent request to be instantiated after subclass request" do
557
+ should "allow parent request to be instantiated after subclass request" do
535
558
  env = Rack::MockRequest.env_for("/?foo=bar")
536
559
 
537
560
  req1 = MyRequest.new(env)
@@ -542,4 +565,16 @@ EOF
542
565
  req2.GET.should.equal "foo" => "bar"
543
566
  req2.params.should.equal "foo" => "bar"
544
567
  end
568
+
569
+ (0x20...0x7E).collect { |a|
570
+ b = a.chr
571
+ c = CGI.escape(b)
572
+ should "not strip '#{a}' => '#{c}' => '#{b}' escaped character from parameters when accessed as string" do
573
+ url = "/?foo=#{c}bar#{c}"
574
+ env = Rack::MockRequest.env_for(url)
575
+ req2 = Rack::Request.new(env)
576
+ req2.GET.should.equal "foo" => "#{b}bar#{b}"
577
+ req2.params.should.equal "foo" => "#{b}bar#{b}"
578
+ end
579
+ }
545
580
  end