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.
- data/COPYING +1 -1
- data/KNOWN-ISSUES +3 -0
- data/RDOX +0 -428
- data/README +61 -26
- data/SPEC +8 -1
- data/bin/rackup +2 -174
- data/lib/rack.rb +10 -8
- data/lib/rack/builder.rb +17 -0
- data/lib/rack/cascade.rb +17 -12
- data/lib/rack/chunked.rb +2 -2
- data/lib/rack/commonlogger.rb +31 -43
- data/lib/rack/config.rb +15 -0
- data/lib/rack/content_type.rb +1 -1
- data/lib/rack/directory.rb +6 -2
- data/lib/rack/etag.rb +23 -0
- data/lib/rack/file.rb +4 -2
- data/lib/rack/handler.rb +19 -0
- data/lib/rack/handler/cgi.rb +1 -1
- data/lib/rack/handler/fastcgi.rb +2 -3
- data/lib/rack/handler/lsws.rb +4 -1
- data/lib/rack/handler/mongrel.rb +8 -5
- data/lib/rack/handler/scgi.rb +4 -4
- data/lib/rack/handler/webrick.rb +2 -4
- data/lib/rack/lint.rb +44 -15
- data/lib/rack/logger.rb +20 -0
- data/lib/rack/mime.rb +3 -1
- data/lib/rack/mock.rb +30 -4
- data/lib/rack/nulllogger.rb +18 -0
- data/lib/rack/reloader.rb +4 -1
- data/lib/rack/request.rb +40 -15
- data/lib/rack/response.rb +5 -39
- data/lib/rack/runtime.rb +27 -0
- data/lib/rack/sendfile.rb +142 -0
- data/lib/rack/server.rb +212 -0
- data/lib/rack/session/abstract/id.rb +3 -5
- data/lib/rack/session/cookie.rb +3 -4
- data/lib/rack/session/memcache.rb +53 -43
- data/lib/rack/session/pool.rb +1 -1
- data/lib/rack/urlmap.rb +9 -8
- data/lib/rack/utils.rb +230 -11
- data/rack.gemspec +33 -49
- data/test/spec_rack_cascade.rb +3 -5
- data/test/spec_rack_cgi.rb +3 -3
- data/test/spec_rack_commonlogger.rb +39 -10
- data/test/spec_rack_config.rb +24 -0
- data/test/spec_rack_directory.rb +1 -1
- data/test/spec_rack_etag.rb +17 -0
- data/test/spec_rack_fastcgi.rb +2 -2
- data/test/spec_rack_file.rb +1 -1
- data/test/spec_rack_lint.rb +26 -19
- data/test/spec_rack_logger.rb +21 -0
- data/test/spec_rack_mock.rb +87 -1
- data/test/spec_rack_mongrel.rb +4 -4
- data/test/spec_rack_nulllogger.rb +13 -0
- data/test/spec_rack_request.rb +47 -6
- data/test/spec_rack_response.rb +3 -0
- data/test/spec_rack_runtime.rb +35 -0
- data/test/spec_rack_sendfile.rb +86 -0
- data/test/spec_rack_session_cookie.rb +1 -10
- data/test/spec_rack_session_memcache.rb +53 -20
- data/test/spec_rack_urlmap.rb +30 -0
- data/test/spec_rack_utils.rb +171 -6
- data/test/spec_rack_webrick.rb +4 -4
- data/test/spec_rackup.rb +154 -0
- metadata +37 -79
- data/Rakefile +0 -164
- data/lib/rack/auth/openid.rb +0 -480
- data/test/cgi/lighttpd.conf +0 -20
- data/test/cgi/test +0 -9
- data/test/cgi/test.fcgi +0 -8
- data/test/cgi/test.ru +0 -7
- data/test/multipart/binary +0 -0
- data/test/multipart/empty +0 -10
- data/test/multipart/ie +0 -6
- data/test/multipart/nested +0 -10
- data/test/multipart/none +0 -9
- data/test/multipart/semicolon +0 -6
- data/test/multipart/text +0 -10
- data/test/spec_rack_auth_openid.rb +0 -84
- data/test/testrequest.rb +0 -57
- data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/test/spec_rack_mongrel.rb
CHANGED
@@ -6,14 +6,14 @@ require 'rack/urlmap'
|
|
6
6
|
require 'rack/lint'
|
7
7
|
require 'testrequest'
|
8
8
|
require 'timeout'
|
9
|
-
|
9
|
+
|
10
10
|
Thread.abort_on_exception = true
|
11
11
|
$tcp_defer_accept_opts = nil
|
12
12
|
$tcp_cork_opts = nil
|
13
13
|
|
14
14
|
context "Rack::Handler::Mongrel" do
|
15
15
|
include TestRequest::Helpers
|
16
|
-
|
16
|
+
|
17
17
|
setup do
|
18
18
|
server = Mongrel::HttpServer.new(@host='0.0.0.0', @port=9201)
|
19
19
|
server.register('/test',
|
@@ -41,7 +41,7 @@ context "Rack::Handler::Mongrel" do
|
|
41
41
|
|
42
42
|
specify "should have rack headers" do
|
43
43
|
GET("/test")
|
44
|
-
response["rack.version"].should.equal [1,
|
44
|
+
response["rack.version"].should.equal [1,1]
|
45
45
|
response["rack.multithread"].should.be true
|
46
46
|
response["rack.multiprocess"].should.be false
|
47
47
|
response["rack.run_once"].should.be false
|
@@ -52,7 +52,7 @@ context "Rack::Handler::Mongrel" do
|
|
52
52
|
response["REQUEST_METHOD"].should.equal "GET"
|
53
53
|
response["SCRIPT_NAME"].should.equal "/test"
|
54
54
|
response["REQUEST_PATH"].should.equal "/test"
|
55
|
-
response["PATH_INFO"].should.be.
|
55
|
+
response["PATH_INFO"].should.be.equal ""
|
56
56
|
response["QUERY_STRING"].should.equal ""
|
57
57
|
response["test.postdata"].should.equal ""
|
58
58
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rack/nulllogger'
|
2
|
+
require 'rack/lint'
|
3
|
+
require 'rack/mock'
|
4
|
+
|
5
|
+
context "Rack::NullLogger" do
|
6
|
+
specify "acks as a nop logger" do
|
7
|
+
app = lambda { |env|
|
8
|
+
env['rack.logger'].warn "b00m"
|
9
|
+
[200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
|
10
|
+
}
|
11
|
+
Rack::NullLogger.new(app).call({})
|
12
|
+
end
|
13
|
+
end
|
data/test/spec_rack_request.rb
CHANGED
@@ -35,9 +35,18 @@ context "Rack::Request" do
|
|
35
35
|
req.host.should.equal "www2.example.org"
|
36
36
|
|
37
37
|
req = Rack::Request.new \
|
38
|
-
Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org
|
38
|
+
Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
|
39
39
|
req.host.should.equal "example.org"
|
40
40
|
|
41
|
+
req = Rack::Request.new \
|
42
|
+
Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
|
43
|
+
req.host.should.equal "example.org"
|
44
|
+
|
45
|
+
env = Rack::MockRequest.env_for("/", "SERVER_ADDR" => "192.168.1.1", "SERVER_PORT" => "9292")
|
46
|
+
env.delete("SERVER_NAME")
|
47
|
+
req = Rack::Request.new(env)
|
48
|
+
req.host.should.equal "192.168.1.1"
|
49
|
+
|
41
50
|
env = Rack::MockRequest.env_for("/")
|
42
51
|
env.delete("SERVER_NAME")
|
43
52
|
req = Rack::Request.new(env)
|
@@ -52,9 +61,16 @@ context "Rack::Request" do
|
|
52
61
|
req.params.should.equal "foo" => "bar", "quux" => "bla"
|
53
62
|
end
|
54
63
|
|
55
|
-
specify "
|
64
|
+
specify "raises if rack.input is missing" do
|
65
|
+
req = Rack::Request.new({})
|
66
|
+
lambda { req.POST }.should.raise(RuntimeError)
|
67
|
+
end
|
68
|
+
|
69
|
+
specify "can parse POST data when method is POST and no Content-Type given" do
|
56
70
|
req = Rack::Request.new \
|
57
|
-
Rack::MockRequest.env_for("/?foo=quux",
|
71
|
+
Rack::MockRequest.env_for("/?foo=quux",
|
72
|
+
"REQUEST_METHOD" => 'POST',
|
73
|
+
:input => "foo=bar&quux=bla")
|
58
74
|
req.content_type.should.be.nil
|
59
75
|
req.media_type.should.be.nil
|
60
76
|
req.query_string.should.equal "foo=quux"
|
@@ -63,7 +79,7 @@ context "Rack::Request" do
|
|
63
79
|
req.params.should.equal "foo" => "bar", "quux" => "bla"
|
64
80
|
end
|
65
81
|
|
66
|
-
specify "can parse POST data with explicit content type" do
|
82
|
+
specify "can parse POST data with explicit content type regardless of method" do
|
67
83
|
req = Rack::Request.new \
|
68
84
|
Rack::MockRequest.env_for("/",
|
69
85
|
"CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
|
@@ -78,6 +94,7 @@ context "Rack::Request" do
|
|
78
94
|
specify "does not parse POST data when media type is not form-data" do
|
79
95
|
req = Rack::Request.new \
|
80
96
|
Rack::MockRequest.env_for("/?foo=quux",
|
97
|
+
"REQUEST_METHOD" => 'POST',
|
81
98
|
"CONTENT_TYPE" => 'text/plain;charset=utf-8',
|
82
99
|
:input => "foo=bar&quux=bla")
|
83
100
|
req.content_type.should.equal 'text/plain;charset=utf-8'
|
@@ -88,6 +105,16 @@ context "Rack::Request" do
|
|
88
105
|
req.body.read.should.equal "foo=bar&quux=bla"
|
89
106
|
end
|
90
107
|
|
108
|
+
specify "can parse POST data on PUT when media type is form-data" do
|
109
|
+
req = Rack::Request.new \
|
110
|
+
Rack::MockRequest.env_for("/?foo=quux",
|
111
|
+
"REQUEST_METHOD" => 'PUT',
|
112
|
+
"CONTENT_TYPE" => 'application/x-www-form-urlencoded',
|
113
|
+
:input => "foo=bar&quux=bla")
|
114
|
+
req.POST.should.equal "foo" => "bar", "quux" => "bla"
|
115
|
+
req.body.read.should.equal "foo=bar&quux=bla"
|
116
|
+
end
|
117
|
+
|
91
118
|
specify "rewinds input after parsing POST data" do
|
92
119
|
input = StringIO.new("foo=bar&quux=bla")
|
93
120
|
req = Rack::Request.new \
|
@@ -100,7 +127,8 @@ context "Rack::Request" do
|
|
100
127
|
|
101
128
|
specify "cleans up Safari's ajax POST body" do
|
102
129
|
req = Rack::Request.new \
|
103
|
-
Rack::MockRequest.env_for("/",
|
130
|
+
Rack::MockRequest.env_for("/",
|
131
|
+
'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0")
|
104
132
|
req.POST.should.equal "foo" => "bar", "quux" => "bla"
|
105
133
|
end
|
106
134
|
|
@@ -147,9 +175,21 @@ context "Rack::Request" do
|
|
147
175
|
req.referer.should.equal "/"
|
148
176
|
end
|
149
177
|
|
178
|
+
specify "user agent should be extracted correct" do
|
179
|
+
req = Rack::Request.new \
|
180
|
+
Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)")
|
181
|
+
req.user_agent.should.equal "Mozilla/4.0 (compatible)"
|
182
|
+
|
183
|
+
req = Rack::Request.new \
|
184
|
+
Rack::MockRequest.env_for("/")
|
185
|
+
req.user_agent.should.equal nil
|
186
|
+
end
|
187
|
+
|
150
188
|
specify "can cache, but invalidates the cache" do
|
151
189
|
req = Rack::Request.new \
|
152
|
-
Rack::MockRequest.env_for("/?foo=quux",
|
190
|
+
Rack::MockRequest.env_for("/?foo=quux",
|
191
|
+
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
192
|
+
:input => "foo=bar&quux=bla")
|
153
193
|
req.GET.should.equal "foo" => "quux"
|
154
194
|
req.GET.should.equal "foo" => "quux"
|
155
195
|
req.env["QUERY_STRING"] = "bla=foo"
|
@@ -424,6 +464,7 @@ Content-Transfer-Encoding: base64\r
|
|
424
464
|
/9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
|
425
465
|
--AaB03x--\r
|
426
466
|
EOF
|
467
|
+
input.force_encoding("ASCII-8BIT") if input.respond_to? :force_encoding
|
427
468
|
res = Rack::MockRequest.new(Rack::Lint.new(app)).get "/",
|
428
469
|
"CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
|
429
470
|
"CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input)
|
data/test/spec_rack_response.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test/spec'
|
2
|
+
require 'rack/mock'
|
3
|
+
require 'rack/runtime'
|
4
|
+
|
5
|
+
context "Rack::Runtime" do
|
6
|
+
specify "sets X-Runtime is none is set" do
|
7
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
8
|
+
response = Rack::Runtime.new(app).call({})
|
9
|
+
response[1]['X-Runtime'].should =~ /[\d\.]+/
|
10
|
+
end
|
11
|
+
|
12
|
+
specify "does not set the X-Runtime if it is already set" do
|
13
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain', "X-Runtime" => "foobar"}, "Hello, World!"] }
|
14
|
+
response = Rack::Runtime.new(app).call({})
|
15
|
+
response[1]['X-Runtime'].should == "foobar"
|
16
|
+
end
|
17
|
+
|
18
|
+
specify "should allow a suffix to be set" do
|
19
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
20
|
+
response = Rack::Runtime.new(app, "Test").call({})
|
21
|
+
response[1]['X-Runtime-Test'].should =~ /[\d\.]+/
|
22
|
+
end
|
23
|
+
|
24
|
+
specify "should allow multiple timers to be set" do
|
25
|
+
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
|
26
|
+
runtime1 = Rack::Runtime.new(app, "App")
|
27
|
+
runtime2 = Rack::Runtime.new(runtime1, "All")
|
28
|
+
response = runtime2.call({})
|
29
|
+
|
30
|
+
response[1]['X-Runtime-App'].should =~ /[\d\.]+/
|
31
|
+
response[1]['X-Runtime-All'].should =~ /[\d\.]+/
|
32
|
+
|
33
|
+
Float(response[1]['X-Runtime-All']).should > Float(response[1]['X-Runtime-App'])
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'test/spec'
|
2
|
+
require 'rack/mock'
|
3
|
+
require 'rack/sendfile'
|
4
|
+
|
5
|
+
context "Rack::File" do
|
6
|
+
specify "should respond to #to_path" do
|
7
|
+
Rack::File.new(Dir.pwd).should.respond_to :to_path
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context "Rack::Sendfile" do
|
12
|
+
def sendfile_body
|
13
|
+
res = ['Hello World']
|
14
|
+
def res.to_path ; "/tmp/hello.txt" ; end
|
15
|
+
res
|
16
|
+
end
|
17
|
+
|
18
|
+
def simple_app(body=sendfile_body)
|
19
|
+
lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
|
20
|
+
end
|
21
|
+
|
22
|
+
def sendfile_app(body=sendfile_body)
|
23
|
+
Rack::Sendfile.new(simple_app(body))
|
24
|
+
end
|
25
|
+
|
26
|
+
setup do
|
27
|
+
@request = Rack::MockRequest.new(sendfile_app)
|
28
|
+
end
|
29
|
+
|
30
|
+
def request(headers={})
|
31
|
+
yield @request.get('/', headers)
|
32
|
+
end
|
33
|
+
|
34
|
+
specify "does nothing when no X-Sendfile-Type header present" do
|
35
|
+
request do |response|
|
36
|
+
response.should.be.ok
|
37
|
+
response.body.should.equal 'Hello World'
|
38
|
+
response.headers.should.not.include 'X-Sendfile'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
specify "sets X-Sendfile response header and discards body" do
|
43
|
+
request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
|
44
|
+
response.should.be.ok
|
45
|
+
response.body.should.be.empty
|
46
|
+
response.headers['X-Sendfile'].should.equal '/tmp/hello.txt'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
specify "sets X-Lighttpd-Send-File response header and discards body" do
|
51
|
+
request 'HTTP_X_SENDFILE_TYPE' => 'X-Lighttpd-Send-File' do |response|
|
52
|
+
response.should.be.ok
|
53
|
+
response.body.should.be.empty
|
54
|
+
response.headers['X-Lighttpd-Send-File'].should.equal '/tmp/hello.txt'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
specify "sets X-Accel-Redirect response header and discards body" do
|
59
|
+
headers = {
|
60
|
+
'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect',
|
61
|
+
'HTTP_X_ACCEL_MAPPING' => '/tmp/=/foo/bar/'
|
62
|
+
}
|
63
|
+
request headers do |response|
|
64
|
+
response.should.be.ok
|
65
|
+
response.body.should.be.empty
|
66
|
+
response.headers['X-Accel-Redirect'].should.equal '/foo/bar/hello.txt'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
specify 'writes to rack.error when no X-Accel-Mapping is specified' do
|
71
|
+
request 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect' do |response|
|
72
|
+
response.should.be.ok
|
73
|
+
response.body.should.equal 'Hello World'
|
74
|
+
response.headers.should.not.include 'X-Accel-Redirect'
|
75
|
+
response.errors.should.include 'X-Accel-Mapping'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
specify 'does nothing when body does not respond to #to_path' do
|
80
|
+
@request = Rack::MockRequest.new(sendfile_app(['Not a file...']))
|
81
|
+
request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
|
82
|
+
response.body.should.equal 'Not a file...'
|
83
|
+
response.headers.should.not.include 'X-Sendfile'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -46,16 +46,7 @@ context "Rack::Session::Cookie" do
|
|
46
46
|
get("/", :fatal => true)
|
47
47
|
}.should.raise(Rack::MockRequest::FatalWarning)
|
48
48
|
end
|
49
|
-
|
50
|
-
specify "creates a new cookie with integrity hash" do
|
51
|
-
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).get("/")
|
52
|
-
if RUBY_VERSION < "1.9"
|
53
|
-
res["Set-Cookie"].should.match("rack.session=BAh7BiIMY291bnRlcmkG%0A--1439b4d37b9d4b04c603848382f712d6fcd31088")
|
54
|
-
else
|
55
|
-
res["Set-Cookie"].should.match("rack.session=BAh7BkkiDGNvdW50ZXIGOg1lbmNvZGluZyINVVMtQVNDSUlpBg%3D%3D%0A--d7a6637b94d2728194a96c18484e1f7ed9074a83")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
49
|
+
|
59
50
|
specify "loads from a cookie wih integrity hash" do
|
60
51
|
res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).get("/")
|
61
52
|
cookie = res["Set-Cookie"]
|
@@ -8,7 +8,7 @@ begin
|
|
8
8
|
|
9
9
|
context "Rack::Session::Memcache" do
|
10
10
|
session_key = Rack::Session::Memcache::DEFAULT_OPTIONS[:key]
|
11
|
-
session_match = /#{session_key}=[0-9a-fA-F]
|
11
|
+
session_match = /#{session_key}=([0-9a-fA-F]+);/
|
12
12
|
incrementor = lambda do |env|
|
13
13
|
env["rack.session"]["counter"] ||= 0
|
14
14
|
env["rack.session"]["counter"] += 1
|
@@ -27,14 +27,20 @@ begin
|
|
27
27
|
incrementor.call(env)
|
28
28
|
end
|
29
29
|
|
30
|
-
specify "
|
31
|
-
|
30
|
+
specify "faults on no connection" do
|
31
|
+
if RUBY_VERSION < "1.9"
|
32
|
+
lambda do
|
33
|
+
Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
|
34
|
+
end.should.raise
|
35
|
+
else
|
36
|
+
lambda do
|
37
|
+
Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
|
38
|
+
end.should.raise ArgumentError
|
39
|
+
end
|
32
40
|
end
|
33
41
|
|
34
|
-
specify "
|
35
|
-
|
36
|
-
Rack::Session::Memcache.new(incrementor, :memcache_server => '')
|
37
|
-
end.should.raise
|
42
|
+
specify "connect to existing server" do
|
43
|
+
test_pool = MemCache.new incrementor, :namespace => 'test:rack:session'
|
38
44
|
end
|
39
45
|
|
40
46
|
specify "creates a new cookie" do
|
@@ -151,6 +157,31 @@ begin
|
|
151
157
|
res3.body.should.equal '{"counter"=>4}'
|
152
158
|
end
|
153
159
|
|
160
|
+
specify "deep hashes are correctly updated" do
|
161
|
+
store = nil
|
162
|
+
hash_check = proc do |env|
|
163
|
+
session = env['rack.session']
|
164
|
+
unless session.include? 'test'
|
165
|
+
session.update :a => :b, :c => { :d => :e },
|
166
|
+
:f => { :g => { :h => :i} }, 'test' => true
|
167
|
+
else
|
168
|
+
session[:f][:g][:h] = :j
|
169
|
+
end
|
170
|
+
[200, {}, session.inspect]
|
171
|
+
end
|
172
|
+
pool = Rack::Session::Memcache.new(hash_check)
|
173
|
+
req = Rack::MockRequest.new(pool)
|
174
|
+
|
175
|
+
res0 = req.get("/")
|
176
|
+
session_id = (cookie = res0["Set-Cookie"])[session_match, 1]
|
177
|
+
ses0 = pool.pool.get(session_id, true)
|
178
|
+
|
179
|
+
res1 = req.get("/", "HTTP_COOKIE" => cookie)
|
180
|
+
ses1 = pool.pool.get(session_id, true)
|
181
|
+
|
182
|
+
ses1.should.not.equal ses0
|
183
|
+
end
|
184
|
+
|
154
185
|
# anyone know how to do this better?
|
155
186
|
specify "multithread: should cleanly merge sessions" do
|
156
187
|
next unless $DEBUG
|
@@ -161,7 +192,7 @@ begin
|
|
161
192
|
res = req.get('/')
|
162
193
|
res.body.should.equal '{"counter"=>1}'
|
163
194
|
cookie = res["Set-Cookie"]
|
164
|
-
|
195
|
+
session_id = cookie[session_match, 1]
|
165
196
|
|
166
197
|
delta_incrementor = lambda do |env|
|
167
198
|
# emulate disconjoinment of threading
|
@@ -178,12 +209,12 @@ begin
|
|
178
209
|
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
|
179
210
|
end
|
180
211
|
end.reverse.map{|t| t.run.join.value }
|
181
|
-
r.each do |
|
182
|
-
|
183
|
-
|
212
|
+
r.each do |request|
|
213
|
+
request['Set-Cookie'].should.equal cookie
|
214
|
+
request.body.should.include '"counter"=>2'
|
184
215
|
end
|
185
216
|
|
186
|
-
session = pool.pool.get(
|
217
|
+
session = pool.pool.get(session_id)
|
187
218
|
session.size.should.be tnum+1 # counter
|
188
219
|
session['counter'].should.be 2 # meeeh
|
189
220
|
|
@@ -202,12 +233,12 @@ begin
|
|
202
233
|
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
|
203
234
|
end
|
204
235
|
end.reverse.map{|t| t.run.join.value }
|
205
|
-
r.each do |
|
206
|
-
|
207
|
-
|
236
|
+
r.each do |request|
|
237
|
+
request['Set-Cookie'].should.equal cookie
|
238
|
+
request.body.should.include '"counter"=>3'
|
208
239
|
end
|
209
240
|
|
210
|
-
session = pool.pool.get(
|
241
|
+
session = pool.pool.get(session_id)
|
211
242
|
session.size.should.be tnum+1
|
212
243
|
session['counter'].should.be 3
|
213
244
|
|
@@ -224,17 +255,19 @@ begin
|
|
224
255
|
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
|
225
256
|
end
|
226
257
|
end.reverse.map{|t| t.run.join.value }
|
227
|
-
r.each do |
|
228
|
-
|
229
|
-
|
258
|
+
r.each do |request|
|
259
|
+
request['Set-Cookie'].should.equal cookie
|
260
|
+
request.body.should.include '"foo"=>"bar"'
|
230
261
|
end
|
231
262
|
|
232
|
-
session = pool.pool.get(
|
263
|
+
session = pool.pool.get(session_id)
|
233
264
|
session.size.should.be r.size+1
|
234
265
|
session['counter'].should.be.nil?
|
235
266
|
session['foo'].should.equal 'bar'
|
236
267
|
end
|
237
268
|
end
|
269
|
+
rescue RuntimeError
|
270
|
+
$stderr.puts "Skipping Rack::Session::Memcache tests. Start memcached and try again."
|
238
271
|
rescue LoadError
|
239
272
|
$stderr.puts "Skipping Rack::Session::Memcache tests (Memcache is required). `gem install memcache-client` and try again."
|
240
273
|
end
|
data/test/spec_rack_urlmap.rb
CHANGED
@@ -44,6 +44,12 @@ context "Rack::URLMap" do
|
|
44
44
|
res["X-ScriptName"].should.equal "/foo/bar"
|
45
45
|
res["X-PathInfo"].should.equal "/"
|
46
46
|
|
47
|
+
res = Rack::MockRequest.new(map).get("/foo///bar//quux")
|
48
|
+
res.status.should.equal 200
|
49
|
+
res.should.be.ok
|
50
|
+
res["X-ScriptName"].should.equal "/foo/bar"
|
51
|
+
res["X-PathInfo"].should.equal "//quux"
|
52
|
+
|
47
53
|
res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
|
48
54
|
res.should.be.ok
|
49
55
|
res["X-ScriptName"].should.equal "/bleh/foo"
|
@@ -182,4 +188,28 @@ context "Rack::URLMap" do
|
|
182
188
|
res["X-PathInfo"].should.equal "/"
|
183
189
|
res["X-ScriptName"].should.equal ""
|
184
190
|
end
|
191
|
+
|
192
|
+
specify "should not squeeze slashes" do
|
193
|
+
map = Rack::URLMap.new("/" => lambda { |env|
|
194
|
+
[200,
|
195
|
+
{ "Content-Type" => "text/plain",
|
196
|
+
"X-Position" => "root",
|
197
|
+
"X-PathInfo" => env["PATH_INFO"],
|
198
|
+
"X-ScriptName" => env["SCRIPT_NAME"]
|
199
|
+
}, [""]]},
|
200
|
+
"/foo" => lambda { |env|
|
201
|
+
[200,
|
202
|
+
{ "Content-Type" => "text/plain",
|
203
|
+
"X-Position" => "foo",
|
204
|
+
"X-PathInfo" => env["PATH_INFO"],
|
205
|
+
"X-ScriptName" => env["SCRIPT_NAME"]
|
206
|
+
}, [""]]}
|
207
|
+
)
|
208
|
+
|
209
|
+
res = Rack::MockRequest.new(map).get("/http://example.org/bar")
|
210
|
+
res.should.be.ok
|
211
|
+
res["X-Position"].should.equal "root"
|
212
|
+
res["X-PathInfo"].should.equal "/http://example.org/bar"
|
213
|
+
res["X-ScriptName"].should.equal ""
|
214
|
+
end
|
185
215
|
end
|