em-http-request 1.0.0 → 1.0.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.
Potentially problematic release.
This version of em-http-request might be problematic. Click here for more details.
- data/.gitignore +2 -0
- data/README.md +4 -2
- data/em-http-request.gemspec +33 -33
- data/examples/fibered-http.rb +51 -47
- data/lib/em-http/client.rb +307 -275
- data/lib/em-http/http_client_options.rb +1 -0
- data/lib/em-http/http_connection.rb +199 -194
- data/lib/em-http/http_connection_options.rb +6 -1
- data/lib/em-http/http_encoding.rb +2 -2
- data/lib/em-http/http_header.rb +4 -0
- data/lib/em-http/http_status_codes.rb +51 -37
- data/lib/em-http/multi.rb +4 -2
- data/lib/em-http/version.rb +5 -5
- data/spec/client_fiber_spec.rb +21 -0
- data/spec/client_spec.rb +734 -669
- data/spec/encoding_spec.rb +11 -2
- data/spec/external_spec.rb +128 -127
- data/spec/helper.rb +2 -2
- data/spec/multi_spec.rb +9 -1
- data/spec/pipelining_spec.rb +66 -38
- data/spec/redirect_spec.rb +55 -3
- data/spec/socksify_proxy_spec.rb +24 -24
- data/spec/stallion.rb +273 -270
- data/spec/stub_server.rb +25 -5
- metadata +34 -31
data/spec/encoding_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
|
3
5
|
describe EventMachine::HttpEncoding do
|
@@ -13,7 +15,8 @@ describe EventMachine::HttpEncoding do
|
|
13
15
|
|
14
16
|
it "should transform a very complex hash into HTTP POST Params" do
|
15
17
|
params = form_encode_body({:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]})
|
16
|
-
|
18
|
+
# 1.8.7 does not have ordered hashes.
|
19
|
+
params.split(/&/).sort.join('&').should == "a=a&b[0][c]=c&b[0][d]=d&b[1][e]=e&b[1][f]=f"
|
17
20
|
end
|
18
21
|
|
19
22
|
it "should escape values" do
|
@@ -31,10 +34,16 @@ describe EventMachine::HttpEncoding do
|
|
31
34
|
params.should == "bad%26str[key%26key][0]=bad%2B%26stuff&bad%26str[key%26key][1]=%5Btest%5D"
|
32
35
|
end
|
33
36
|
|
37
|
+
it "should not issue warnings on non-ASCII encodings" do
|
38
|
+
# I don't know how to check for ruby warnings.
|
39
|
+
params = escape('valö')
|
40
|
+
params = escape('valö'.encode('ISO-8859-15'))
|
41
|
+
end
|
42
|
+
|
34
43
|
# xit "should be fast on long string escapes" do
|
35
44
|
# s = Time.now
|
36
45
|
# 5000.times { |n| form_encode_body({:a => "{a:'b', d:'f', g:['a','b']}"*50}) }
|
37
46
|
# (Time.now - s).should satisfy { |t| t < 1.5 }
|
38
47
|
# end
|
39
48
|
|
40
|
-
end
|
49
|
+
end
|
data/spec/external_spec.rb
CHANGED
@@ -1,127 +1,128 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
requires_connection do
|
4
|
-
|
5
|
-
describe EventMachine::HttpRequest do
|
6
|
-
|
7
|
-
it "should follow redirects on HEAD method (external)" do
|
8
|
-
EventMachine.run {
|
9
|
-
http = EventMachine::HttpRequest.new('http://www.google.com/').head :redirects => 1
|
10
|
-
http.errback { failed(http) }
|
11
|
-
http.callback {
|
12
|
-
http.response_header.status.should == 200
|
13
|
-
EM.stop
|
14
|
-
}
|
15
|
-
}
|
16
|
-
end
|
17
|
-
|
18
|
-
it "should follow redirect to https and initiate the handshake" do
|
19
|
-
EventMachine.run {
|
20
|
-
http = EventMachine::HttpRequest.new('http://analytics.postrank.com/').get :redirects => 5
|
21
|
-
|
22
|
-
http.errback { failed(http) }
|
23
|
-
http.callback {
|
24
|
-
http.response_header.status.should == 200
|
25
|
-
EventMachine.stop
|
26
|
-
}
|
27
|
-
}
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should perform a streaming GET" do
|
31
|
-
EventMachine.run {
|
32
|
-
|
33
|
-
# digg.com uses chunked encoding
|
34
|
-
http = EventMachine::HttpRequest.new('http://digg.com/news').get
|
35
|
-
|
36
|
-
http.errback { failed(http) }
|
37
|
-
http.callback {
|
38
|
-
http.response_header.status.should == 200
|
39
|
-
EventMachine.stop
|
40
|
-
}
|
41
|
-
}
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should handle a 100 continue" do
|
45
|
-
EventMachine.run {
|
46
|
-
# 8.2.3 Use of the 100 (Continue) Status - http://www.ietf.org/rfc/rfc2616.txt
|
47
|
-
#
|
48
|
-
# An origin server SHOULD NOT send a 100 (Continue) response if
|
49
|
-
# the request message does not include an Expect request-header
|
50
|
-
# field with the "100-continue" expectation, and MUST NOT send a
|
51
|
-
# 100 (Continue) response if such a request comes from an HTTP/1.0
|
52
|
-
# (or earlier) client. There is an exception to this rule: for
|
53
|
-
# compatibility with RFC 2068, a server MAY send a 100 (Continue)
|
54
|
-
# status in response to an HTTP/1.1 PUT or POST request that does
|
55
|
-
# not include an Expect request-header field with the "100-
|
56
|
-
# continue" expectation. This exception, the purpose of which is
|
57
|
-
# to minimize any client processing delays associated with an
|
58
|
-
# undeclared wait for 100 (Continue) status, applies only to
|
59
|
-
# HTTP/1.1 requests, and not to requests with any other HTTP-
|
60
|
-
# version value.
|
61
|
-
#
|
62
|
-
# 10.1.1: 100 Continue - http://www.ietf.org/rfc/rfc2068.txt
|
63
|
-
# The client may continue with its request. This interim response is
|
64
|
-
# used to inform the client that the initial part of the request has
|
65
|
-
# been received and has not yet been rejected by the server. The client
|
66
|
-
# SHOULD continue by sending the remainder of the request or, if the
|
67
|
-
# request has already been completed, ignore this response. The server
|
68
|
-
# MUST send a final response after the request has been completed.
|
69
|
-
|
70
|
-
url = 'http://ws.serviceobjects.com/lv/LeadValidation.asmx/ValidateLead_V2'
|
71
|
-
http = EventMachine::HttpRequest.new(url).post :body => {:name => :test}
|
72
|
-
|
73
|
-
http.errback { failed(http) }
|
74
|
-
http.callback {
|
75
|
-
http.response_header.status.should == 500
|
76
|
-
http.response.should match('Missing')
|
77
|
-
EventMachine.stop
|
78
|
-
}
|
79
|
-
}
|
80
|
-
end
|
81
|
-
|
82
|
-
it "should detect deflate encoding" do
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
http.
|
90
|
-
|
91
|
-
http.response_header
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
http.
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
end
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
requires_connection do
|
4
|
+
|
5
|
+
describe EventMachine::HttpRequest do
|
6
|
+
|
7
|
+
it "should follow redirects on HEAD method (external)" do
|
8
|
+
EventMachine.run {
|
9
|
+
http = EventMachine::HttpRequest.new('http://www.google.com/').head :redirects => 1
|
10
|
+
http.errback { failed(http) }
|
11
|
+
http.callback {
|
12
|
+
http.response_header.status.should == 200
|
13
|
+
EM.stop
|
14
|
+
}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should follow redirect to https and initiate the handshake" do
|
19
|
+
EventMachine.run {
|
20
|
+
http = EventMachine::HttpRequest.new('http://analytics.postrank.com/').get :redirects => 5
|
21
|
+
|
22
|
+
http.errback { failed(http) }
|
23
|
+
http.callback {
|
24
|
+
http.response_header.status.should == 200
|
25
|
+
EventMachine.stop
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should perform a streaming GET" do
|
31
|
+
EventMachine.run {
|
32
|
+
|
33
|
+
# digg.com uses chunked encoding
|
34
|
+
http = EventMachine::HttpRequest.new('http://digg.com/news').get
|
35
|
+
|
36
|
+
http.errback { failed(http) }
|
37
|
+
http.callback {
|
38
|
+
http.response_header.status.should == 200
|
39
|
+
EventMachine.stop
|
40
|
+
}
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should handle a 100 continue" do
|
45
|
+
EventMachine.run {
|
46
|
+
# 8.2.3 Use of the 100 (Continue) Status - http://www.ietf.org/rfc/rfc2616.txt
|
47
|
+
#
|
48
|
+
# An origin server SHOULD NOT send a 100 (Continue) response if
|
49
|
+
# the request message does not include an Expect request-header
|
50
|
+
# field with the "100-continue" expectation, and MUST NOT send a
|
51
|
+
# 100 (Continue) response if such a request comes from an HTTP/1.0
|
52
|
+
# (or earlier) client. There is an exception to this rule: for
|
53
|
+
# compatibility with RFC 2068, a server MAY send a 100 (Continue)
|
54
|
+
# status in response to an HTTP/1.1 PUT or POST request that does
|
55
|
+
# not include an Expect request-header field with the "100-
|
56
|
+
# continue" expectation. This exception, the purpose of which is
|
57
|
+
# to minimize any client processing delays associated with an
|
58
|
+
# undeclared wait for 100 (Continue) status, applies only to
|
59
|
+
# HTTP/1.1 requests, and not to requests with any other HTTP-
|
60
|
+
# version value.
|
61
|
+
#
|
62
|
+
# 10.1.1: 100 Continue - http://www.ietf.org/rfc/rfc2068.txt
|
63
|
+
# The client may continue with its request. This interim response is
|
64
|
+
# used to inform the client that the initial part of the request has
|
65
|
+
# been received and has not yet been rejected by the server. The client
|
66
|
+
# SHOULD continue by sending the remainder of the request or, if the
|
67
|
+
# request has already been completed, ignore this response. The server
|
68
|
+
# MUST send a final response after the request has been completed.
|
69
|
+
|
70
|
+
url = 'http://ws.serviceobjects.com/lv/LeadValidation.asmx/ValidateLead_V2'
|
71
|
+
http = EventMachine::HttpRequest.new(url).post :body => {:name => :test}
|
72
|
+
|
73
|
+
http.errback { failed(http) }
|
74
|
+
http.callback {
|
75
|
+
http.response_header.status.should == 500
|
76
|
+
http.response.should match('Missing')
|
77
|
+
EventMachine.stop
|
78
|
+
}
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should detect deflate encoding" do
|
83
|
+
pending "need an endpoint which supports deflate.. MSN is no longer"
|
84
|
+
EventMachine.run {
|
85
|
+
|
86
|
+
options = {:head => {"accept-encoding" => "deflate"}, :redirects => 5}
|
87
|
+
http = EventMachine::HttpRequest.new('http://www.msn.com').get options
|
88
|
+
|
89
|
+
http.errback { failed(http) }
|
90
|
+
http.callback {
|
91
|
+
http.response_header.status.should == 200
|
92
|
+
http.response_header["CONTENT_ENCODING"].should == "deflate"
|
93
|
+
|
94
|
+
EventMachine.stop
|
95
|
+
}
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
context "keepalive" do
|
100
|
+
it "should default to non-keepalive" do
|
101
|
+
EventMachine.run {
|
102
|
+
headers = {'If-Modified-Since' => 'Thu, 05 Aug 2010 22:54:44 GMT'}
|
103
|
+
http = EventMachine::HttpRequest.new('http://www.google.com/images/logos/ps_logo2.png').get :head => headers
|
104
|
+
|
105
|
+
http.errback { fail }
|
106
|
+
start = Time.now.to_i
|
107
|
+
http.callback {
|
108
|
+
(Time.now.to_i - start).should be_within(2).of(0)
|
109
|
+
EventMachine.stop
|
110
|
+
}
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should work with keep-alive servers" do
|
115
|
+
EventMachine.run {
|
116
|
+
http = EventMachine::HttpRequest.new('http://mexicodiario.com/touch.public.json.php').get :keepalive => true
|
117
|
+
|
118
|
+
http.errback { failed(http) }
|
119
|
+
http.callback {
|
120
|
+
http.response_header.status.should == 200
|
121
|
+
EventMachine.stop
|
122
|
+
}
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
data/spec/helper.rb
CHANGED
@@ -13,7 +13,7 @@ def failed(http = nil)
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def requires_connection(&blk)
|
16
|
-
blk.call if system('ping -t1 -c1 google.com
|
16
|
+
blk.call if system('ping -t1 -c1 google.com 2>&1 > /dev/null')
|
17
17
|
end
|
18
18
|
|
19
19
|
def requires_port(port, &blk)
|
@@ -26,4 +26,4 @@ def requires_port(port, &blk)
|
|
26
26
|
end
|
27
27
|
|
28
28
|
blk.call if port_open
|
29
|
-
end
|
29
|
+
end
|
data/spec/multi_spec.rb
CHANGED
@@ -27,6 +27,14 @@ describe EventMachine::MultiRequest do
|
|
27
27
|
}
|
28
28
|
end
|
29
29
|
|
30
|
+
it "should require unique keys for each deferrable" do
|
31
|
+
lambda do
|
32
|
+
multi.add :df1, EM::DefaultDeferrable.new
|
33
|
+
multi.add :df1, EM::DefaultDeferrable.new
|
34
|
+
end.should raise_error("Duplicate Multi key")
|
35
|
+
end
|
36
|
+
|
37
|
+
|
30
38
|
describe "#requests" do
|
31
39
|
it "should return the added requests" do
|
32
40
|
request1 = stub('request1', :callback => nil, :errback => nil)
|
@@ -35,7 +43,7 @@ describe EventMachine::MultiRequest do
|
|
35
43
|
multi.add :a, request1
|
36
44
|
multi.add :b, request2
|
37
45
|
|
38
|
-
multi.requests.should ==
|
46
|
+
multi.requests.should == {:a => request1, :b => request2}
|
39
47
|
end
|
40
48
|
end
|
41
49
|
|
data/spec/pipelining_spec.rb
CHANGED
@@ -1,38 +1,66 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
requires_connection do
|
4
|
-
|
5
|
-
describe EventMachine::HttpRequest do
|
6
|
-
|
7
|
-
it "should perform successful pipelined GETs" do
|
8
|
-
EventMachine.run do
|
9
|
-
|
10
|
-
# Mongrel doesn't support pipelined requests - bah!
|
11
|
-
conn = EventMachine::HttpRequest.new('http://www.igvita.com/')
|
12
|
-
|
13
|
-
pipe1 = conn.get :keepalive => true
|
14
|
-
pipe2 = conn.get :path => '/
|
15
|
-
|
16
|
-
processed = 0
|
17
|
-
stop = proc { EM.stop if processed == 2}
|
18
|
-
|
19
|
-
pipe1.errback { failed(conn) }
|
20
|
-
pipe1.callback {
|
21
|
-
processed += 1
|
22
|
-
pipe1.response_header.status.should == 200
|
23
|
-
stop.call
|
24
|
-
}
|
25
|
-
|
26
|
-
pipe2.errback {
|
27
|
-
pipe2.callback {
|
28
|
-
processed += 1
|
29
|
-
pipe2.response_header.status.should == 200
|
30
|
-
pipe2.response.should match(/
|
31
|
-
stop.call
|
32
|
-
}
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
requires_connection do
|
4
|
+
|
5
|
+
describe EventMachine::HttpRequest do
|
6
|
+
|
7
|
+
it "should perform successful pipelined GETs" do
|
8
|
+
EventMachine.run do
|
9
|
+
|
10
|
+
# Mongrel doesn't support pipelined requests - bah!
|
11
|
+
conn = EventMachine::HttpRequest.new('http://www.igvita.com/')
|
12
|
+
|
13
|
+
pipe1 = conn.get :keepalive => true
|
14
|
+
pipe2 = conn.get :path => '/archives/', :keepalive => true
|
15
|
+
|
16
|
+
processed = 0
|
17
|
+
stop = proc { EM.stop if processed == 2}
|
18
|
+
|
19
|
+
pipe1.errback { failed(conn) }
|
20
|
+
pipe1.callback {
|
21
|
+
processed += 1
|
22
|
+
pipe1.response_header.status.should == 200
|
23
|
+
stop.call
|
24
|
+
}
|
25
|
+
|
26
|
+
pipe2.errback { failed(conn) }
|
27
|
+
pipe2.callback {
|
28
|
+
processed += 1
|
29
|
+
pipe2.response_header.status.should == 200
|
30
|
+
pipe2.response.should match(/2011/i)
|
31
|
+
stop.call
|
32
|
+
}
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should perform successful pipelined HEAD requests" do
|
38
|
+
EventMachine.run do
|
39
|
+
conn = EventMachine::HttpRequest.new('http://www.igvita.com/')
|
40
|
+
|
41
|
+
pipe1 = conn.head :keepalive => true
|
42
|
+
pipe2 = conn.head :path => '/archives/', :keepalive => true
|
43
|
+
|
44
|
+
processed = 0
|
45
|
+
stop = proc { EM.stop if processed == 2}
|
46
|
+
|
47
|
+
pipe1.errback { failed(conn) }
|
48
|
+
pipe1.callback {
|
49
|
+
processed += 1
|
50
|
+
pipe1.response_header.status.should == 200
|
51
|
+
stop.call
|
52
|
+
}
|
53
|
+
|
54
|
+
pipe2.errback { failed(conn) }
|
55
|
+
pipe2.callback {
|
56
|
+
processed += 1
|
57
|
+
pipe2.response_header.status.should == 200
|
58
|
+
stop.call
|
59
|
+
}
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/spec/redirect_spec.rb
CHANGED
@@ -15,7 +15,7 @@ end
|
|
15
15
|
|
16
16
|
class PickyRedirectMiddleware < RedirectMiddleware
|
17
17
|
def response(r)
|
18
|
-
if r.redirect? && r.response_header['LOCATION'][-1] == '3'
|
18
|
+
if r.redirect? && r.response_header['LOCATION'][-1].chr == '3'
|
19
19
|
# set redirects to 0 to avoid further processing
|
20
20
|
r.req.redirects = 0
|
21
21
|
end
|
@@ -40,6 +40,58 @@ describe EventMachine::HttpRequest do
|
|
40
40
|
}
|
41
41
|
end
|
42
42
|
|
43
|
+
it "should not forward cookies across domains with http redirect" do
|
44
|
+
|
45
|
+
expires = (Date.today + 1).strftime('%a, %d %b %Y %T GMT')
|
46
|
+
response =<<-HTTP.gsub(/^ +/, '')
|
47
|
+
HTTP/1.1 301 MOVED PERMANENTLY
|
48
|
+
Location: http://localhost:8081/
|
49
|
+
Set-Cookie: foo=bar; expires=#{expires}; path=/; HttpOnly
|
50
|
+
|
51
|
+
HTTP
|
52
|
+
|
53
|
+
EventMachine.run do
|
54
|
+
@stub = StubServer.new(:host => '127.0.0.1', :port => 8080, :response => response)
|
55
|
+
@echo = StubServer.new(:host => 'localhost', :port => 8081, :echo => true)
|
56
|
+
|
57
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :redirects => 1
|
58
|
+
|
59
|
+
http.errback { failed(http) }
|
60
|
+
http.callback do
|
61
|
+
http.response.should_not match(/Cookie/)
|
62
|
+
@stub.stop
|
63
|
+
@echo.stop
|
64
|
+
EM.stop
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should forward valid cookies across domains with http redirect" do
|
70
|
+
|
71
|
+
expires = (Date.today + 1).strftime('%a, %d %b %Y %T GMT')
|
72
|
+
response =<<-HTTP.gsub(/^ +/, '')
|
73
|
+
HTTP/1.1 301 MOVED PERMANENTLY
|
74
|
+
Location: http://127.0.0.1:8081/
|
75
|
+
Set-Cookie: foo=bar; expires=#{expires}; path=/; HttpOnly
|
76
|
+
|
77
|
+
HTTP
|
78
|
+
|
79
|
+
EventMachine.run do
|
80
|
+
@stub = StubServer.new(:port => 8080, :response => response)
|
81
|
+
@echo = StubServer.new(:port => 8081, :echo => true)
|
82
|
+
|
83
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :redirects => 1
|
84
|
+
|
85
|
+
http.errback { failed(http) }
|
86
|
+
http.callback do
|
87
|
+
http.response.should match(/Cookie/)
|
88
|
+
@stub.stop
|
89
|
+
@echo.stop
|
90
|
+
EM.stop
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
43
95
|
it "should redirect with missing content-length" do
|
44
96
|
EventMachine.run {
|
45
97
|
@s = StubServer.new("HTTP/1.0 301 MOVED PERMANENTLY\r\nlocation: http://127.0.0.1:8090/redirect\r\n\r\n")
|
@@ -144,7 +196,7 @@ describe EventMachine::HttpRequest do
|
|
144
196
|
http.last_effective_url.to_s.should == 'http://127.0.0.1:8090/gzip'
|
145
197
|
http.redirects.should == 2
|
146
198
|
http.cookies.should include("id=2;")
|
147
|
-
http.cookies.should include("another_id=1
|
199
|
+
http.cookies.should include("another_id=1")
|
148
200
|
|
149
201
|
EM.stop
|
150
202
|
}
|
@@ -162,7 +214,7 @@ describe EventMachine::HttpRequest do
|
|
162
214
|
http.last_effective_url.to_s.should == 'http://127.0.0.1:8090/gzip'
|
163
215
|
http.redirects.should == 2
|
164
216
|
http.cookies.should include("id=2;")
|
165
|
-
http.cookies.should_not include("another_id=1; expires=
|
217
|
+
http.cookies.should_not include("another_id=1; expires=Sat, 09 Aug 2031 17:53:39 GMT; path=/;")
|
166
218
|
|
167
219
|
EM.stop
|
168
220
|
}
|