em-http-request 0.2.15 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of em-http-request might be problematic. Click here for more details.
- data/.gitignore +2 -1
- data/.rspec +0 -0
- data/Changelog.md +13 -0
- data/Gemfile +2 -14
- data/README.md +7 -0
- data/Rakefile +6 -35
- data/em-http-request.gemspec +25 -94
- data/ext/buffer/extconf.rb +53 -53
- data/ext/http11_client/ext_help.h +14 -14
- data/ext/http11_client/extconf.rb +6 -6
- data/ext/http11_client/http11_client.c +328 -328
- data/ext/http11_client/http11_parser.h +48 -48
- data/lib/em-http.rb +15 -16
- data/lib/em-http/client.rb +15 -222
- data/lib/em-http/http_encoding.rb +135 -0
- data/lib/em-http/http_header.rb +71 -0
- data/lib/em-http/http_options.rb +4 -3
- data/lib/em-http/request.rb +0 -3
- data/lib/em-http/version.rb +5 -0
- data/spec/encoding_spec.rb +7 -1
- data/spec/mock_spec.rb +1 -1
- data/spec/multi_spec.rb +68 -68
- data/spec/request_spec.rb +125 -75
- data/spec/stallion.rb +1 -0
- metadata +100 -25
- data/LICENSE +0 -58
- data/VERSION +0 -1
- data/autotest/discover.rb +0 -1
@@ -0,0 +1,71 @@
|
|
1
|
+
module EventMachine
|
2
|
+
# A simple hash is returned for each request made by HttpClient with the
|
3
|
+
# headers that were given by the server for that request.
|
4
|
+
class HttpResponseHeader < Hash
|
5
|
+
# The reason returned in the http response ("OK","File not found",etc.)
|
6
|
+
attr_accessor :http_reason
|
7
|
+
|
8
|
+
# The HTTP version returned.
|
9
|
+
attr_accessor :http_version
|
10
|
+
|
11
|
+
# The status code (as a string!)
|
12
|
+
attr_accessor :http_status
|
13
|
+
|
14
|
+
# E-Tag
|
15
|
+
def etag
|
16
|
+
self[HttpClient::ETAG]
|
17
|
+
end
|
18
|
+
|
19
|
+
def last_modified
|
20
|
+
self[HttpClient::LAST_MODIFIED]
|
21
|
+
end
|
22
|
+
|
23
|
+
# HTTP response status as an integer
|
24
|
+
def status
|
25
|
+
Integer(http_status) rescue 0
|
26
|
+
end
|
27
|
+
|
28
|
+
# Length of content as an integer, or nil if chunked/unspecified
|
29
|
+
def content_length
|
30
|
+
@content_length ||= ((s = self[HttpClient::CONTENT_LENGTH]) &&
|
31
|
+
(s =~ /^(\d+)$/)) ? $1.to_i : nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# Cookie header from the server
|
35
|
+
def cookie
|
36
|
+
self[HttpClient::SET_COOKIE]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Is the transfer encoding chunked?
|
40
|
+
def chunked_encoding?
|
41
|
+
/chunked/i === self[HttpClient::TRANSFER_ENCODING]
|
42
|
+
end
|
43
|
+
|
44
|
+
def keep_alive?
|
45
|
+
/keep-alive/i === self[HttpClient::KEEP_ALIVE]
|
46
|
+
end
|
47
|
+
|
48
|
+
def compressed?
|
49
|
+
/gzip|compressed|deflate/i === self[HttpClient::CONTENT_ENCODING]
|
50
|
+
end
|
51
|
+
|
52
|
+
def location
|
53
|
+
self[HttpClient::LOCATION]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class HttpChunkHeader < Hash
|
58
|
+
# When parsing chunked encodings this is set
|
59
|
+
attr_accessor :http_chunk_size
|
60
|
+
|
61
|
+
def initialize
|
62
|
+
super
|
63
|
+
@http_chunk_size = '0'
|
64
|
+
end
|
65
|
+
|
66
|
+
# Size of the chunk as an integer
|
67
|
+
def chunk_size
|
68
|
+
@http_chunk_size.to_i(base=16)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/em-http/http_options.rb
CHANGED
@@ -2,7 +2,7 @@ class HttpOptions
|
|
2
2
|
attr_reader :uri, :method, :host, :port, :options
|
3
3
|
|
4
4
|
def initialize(method, uri, options)
|
5
|
-
uri.
|
5
|
+
uri.path = '/' if uri.path.empty?
|
6
6
|
|
7
7
|
@options = options
|
8
8
|
@method = method.to_s.upcase
|
@@ -18,8 +18,9 @@ class HttpOptions
|
|
18
18
|
@port = uri.port
|
19
19
|
end
|
20
20
|
|
21
|
-
@options[:timeout] ||= 10
|
22
|
-
@options[:redirects] ||= 0
|
21
|
+
@options[:timeout] ||= 10 # default connect & inactivity timeouts
|
22
|
+
@options[:redirects] ||= 0 # default number of redirects to follow
|
23
|
+
@options[:keepalive] ||= false # default to single request per connection
|
23
24
|
|
24
25
|
# Make sure the ports are set as Addressable::URI doesn't
|
25
26
|
# set the port if it isn't there
|
data/lib/em-http/request.rb
CHANGED
data/spec/encoding_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'helper'
|
2
2
|
|
3
3
|
describe EventMachine::HttpEncoding do
|
4
4
|
include EventMachine::HttpEncoding
|
@@ -31,4 +31,10 @@ describe EventMachine::HttpEncoding do
|
|
31
31
|
params.should == "bad%26str[key%26key][0]=bad%2B%26stuff&bad%26str[key%26key][1]=%5Btest%5D"
|
32
32
|
end
|
33
33
|
|
34
|
+
it "should be fast on long string escapes" do
|
35
|
+
s = Time.now
|
36
|
+
5000.times { |n| form_encode_body({:a => "{a:'b', d:'f', g:['a','b']}"*50}) }
|
37
|
+
(Time.now - s).should satisfy { |t| t < 1.5 }
|
38
|
+
end
|
39
|
+
|
34
40
|
end
|
data/spec/mock_spec.rb
CHANGED
data/spec/multi_spec.rb
CHANGED
@@ -1,68 +1,68 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
|
4
|
-
describe EventMachine::MultiRequest do
|
5
|
-
|
6
|
-
it "should submit multiple requests in parallel and return once all of them are complete" do
|
7
|
-
EventMachine.run {
|
8
|
-
|
9
|
-
# create an instance of multi-request handler, and the requests themselves
|
10
|
-
multi = EventMachine::MultiRequest.new
|
11
|
-
|
12
|
-
# add multiple requests to the multi-handler
|
13
|
-
multi.add(EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get(:query => {:q => 'test'}))
|
14
|
-
multi.add(EventMachine::HttpRequest.new('http://0.0.0.0:8083/').get(:timeout => 1))
|
15
|
-
|
16
|
-
multi.callback {
|
17
|
-
# verify successful request
|
18
|
-
multi.responses[:succeeded].size.should == 1
|
19
|
-
multi.responses[:succeeded].first.response.should match(/test/)
|
20
|
-
|
21
|
-
# verify invalid requests
|
22
|
-
multi.responses[:failed].size.should == 1
|
23
|
-
multi.responses[:failed].first.response_header.status.should == 0
|
24
|
-
|
25
|
-
EventMachine.stop
|
26
|
-
}
|
27
|
-
}
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should accept multiple open connections and return once all of them are complete" do
|
31
|
-
EventMachine.run {
|
32
|
-
http1 = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get(:query => {:q => 'test'})
|
33
|
-
http2 = EventMachine::HttpRequest.new('http://0.0.0.0:8083/').get(:timeout => 1)
|
34
|
-
|
35
|
-
multi = EventMachine::MultiRequest.new([http1, http2]) do
|
36
|
-
multi.responses[:succeeded].size.should == 1
|
37
|
-
multi.responses[:succeeded].first.response.should match(/test/)
|
38
|
-
|
39
|
-
multi.responses[:failed].size.should == 1
|
40
|
-
multi.responses[:failed].first.response_header.status.should == 0
|
41
|
-
|
42
|
-
EventMachine.stop
|
43
|
-
end
|
44
|
-
}
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should handle multiple mock requests" do
|
48
|
-
EventMachine::MockHttpRequest.register_file('http://127.0.0.1:8080/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
49
|
-
EventMachine::MockHttpRequest.register_file('http://0.0.0.0:8083/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
50
|
-
|
51
|
-
EventMachine.run {
|
52
|
-
|
53
|
-
# create an instance of multi-request handler, and the requests themselves
|
54
|
-
multi = EventMachine::MultiRequest.new
|
55
|
-
|
56
|
-
# add multiple requests to the multi-handler
|
57
|
-
multi.add(EventMachine::MockHttpRequest.new('http://127.0.0.1:8080/').get)
|
58
|
-
multi.add(EventMachine::MockHttpRequest.new('http://0.0.0.0:8083/').get)
|
59
|
-
|
60
|
-
multi.callback {
|
61
|
-
# verify successful request
|
62
|
-
multi.responses[:succeeded].size.should == 2
|
63
|
-
|
64
|
-
EventMachine.stop
|
65
|
-
}
|
66
|
-
}
|
67
|
-
end
|
68
|
-
end
|
1
|
+
require 'helper'
|
2
|
+
require 'stallion'
|
3
|
+
|
4
|
+
describe EventMachine::MultiRequest do
|
5
|
+
|
6
|
+
it "should submit multiple requests in parallel and return once all of them are complete" do
|
7
|
+
EventMachine.run {
|
8
|
+
|
9
|
+
# create an instance of multi-request handler, and the requests themselves
|
10
|
+
multi = EventMachine::MultiRequest.new
|
11
|
+
|
12
|
+
# add multiple requests to the multi-handler
|
13
|
+
multi.add(EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get(:query => {:q => 'test'}))
|
14
|
+
multi.add(EventMachine::HttpRequest.new('http://0.0.0.0:8083/').get(:timeout => 1))
|
15
|
+
|
16
|
+
multi.callback {
|
17
|
+
# verify successful request
|
18
|
+
multi.responses[:succeeded].size.should == 1
|
19
|
+
multi.responses[:succeeded].first.response.should match(/test/)
|
20
|
+
|
21
|
+
# verify invalid requests
|
22
|
+
multi.responses[:failed].size.should == 1
|
23
|
+
multi.responses[:failed].first.response_header.status.should == 0
|
24
|
+
|
25
|
+
EventMachine.stop
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should accept multiple open connections and return once all of them are complete" do
|
31
|
+
EventMachine.run {
|
32
|
+
http1 = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get(:query => {:q => 'test'})
|
33
|
+
http2 = EventMachine::HttpRequest.new('http://0.0.0.0:8083/').get(:timeout => 1)
|
34
|
+
|
35
|
+
multi = EventMachine::MultiRequest.new([http1, http2]) do
|
36
|
+
multi.responses[:succeeded].size.should == 1
|
37
|
+
multi.responses[:succeeded].first.response.should match(/test/)
|
38
|
+
|
39
|
+
multi.responses[:failed].size.should == 1
|
40
|
+
multi.responses[:failed].first.response_header.status.should == 0
|
41
|
+
|
42
|
+
EventMachine.stop
|
43
|
+
end
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should handle multiple mock requests" do
|
48
|
+
EventMachine::MockHttpRequest.register_file('http://127.0.0.1:8080/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
49
|
+
EventMachine::MockHttpRequest.register_file('http://0.0.0.0:8083/', :get, {}, File.join(File.dirname(__FILE__), 'fixtures', 'google.ca'))
|
50
|
+
|
51
|
+
EventMachine.run {
|
52
|
+
|
53
|
+
# create an instance of multi-request handler, and the requests themselves
|
54
|
+
multi = EventMachine::MultiRequest.new
|
55
|
+
|
56
|
+
# add multiple requests to the multi-handler
|
57
|
+
multi.add(EventMachine::MockHttpRequest.new('http://127.0.0.1:8080/').get)
|
58
|
+
multi.add(EventMachine::MockHttpRequest.new('http://0.0.0.0:8083/').get)
|
59
|
+
|
60
|
+
multi.callback {
|
61
|
+
# verify successful request
|
62
|
+
multi.responses[:succeeded].size.should == 2
|
63
|
+
|
64
|
+
EventMachine.stop
|
65
|
+
}
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
data/spec/request_spec.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require '
|
1
|
+
require 'helper'
|
2
|
+
require 'stallion'
|
3
|
+
require 'stub_server'
|
4
4
|
|
5
5
|
describe EventMachine::HttpRequest do
|
6
6
|
|
7
|
-
def failed
|
7
|
+
def failed(http=nil)
|
8
8
|
EventMachine.stop
|
9
|
-
fail
|
9
|
+
http ? fail(http.error) : fail
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should fail GET on DNS timeout" do
|
13
13
|
EventMachine.run {
|
14
14
|
EventMachine.heartbeat_interval = 0.1
|
15
15
|
http = EventMachine::HttpRequest.new('http://127.1.1.1/').get :timeout => 1
|
16
|
-
http.callback { failed }
|
16
|
+
http.callback { failed(http) }
|
17
17
|
http.errback {
|
18
18
|
http.response_header.status.should == 0
|
19
19
|
EventMachine.stop
|
@@ -25,7 +25,7 @@ describe EventMachine::HttpRequest do
|
|
25
25
|
EventMachine.run {
|
26
26
|
EventMachine.heartbeat_interval = 0.1
|
27
27
|
http = EventMachine::HttpRequest.new('http://somethinglocal/').get :timeout => 1
|
28
|
-
http.callback { failed }
|
28
|
+
http.callback { failed(http) }
|
29
29
|
http.errback {
|
30
30
|
http.response_header.status.should == 0
|
31
31
|
http.error.should match(/unable to resolve server address/)
|
@@ -59,7 +59,7 @@ describe EventMachine::HttpRequest do
|
|
59
59
|
EventMachine.run {
|
60
60
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
|
61
61
|
|
62
|
-
http.errback { failed }
|
62
|
+
http.errback { failed(http) }
|
63
63
|
http.callback {
|
64
64
|
http.response_header.status.should == 200
|
65
65
|
http.response.should match(/Hello/)
|
@@ -74,7 +74,7 @@ describe EventMachine::HttpRequest do
|
|
74
74
|
EventMachine.run {
|
75
75
|
http = EventMachine::HttpRequest.new('http://google.com:8080/').get :host => '127.0.0.1'
|
76
76
|
|
77
|
-
http.errback { failed }
|
77
|
+
http.errback { failed(http) }
|
78
78
|
http.callback {
|
79
79
|
http.response_header.status.should == 200
|
80
80
|
http.response.should match(/Hello/)
|
@@ -87,7 +87,7 @@ describe EventMachine::HttpRequest do
|
|
87
87
|
EventMachine.run {
|
88
88
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect').get :redirects => 1, :host => '127.0.0.1'
|
89
89
|
|
90
|
-
http.errback { failed }
|
90
|
+
http.errback { failed(http) }
|
91
91
|
http.callback {
|
92
92
|
http.response_header.status.should == 200
|
93
93
|
http.response_header["CONTENT_ENCODING"].should == "gzip"
|
@@ -105,7 +105,7 @@ describe EventMachine::HttpRequest do
|
|
105
105
|
@s = StubServer.new("HTTP/1.0 301 MOVED PERMANENTLY\r\nlocation: http://127.0.0.1:8080/redirect\r\n\r\n")
|
106
106
|
|
107
107
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get :redirects => 2
|
108
|
-
http.errback { failed }
|
108
|
+
http.errback { failed(http) }
|
109
109
|
|
110
110
|
http.callback {
|
111
111
|
http.response_header.status.should == 200
|
@@ -123,7 +123,7 @@ describe EventMachine::HttpRequest do
|
|
123
123
|
it "should follow redirects on HEAD method" do
|
124
124
|
EventMachine.run {
|
125
125
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect/head').head :redirects => 1
|
126
|
-
http.errback { failed }
|
126
|
+
http.errback { failed(http) }
|
127
127
|
http.callback {
|
128
128
|
http.response_header.status.should == 200
|
129
129
|
http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/'
|
@@ -136,7 +136,7 @@ describe EventMachine::HttpRequest do
|
|
136
136
|
|
137
137
|
EventMachine.run {
|
138
138
|
http = EventMachine::HttpRequest.new('http://www.google.com/').head :redirects => 1
|
139
|
-
http.errback { failed }
|
139
|
+
http.errback { failed(http) }
|
140
140
|
http.callback {
|
141
141
|
http.response_header.status.should == 200
|
142
142
|
EM.stop
|
@@ -151,7 +151,7 @@ describe EventMachine::HttpRequest do
|
|
151
151
|
uri = URI.parse('http://127.0.0.1:8080/')
|
152
152
|
http = EventMachine::HttpRequest.new(uri).get
|
153
153
|
|
154
|
-
http.errback { failed }
|
154
|
+
http.errback { failed(http) }
|
155
155
|
http.callback {
|
156
156
|
http.response_header.status.should == 200
|
157
157
|
http.response.should match(/Hello/)
|
@@ -165,7 +165,7 @@ describe EventMachine::HttpRequest do
|
|
165
165
|
uri = URI.parse('http://127.0.0.1:8080/')
|
166
166
|
http = EventMachine::HttpRequest.new(uri).head
|
167
167
|
|
168
|
-
http.errback {
|
168
|
+
http.errback { failed(http) }
|
169
169
|
http.callback {
|
170
170
|
http.response_header.status.should == 200
|
171
171
|
http.response.should == ""
|
@@ -180,7 +180,7 @@ describe EventMachine::HttpRequest do
|
|
180
180
|
uri = URI.parse('http://127.0.0.1:8080/')
|
181
181
|
http = EventMachine::HttpRequest.new(uri).delete
|
182
182
|
|
183
|
-
http.errback { failed }
|
183
|
+
http.errback { failed(http) }
|
184
184
|
http.callback {
|
185
185
|
http.response_header.status.should == 200
|
186
186
|
http.response.should == ""
|
@@ -193,7 +193,7 @@ describe EventMachine::HttpRequest do
|
|
193
193
|
EventMachine.run {
|
194
194
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/fail').get
|
195
195
|
|
196
|
-
http.errback { failed }
|
196
|
+
http.errback { failed(http) }
|
197
197
|
http.callback {
|
198
198
|
http.response_header.status.should == 404
|
199
199
|
EventMachine.stop
|
@@ -205,7 +205,7 @@ describe EventMachine::HttpRequest do
|
|
205
205
|
EventMachine.run {
|
206
206
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :query => {:q => 'test'}
|
207
207
|
|
208
|
-
http.errback { failed }
|
208
|
+
http.errback { failed(http) }
|
209
209
|
http.callback {
|
210
210
|
http.response_header.status.should == 200
|
211
211
|
http.response.should match(/test/)
|
@@ -218,7 +218,7 @@ describe EventMachine::HttpRequest do
|
|
218
218
|
EventMachine.run {
|
219
219
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :query => "q=test"
|
220
220
|
|
221
|
-
http.errback { failed }
|
221
|
+
http.errback { failed(http) }
|
222
222
|
http.callback {
|
223
223
|
http.response_header.status.should == 200
|
224
224
|
http.response.should match(/test/)
|
@@ -231,7 +231,7 @@ describe EventMachine::HttpRequest do
|
|
231
231
|
EventMachine.run {
|
232
232
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_query').get :query => {:hash => ['value1', 'value2']}
|
233
233
|
|
234
|
-
http.errback { failed }
|
234
|
+
http.errback { failed(http) }
|
235
235
|
http.callback {
|
236
236
|
http.response_header.status.should == 200
|
237
237
|
http.response.should match(/hash\[\]=value1&hash\[\]=value2/)
|
@@ -245,7 +245,7 @@ describe EventMachine::HttpRequest do
|
|
245
245
|
EventMachine.run {
|
246
246
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').put :body => "data"
|
247
247
|
|
248
|
-
http.errback { failed }
|
248
|
+
http.errback { failed(http) }
|
249
249
|
http.callback {
|
250
250
|
http.response_header.status.should == 200
|
251
251
|
http.response.should match(/data/)
|
@@ -258,7 +258,7 @@ describe EventMachine::HttpRequest do
|
|
258
258
|
EventMachine.run {
|
259
259
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => "data"
|
260
260
|
|
261
|
-
http.errback { failed }
|
261
|
+
http.errback { failed(http) }
|
262
262
|
http.callback {
|
263
263
|
http.response_header.status.should == 200
|
264
264
|
http.response.should match(/data/)
|
@@ -271,7 +271,7 @@ describe EventMachine::HttpRequest do
|
|
271
271
|
EventMachine.run {
|
272
272
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => {:stuff => 'string&string'}
|
273
273
|
|
274
|
-
http.errback { failed }
|
274
|
+
http.errback { failed(http) }
|
275
275
|
http.callback {
|
276
276
|
http.response_header.status.should == 200
|
277
277
|
http.response.should == "stuff=string%26string"
|
@@ -284,7 +284,7 @@ describe EventMachine::HttpRequest do
|
|
284
284
|
EventMachine.run {
|
285
285
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :body => {"key1" => 1, "key2" => [2,3]}
|
286
286
|
|
287
|
-
http.errback { failed }
|
287
|
+
http.errback { failed(http) }
|
288
288
|
http.callback {
|
289
289
|
http.response_header.status.should == 200
|
290
290
|
|
@@ -298,7 +298,7 @@ describe EventMachine::HttpRequest do
|
|
298
298
|
EventMachine.run {
|
299
299
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_length').post :body => {"key1" => "data1"}
|
300
300
|
|
301
|
-
http.errback { failed }
|
301
|
+
http.errback { failed(http) }
|
302
302
|
http.callback {
|
303
303
|
http.response_header.status.should == 200
|
304
304
|
|
@@ -312,7 +312,7 @@ describe EventMachine::HttpRequest do
|
|
312
312
|
EventMachine.run {
|
313
313
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :head => {'if-none-match' => 'evar!'}
|
314
314
|
|
315
|
-
http.errback { failed }
|
315
|
+
http.errback { failed(http) }
|
316
316
|
http.callback {
|
317
317
|
http.response_header.status.should == 304
|
318
318
|
EventMachine.stop
|
@@ -326,7 +326,7 @@ describe EventMachine::HttpRequest do
|
|
326
326
|
# digg.com uses chunked encoding
|
327
327
|
http = EventMachine::HttpRequest.new('http://digg.com/news').get
|
328
328
|
|
329
|
-
http.errback { failed }
|
329
|
+
http.errback { failed(http) }
|
330
330
|
http.callback {
|
331
331
|
http.response_header.status.should == 200
|
332
332
|
EventMachine.stop
|
@@ -339,7 +339,7 @@ describe EventMachine::HttpRequest do
|
|
339
339
|
|
340
340
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get :head => {'authorization' => ['user', 'pass']}
|
341
341
|
|
342
|
-
http.errback { failed }
|
342
|
+
http.errback { failed(http) }
|
343
343
|
http.callback {
|
344
344
|
http.response_header.status.should == 200
|
345
345
|
EventMachine.stop
|
@@ -352,7 +352,7 @@ describe EventMachine::HttpRequest do
|
|
352
352
|
oauth_header = 'OAuth oauth_nonce="oqwgSYFUD87MHmJJDv7bQqOF2EPnVus7Wkqj5duNByU", b=c, d=e'
|
353
353
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/oauth_auth').get :head => {'authorization' => oauth_header}
|
354
354
|
|
355
|
-
http.errback { failed }
|
355
|
+
http.errback { failed(http) }
|
356
356
|
http.callback {
|
357
357
|
http.response_header.status.should == 200
|
358
358
|
http.response.should == oauth_header
|
@@ -361,24 +361,39 @@ describe EventMachine::HttpRequest do
|
|
361
361
|
}
|
362
362
|
end
|
363
363
|
|
364
|
-
|
365
|
-
|
364
|
+
context "keepalive" do
|
365
|
+
it "should default to non-keepalive" do
|
366
|
+
EventMachine.run {
|
367
|
+
headers = {'If-Modified-Since' => 'Thu, 05 Aug 2010 22:54:44 GMT'}
|
368
|
+
http = EventMachine::HttpRequest.new('http://www.google.com/images/logos/ps_logo2.png').get :head => headers
|
366
369
|
|
367
|
-
|
370
|
+
http.errback { fail }
|
371
|
+
start = Time.now.to_i
|
372
|
+
http.callback {
|
373
|
+
(start - Time.now.to_i).should be_within(1).of(0)
|
374
|
+
EventMachine.stop
|
375
|
+
}
|
376
|
+
}
|
377
|
+
end
|
368
378
|
|
369
|
-
|
370
|
-
|
371
|
-
http.
|
372
|
-
|
379
|
+
it "should work with keep-alive servers" do
|
380
|
+
EventMachine.run {
|
381
|
+
http = EventMachine::HttpRequest.new('http://mexicodiario.com/touch.public.json.php').get :keepalive => true
|
382
|
+
|
383
|
+
http.errback { failed(http) }
|
384
|
+
http.callback {
|
385
|
+
http.response_header.status.should == 200
|
386
|
+
EventMachine.stop
|
387
|
+
}
|
373
388
|
}
|
374
|
-
|
389
|
+
end
|
375
390
|
end
|
376
391
|
|
377
392
|
it "should return ETag and Last-Modified headers" do
|
378
393
|
EventMachine.run {
|
379
394
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_query').get
|
380
395
|
|
381
|
-
http.errback { failed }
|
396
|
+
http.errback { failed(http) }
|
382
397
|
http.callback {
|
383
398
|
http.response_header.status.should == 200
|
384
399
|
http.response_header.etag.should match('abcdefg')
|
@@ -393,7 +408,7 @@ describe EventMachine::HttpRequest do
|
|
393
408
|
|
394
409
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate"}
|
395
410
|
|
396
|
-
http.errback { failed }
|
411
|
+
http.errback { failed(http) }
|
397
412
|
http.callback {
|
398
413
|
http.response_header.status.should == 200
|
399
414
|
http.response_header["CONTENT_ENCODING"].should == "deflate"
|
@@ -409,7 +424,7 @@ describe EventMachine::HttpRequest do
|
|
409
424
|
|
410
425
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/gzip').get :head => {"accept-encoding" => "gzip, compressed"}
|
411
426
|
|
412
|
-
http.errback { failed }
|
427
|
+
http.errback { failed(http) }
|
413
428
|
http.callback {
|
414
429
|
http.response_header.status.should == 200
|
415
430
|
http.response_header["CONTENT_ENCODING"].should == "gzip"
|
@@ -430,7 +445,7 @@ describe EventMachine::HttpRequest do
|
|
430
445
|
(Time.now.to_i - t).should <= 5
|
431
446
|
EventMachine.stop
|
432
447
|
}
|
433
|
-
http.callback { failed }
|
448
|
+
http.callback { failed(http) }
|
434
449
|
}
|
435
450
|
end
|
436
451
|
|
@@ -438,7 +453,7 @@ describe EventMachine::HttpRequest do
|
|
438
453
|
it "should report last_effective_url" do
|
439
454
|
EventMachine.run {
|
440
455
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
|
441
|
-
http.errback { failed }
|
456
|
+
http.errback { failed(http) }
|
442
457
|
http.callback {
|
443
458
|
http.response_header.status.should == 200
|
444
459
|
http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/'
|
@@ -451,7 +466,7 @@ describe EventMachine::HttpRequest do
|
|
451
466
|
it "should follow location redirects" do
|
452
467
|
EventMachine.run {
|
453
468
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect').get :redirects => 1
|
454
|
-
http.errback { failed }
|
469
|
+
http.errback { failed(http) }
|
455
470
|
http.callback {
|
456
471
|
http.response_header.status.should == 200
|
457
472
|
http.response_header["CONTENT_ENCODING"].should == "gzip"
|
@@ -467,7 +482,7 @@ describe EventMachine::HttpRequest do
|
|
467
482
|
it "should default to 0 redirects" do
|
468
483
|
EventMachine.run {
|
469
484
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect').get
|
470
|
-
http.errback { failed }
|
485
|
+
http.errback { failed(http) }
|
471
486
|
http.callback {
|
472
487
|
http.response_header.status.should == 301
|
473
488
|
http.last_effective_url.to_s.should == 'http://127.0.0.1:8080/gzip'
|
@@ -478,10 +493,10 @@ describe EventMachine::HttpRequest do
|
|
478
493
|
}
|
479
494
|
end
|
480
495
|
|
481
|
-
it "should not invoke redirect logic on failed connections" do
|
496
|
+
it "should not invoke redirect logic on failed(http) connections" do
|
482
497
|
EventMachine.run {
|
483
498
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get :timeout => 0.1, :redirects => 5
|
484
|
-
http.callback { failed }
|
499
|
+
http.callback { failed(http) }
|
485
500
|
http.errback {
|
486
501
|
http.redirects.should == 0
|
487
502
|
EM.stop
|
@@ -492,7 +507,7 @@ describe EventMachine::HttpRequest do
|
|
492
507
|
it "should normalize redirect urls" do
|
493
508
|
EventMachine.run {
|
494
509
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect/bad').get :redirects => 1
|
495
|
-
http.errback { failed }
|
510
|
+
http.errback { failed(http) }
|
496
511
|
http.callback {
|
497
512
|
http.last_effective_url.to_s.should match('http://127.0.0.1:8080/')
|
498
513
|
http.response.should match('Hello, World!')
|
@@ -504,7 +519,7 @@ describe EventMachine::HttpRequest do
|
|
504
519
|
it "should fail gracefully on a missing host in absolute Location header" do
|
505
520
|
EventMachine.run {
|
506
521
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect/nohost').get :redirects => 1
|
507
|
-
http.callback { failed }
|
522
|
+
http.callback { failed(http) }
|
508
523
|
http.errback {
|
509
524
|
http.error.should == 'Location header format error'
|
510
525
|
EM.stop
|
@@ -515,7 +530,7 @@ describe EventMachine::HttpRequest do
|
|
515
530
|
it "should fail gracefully on an invalid host in Location header" do
|
516
531
|
EventMachine.run {
|
517
532
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/redirect/badhost').get :redirects => 1
|
518
|
-
http.callback { failed }
|
533
|
+
http.callback { failed(http) }
|
519
534
|
http.errback {
|
520
535
|
http.error.should == 'unable to resolve server address'
|
521
536
|
EM.stop
|
@@ -529,7 +544,7 @@ describe EventMachine::HttpRequest do
|
|
529
544
|
body = ''
|
530
545
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
|
531
546
|
|
532
|
-
http.errback { failed }
|
547
|
+
http.errback { failed(http) }
|
533
548
|
http.stream { |chunk| body += chunk }
|
534
549
|
|
535
550
|
http.callback {
|
@@ -546,7 +561,7 @@ describe EventMachine::HttpRequest do
|
|
546
561
|
EventMachine.run {
|
547
562
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
|
548
563
|
|
549
|
-
http.errback { failed }
|
564
|
+
http.errback { failed(http) }
|
550
565
|
http.headers { |hash|
|
551
566
|
hash.should be_an_kind_of Hash
|
552
567
|
hash.should include 'CONNECTION'
|
@@ -565,7 +580,7 @@ describe EventMachine::HttpRequest do
|
|
565
580
|
EventMachine.run {
|
566
581
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').get
|
567
582
|
|
568
|
-
http.callback { failed }
|
583
|
+
http.callback { failed(http) }
|
569
584
|
http.headers { |hash|
|
570
585
|
hash.should be_an_kind_of Hash
|
571
586
|
hash.should include 'CONNECTION'
|
@@ -589,7 +604,7 @@ describe EventMachine::HttpRequest do
|
|
589
604
|
body = ''
|
590
605
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/deflate').get :head => {"accept-encoding" => "deflate, compressed"}
|
591
606
|
|
592
|
-
http.errback { failed }
|
607
|
+
http.errback { failed(http) }
|
593
608
|
http.stream { |chunk| body += chunk }
|
594
609
|
|
595
610
|
http.callback {
|
@@ -606,7 +621,7 @@ describe EventMachine::HttpRequest do
|
|
606
621
|
EventMachine.run {
|
607
622
|
http = EventMachine::HttpRequest.new('https://mail.google.com:443/mail/').get
|
608
623
|
|
609
|
-
http.errback { failed }
|
624
|
+
http.errback { failed(http) }
|
610
625
|
http.callback {
|
611
626
|
http.response_header.status.should == 302
|
612
627
|
EventMachine.stop
|
@@ -618,7 +633,7 @@ describe EventMachine::HttpRequest do
|
|
618
633
|
EventMachine.run {
|
619
634
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/set_cookie').get
|
620
635
|
|
621
|
-
http.errback { failed }
|
636
|
+
http.errback { failed(http) }
|
622
637
|
http.callback {
|
623
638
|
http.response_header.status.should == 200
|
624
639
|
http.response_header.cookie.should == "id=1; expires=Tue, 09-Aug-2011 17:53:39 GMT; path=/;"
|
@@ -631,7 +646,7 @@ describe EventMachine::HttpRequest do
|
|
631
646
|
EventMachine.run {
|
632
647
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => 'id=2;'}
|
633
648
|
|
634
|
-
http.errback { failed }
|
649
|
+
http.errback { failed(http) }
|
635
650
|
http.callback {
|
636
651
|
http.response.should == "id=2;"
|
637
652
|
EventMachine.stop
|
@@ -643,7 +658,7 @@ describe EventMachine::HttpRequest do
|
|
643
658
|
EventMachine.run {
|
644
659
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_cookie').get :head => {'cookie' => {'id' => 2}}
|
645
660
|
|
646
|
-
http.errback { failed }
|
661
|
+
http.errback { failed(http) }
|
647
662
|
http.callback {
|
648
663
|
http.response.should == "id=2;"
|
649
664
|
EventMachine.stop
|
@@ -657,7 +672,7 @@ describe EventMachine::HttpRequest do
|
|
657
672
|
@s = StubServer.new("HTTP/1.0 200 OK\r\nConnection: close\r\n\r\nFoo")
|
658
673
|
|
659
674
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
|
660
|
-
http.errback { failed }
|
675
|
+
http.errback { failed(http) }
|
661
676
|
http.callback {
|
662
677
|
http.response.should match(/Foo/)
|
663
678
|
http.response_header['CONTENT_LENGTH'].should_not == 0
|
@@ -673,7 +688,7 @@ describe EventMachine::HttpRequest do
|
|
673
688
|
@s = StubServer.new("HTTP/1.0 200 OK\nContent-Type: text/plain\nContent-Length: 3\nConnection: close\n\nFoo")
|
674
689
|
|
675
690
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8081/').get
|
676
|
-
http.errback { failed }
|
691
|
+
http.errback { failed(http) }
|
677
692
|
http.callback {
|
678
693
|
http.response_header.status.should == 200
|
679
694
|
http.response_header['CONTENT_TYPE'].should == 'text/plain'
|
@@ -691,7 +706,7 @@ describe EventMachine::HttpRequest do
|
|
691
706
|
EventMachine.run {
|
692
707
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post :body => "data"
|
693
708
|
|
694
|
-
http.errback { failed }
|
709
|
+
http.errback { failed(http) }
|
695
710
|
http.callback {
|
696
711
|
http.response_header.status.should == 200
|
697
712
|
http.response.should be_empty
|
@@ -704,7 +719,7 @@ describe EventMachine::HttpRequest do
|
|
704
719
|
EventMachine.run {
|
705
720
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post :body => {:a => :b}
|
706
721
|
|
707
|
-
http.errback { failed }
|
722
|
+
http.errback { failed(http) }
|
708
723
|
http.callback {
|
709
724
|
http.response_header.status.should == 200
|
710
725
|
http.response.should match("application/x-www-form-urlencoded")
|
@@ -715,24 +730,59 @@ describe EventMachine::HttpRequest do
|
|
715
730
|
|
716
731
|
it "should not override content-type when passing in ruby hash/array for body" do
|
717
732
|
EventMachine.run {
|
733
|
+
ct = 'text; charset=utf-8'
|
718
734
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post({
|
719
|
-
:body => {:a => :b}, :head => {'content-type' =>
|
735
|
+
:body => {:a => :b}, :head => {'content-type' => ct}})
|
720
736
|
|
721
|
-
http.errback { failed }
|
737
|
+
http.errback { failed(http) }
|
722
738
|
http.callback {
|
723
739
|
http.response_header.status.should == 200
|
724
|
-
http.
|
740
|
+
http.content_charset.should == Encoding.find('utf-8')
|
741
|
+
http.response_header["CONTENT_TYPE"].should == ct
|
725
742
|
EventMachine.stop
|
726
743
|
}
|
727
744
|
}
|
728
745
|
end
|
746
|
+
|
747
|
+
it "should default to external encoding on invalid encoding" do
|
748
|
+
EventMachine.run {
|
749
|
+
ct = 'text/html; charset=utf-8lias'
|
750
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post({
|
751
|
+
:body => {:a => :b}, :head => {'content-type' => ct}})
|
752
|
+
|
753
|
+
http.errback { failed(http) }
|
754
|
+
http.callback {
|
755
|
+
http.response_header.status.should == 200
|
756
|
+
http.content_charset.should == Encoding.find('utf-8')
|
757
|
+
http.response_header["CONTENT_TYPE"].should == ct
|
758
|
+
EventMachine.stop
|
759
|
+
}
|
760
|
+
}
|
761
|
+
end
|
762
|
+
|
763
|
+
it "should processed escaped content-type" do
|
764
|
+
EventMachine.run {
|
765
|
+
ct = "text/html; charset=\"ISO-8859-4\""
|
766
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post({
|
767
|
+
:body => {:a => :b}, :head => {'content-type' => ct}})
|
768
|
+
|
769
|
+
http.errback { failed(http) }
|
770
|
+
http.callback {
|
771
|
+
http.response_header.status.should == 200
|
772
|
+
http.content_charset.should == Encoding.find('ISO-8859-4')
|
773
|
+
http.response_header["CONTENT_TYPE"].should == ct
|
774
|
+
EventMachine.stop
|
775
|
+
}
|
776
|
+
}
|
777
|
+
end
|
778
|
+
|
729
779
|
end
|
730
780
|
|
731
781
|
it "should complete a Location: with a relative path" do
|
732
782
|
EventMachine.run {
|
733
783
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/relative-location').get
|
734
784
|
|
735
|
-
http.errback { failed }
|
785
|
+
http.errback { failed(http) }
|
736
786
|
http.callback {
|
737
787
|
http.response_header['LOCATION'].should == 'http://127.0.0.1:8080/forwarded'
|
738
788
|
EventMachine.stop
|
@@ -744,7 +794,7 @@ describe EventMachine::HttpRequest do
|
|
744
794
|
EventMachine.run {
|
745
795
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/').post :file => 'spec/fixtures/google.ca'
|
746
796
|
|
747
|
-
http.errback { failed }
|
797
|
+
http.errback { failed(http) }
|
748
798
|
http.callback {
|
749
799
|
http.response.should match('google')
|
750
800
|
EventMachine.stop
|
@@ -760,7 +810,7 @@ describe EventMachine::HttpRequest do
|
|
760
810
|
c.options[:body] = {:callback_run => 'yes'}
|
761
811
|
client = c
|
762
812
|
}
|
763
|
-
http.errback { failed }
|
813
|
+
http.errback { failed(http) }
|
764
814
|
http.callback {
|
765
815
|
client.should be_kind_of(EventMachine::HttpClient)
|
766
816
|
http.response_header.status.should == 200
|
@@ -797,7 +847,7 @@ describe EventMachine::HttpRequest do
|
|
797
847
|
:host => '127.0.0.1', :port => 8083
|
798
848
|
}
|
799
849
|
|
800
|
-
http.errback {
|
850
|
+
http.errback { failed(http) }
|
801
851
|
http.callback {
|
802
852
|
http.response_header.status.should == 200
|
803
853
|
http.response.should match('test')
|
@@ -813,7 +863,7 @@ describe EventMachine::HttpRequest do
|
|
813
863
|
:host => '127.0.0.1', :port => 8083
|
814
864
|
}
|
815
865
|
|
816
|
-
http.errback {
|
866
|
+
http.errback { failed(http) }
|
817
867
|
http.callback {
|
818
868
|
http.response_header.status.should == 200
|
819
869
|
# The test proxy server gives the requested uri back in this header
|
@@ -833,7 +883,7 @@ describe EventMachine::HttpRequest do
|
|
833
883
|
:query => { 'q' => 'test' }
|
834
884
|
)
|
835
885
|
|
836
|
-
http.errback {
|
886
|
+
http.errback { failed(http) }
|
837
887
|
http.callback {
|
838
888
|
http.response_header.status.should == 200
|
839
889
|
http.response.should match('test')
|
@@ -851,7 +901,7 @@ describe EventMachine::HttpRequest do
|
|
851
901
|
:proxy => {:host => '127.0.0.1', :port => 8082, :use_connect => true}
|
852
902
|
})
|
853
903
|
|
854
|
-
http.errback {
|
904
|
+
http.errback { failed(http) }
|
855
905
|
http.callback {
|
856
906
|
http.response_header.status.should == 200
|
857
907
|
http.response.should == 'Hello, World!'
|
@@ -867,7 +917,7 @@ describe EventMachine::HttpRequest do
|
|
867
917
|
:body => "data", :proxy => {:host => '127.0.0.1', :port => 8082, :use_connect => true}
|
868
918
|
})
|
869
919
|
|
870
|
-
http.errback { failed }
|
920
|
+
http.errback { failed(http) }
|
871
921
|
http.callback {
|
872
922
|
http.response_header.status.should == 200
|
873
923
|
http.response.should match(/data/)
|
@@ -890,7 +940,7 @@ describe EventMachine::HttpRequest do
|
|
890
940
|
EventMachine.run {
|
891
941
|
http = EventMachine::HttpRequest.new('ws://127.0.0.1:8080/').get :timeout => 0
|
892
942
|
|
893
|
-
http.callback { failed }
|
943
|
+
http.callback { failed(http) }
|
894
944
|
http.errback {
|
895
945
|
http.response_header.status.should == 200
|
896
946
|
EventMachine.stop
|
@@ -907,7 +957,7 @@ describe EventMachine::HttpRequest do
|
|
907
957
|
end
|
908
958
|
|
909
959
|
http = EventMachine::HttpRequest.new('ws://127.0.0.1:8085/').get :timeout => 1
|
910
|
-
http.errback { failed }
|
960
|
+
http.errback { failed(http) }
|
911
961
|
http.callback {
|
912
962
|
http.response_header.status.should == 101
|
913
963
|
http.response_header['CONNECTION'].should match(/Upgrade/)
|
@@ -938,7 +988,7 @@ describe EventMachine::HttpRequest do
|
|
938
988
|
|
939
989
|
EventMachine.add_timer(0.1) do
|
940
990
|
http = EventMachine::HttpRequest.new('ws://127.0.0.1:8085/').get :timeout => 0
|
941
|
-
http.errback { failed }
|
991
|
+
http.errback { failed(http) }
|
942
992
|
http.callback { http.response_header.status.should == 101 }
|
943
993
|
http.stream {|msg|
|
944
994
|
msg.should == messages[recieved.size]
|