em-http-request 1.0.0.beta.3 → 1.0.0.beta.4
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/.gemtest +0 -0
- data/Gemfile +12 -1
- data/README.md +2 -2
- data/Rakefile +2 -1
- data/benchmarks/clients.rb +156 -0
- data/benchmarks/em-excon.rb +87 -0
- data/benchmarks/em-profile.gif +0 -0
- data/benchmarks/em-profile.txt +65 -0
- data/benchmarks/server.rb +48 -0
- data/em-http-request.gemspec +2 -1
- data/examples/.gitignore +1 -0
- data/examples/fibered-http.rb +10 -6
- data/examples/oauth-tweet.rb +22 -37
- data/lib/em-http.rb +3 -2
- data/lib/em-http/client.rb +52 -37
- data/lib/em-http/decoders.rb +1 -1
- data/lib/em-http/http_client_options.rb +56 -0
- data/lib/em-http/http_connection.rb +97 -41
- data/lib/em-http/http_connection_options.rb +23 -0
- data/lib/em-http/http_encoding.rb +1 -1
- data/lib/em-http/middleware/cookie_jar.rb +38 -0
- data/lib/em-http/middleware/json_response.rb +15 -0
- data/lib/em-http/middleware/oauth.rb +21 -0
- data/lib/em-http/multi.rb +18 -18
- data/lib/em-http/request.rb +7 -29
- data/lib/em-http/version.rb +1 -1
- data/spec/client_spec.rb +39 -0
- data/spec/external_spec.rb +17 -1
- data/spec/helper.rb +12 -0
- data/spec/middleware_spec.rb +85 -7
- data/spec/multi_spec.rb +77 -22
- data/spec/pipelining_spec.rb +1 -1
- data/spec/redirect_spec.rb +86 -0
- data/spec/socksify_proxy_spec.rb +14 -14
- data/spec/stallion.rb +33 -2
- metadata +28 -6
- data/lib/em-http/http_options.rb +0 -53
data/examples/oauth-tweet.rb
CHANGED
@@ -1,50 +1,35 @@
|
|
1
|
-
|
2
|
-
# http://gist.github.com/265261
|
3
|
-
#
|
4
|
-
|
5
|
-
require 'rubygems'
|
1
|
+
$: << 'lib' << '../lib'
|
6
2
|
|
7
3
|
require 'em-http'
|
8
|
-
require 'oauth'
|
9
|
-
|
10
|
-
# At a minimum, require 'oauth/request_proxy/em_http_request'
|
11
|
-
# for this example, we'll use Net::HTTP like support.
|
12
|
-
require 'oauth/client/em_http'
|
4
|
+
require 'em-http/middleware/oauth'
|
5
|
+
require 'em-http/middleware/json_response'
|
13
6
|
|
14
|
-
|
15
|
-
# You need to generate an access token, I suggest looking elsewhere how to do that or wait for a full tutorial.
|
16
|
-
# For a consumer key / consumer secret, signup for an app at:
|
17
|
-
# http://twitter.com/apps/new
|
7
|
+
require 'pp'
|
18
8
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def twitter_oauth_consumer
|
26
|
-
@twitter_oauth_consumer ||= OAuth::Consumer.new(CONSUMER_KEY, CONSUMER_SECRET, :site => "http://twitter.com")
|
27
|
-
end
|
28
|
-
|
29
|
-
def twitter_oauth_access_token
|
30
|
-
@twitter_oauth_access_token ||= OAuth::AccessToken.new(twitter_oauth_consumer, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
|
31
|
-
end
|
9
|
+
OAuthConfig = {
|
10
|
+
:consumer_key => '',
|
11
|
+
:consumer_secret => '',
|
12
|
+
:access_token => '',
|
13
|
+
:access_token_secret => ''
|
14
|
+
}
|
32
15
|
|
33
16
|
EM.run do
|
17
|
+
# automatically parse the JSON response into a Ruby object
|
18
|
+
EventMachine::HttpRequest.use EventMachine::Middleware::JSONResponse
|
34
19
|
|
35
|
-
request
|
36
|
-
|
37
|
-
|
38
|
-
end
|
20
|
+
# sign the request with OAuth credentials
|
21
|
+
conn = EventMachine::HttpRequest.new('http://api.twitter.com/1/statuses/home_timeline.json')
|
22
|
+
conn.use EventMachine::Middleware::OAuth, OAuthConfig
|
39
23
|
|
24
|
+
http = conn.get
|
40
25
|
http.callback do
|
41
|
-
|
42
|
-
EM.
|
26
|
+
pp http.response
|
27
|
+
EM.stop
|
43
28
|
end
|
44
29
|
|
45
30
|
http.errback do
|
46
|
-
puts "Failed
|
47
|
-
|
31
|
+
puts "Failed retrieving user stream."
|
32
|
+
pp http.response
|
33
|
+
EM.stop
|
48
34
|
end
|
49
|
-
|
50
|
-
end
|
35
|
+
end
|
data/lib/em-http.rb
CHANGED
@@ -10,8 +10,9 @@ require 'em-http/core_ext/bytesize'
|
|
10
10
|
require 'em-http/http_connection'
|
11
11
|
require 'em-http/http_header'
|
12
12
|
require 'em-http/http_encoding'
|
13
|
-
require 'em-http/
|
13
|
+
require 'em-http/http_client_options'
|
14
|
+
require 'em-http/http_connection_options'
|
14
15
|
require 'em-http/client'
|
15
16
|
require 'em-http/multi'
|
16
17
|
require 'em-http/request'
|
17
|
-
require 'em-http/decoders'
|
18
|
+
require 'em-http/decoders'
|
data/lib/em-http/client.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module EventMachine
|
2
|
+
|
2
3
|
class HttpClient
|
3
4
|
include Deferrable
|
4
5
|
include HttpEncoding
|
@@ -17,17 +18,15 @@ module EventMachine
|
|
17
18
|
CRLF="\r\n"
|
18
19
|
|
19
20
|
attr_accessor :state, :response
|
20
|
-
attr_reader :response_header, :error, :content_charset, :req
|
21
|
+
attr_reader :response_header, :error, :content_charset, :req, :cookies
|
21
22
|
|
22
|
-
def initialize(conn,
|
23
|
+
def initialize(conn, options)
|
23
24
|
@conn = conn
|
24
|
-
|
25
|
-
@req = req
|
26
|
-
@method = req.method
|
27
|
-
@options = options
|
25
|
+
@req = options
|
28
26
|
|
29
27
|
@stream = nil
|
30
28
|
@headers = nil
|
29
|
+
@cookies = []
|
31
30
|
|
32
31
|
reset!
|
33
32
|
end
|
@@ -43,14 +42,15 @@ module EventMachine
|
|
43
42
|
end
|
44
43
|
|
45
44
|
def last_effective_url; @req.uri; end
|
46
|
-
def redirects; @req.
|
45
|
+
def redirects; @req.followed; end
|
46
|
+
def peer; @conn.peer; end
|
47
47
|
|
48
48
|
def connection_completed
|
49
49
|
@state = :response_header
|
50
50
|
|
51
|
-
head, body = build_request, @
|
51
|
+
head, body = build_request, @req.body
|
52
52
|
@conn.middleware.each do |m|
|
53
|
-
head, body = m.request(head, body) if m.respond_to?(:request)
|
53
|
+
head, body = m.request(self, head, body) if m.respond_to?(:request)
|
54
54
|
end
|
55
55
|
|
56
56
|
send_request(head, body)
|
@@ -66,6 +66,10 @@ module EventMachine
|
|
66
66
|
unbind
|
67
67
|
end
|
68
68
|
|
69
|
+
def continue?
|
70
|
+
@response_header.status == 100 && (@req.method == 'POST' || @req.method == 'PUT')
|
71
|
+
end
|
72
|
+
|
69
73
|
def finished?
|
70
74
|
@state == :finished || (@state == :body && @response_header.content_length.nil?)
|
71
75
|
end
|
@@ -77,8 +81,26 @@ module EventMachine
|
|
77
81
|
def unbind
|
78
82
|
if finished?
|
79
83
|
if redirect?
|
80
|
-
|
81
|
-
|
84
|
+
|
85
|
+
begin
|
86
|
+
@conn.middleware.each do |m|
|
87
|
+
m.response(self) if m.respond_to?(:response)
|
88
|
+
end
|
89
|
+
|
90
|
+
# one of the injected middlewares could have changed
|
91
|
+
# our redirect settings, check if we still want to
|
92
|
+
# follow the location header
|
93
|
+
if redirect?
|
94
|
+
@req.followed += 1
|
95
|
+
@req.set_uri(@response_header.location)
|
96
|
+
@conn.redirect(self)
|
97
|
+
else
|
98
|
+
succeed(self)
|
99
|
+
end
|
100
|
+
|
101
|
+
rescue Exception => e
|
102
|
+
on_error(e.message)
|
103
|
+
end
|
82
104
|
else
|
83
105
|
succeed(self)
|
84
106
|
end
|
@@ -101,32 +123,22 @@ module EventMachine
|
|
101
123
|
body.is_a?(Hash) ? form_encode_body(body) : body
|
102
124
|
end
|
103
125
|
|
104
|
-
def proxy?; !@options[:proxy].nil?; end
|
105
|
-
def http_proxy?; proxy? && [nil, :http].include?(@options[:proxy][:type]); end
|
106
|
-
|
107
|
-
def ssl?; @req.uri.scheme == "https" || @req.uri.port == 443; end
|
108
|
-
|
109
|
-
def continue?
|
110
|
-
@response_header.status == 100 && (@method == 'POST' || @method == 'PUT')
|
111
|
-
end
|
112
|
-
|
113
126
|
def build_request
|
114
|
-
head = @
|
115
|
-
proxy = @
|
127
|
+
head = @req.headers ? munge_header_keys(@req.headers) : {}
|
128
|
+
proxy = @req.proxy
|
116
129
|
|
117
|
-
if http_proxy?
|
118
|
-
|
119
|
-
head = proxy[:head] ? munge_header_keys(proxy[:head]) : {}
|
120
|
-
head['proxy-authorization'] = proxy[:authorization] if proxy[:authorization]
|
130
|
+
if @req.http_proxy?
|
131
|
+
head['proxy-authorization'] = @req.proxy[:authorization] if @req.proxy[:authorization]
|
121
132
|
end
|
122
133
|
|
123
134
|
# Set the cookie header if provided
|
124
|
-
if cookie = head
|
125
|
-
|
135
|
+
if cookie = head['cookie']
|
136
|
+
@cookies << encode_cookie(cookie) if cookie
|
126
137
|
end
|
138
|
+
head['cookie'] = @cookies.compact.uniq.join("; ").squeeze(";") unless @cookies.empty?
|
127
139
|
|
128
140
|
# Set connection close unless keepalive
|
129
|
-
|
141
|
+
if !@req.keepalive
|
130
142
|
head['connection'] = 'close'
|
131
143
|
end
|
132
144
|
|
@@ -141,8 +153,8 @@ module EventMachine
|
|
141
153
|
|
142
154
|
def send_request(head, body)
|
143
155
|
body = normalize_body(body)
|
144
|
-
file = @
|
145
|
-
query = @
|
156
|
+
file = @req.file
|
157
|
+
query = @req.query
|
146
158
|
|
147
159
|
# Set the Content-Length if file is given
|
148
160
|
head['content-length'] = File.size(file) if file
|
@@ -151,19 +163,19 @@ module EventMachine
|
|
151
163
|
head['content-length'] = body.bytesize if body
|
152
164
|
|
153
165
|
# Set content-type header if missing and body is a Ruby hash
|
154
|
-
if not head['content-type'] and @
|
166
|
+
if not head['content-type'] and @req.body.is_a? Hash
|
155
167
|
head['content-type'] = 'application/x-www-form-urlencoded'
|
156
168
|
end
|
157
169
|
|
158
|
-
request_header ||= encode_request(@method, @req.uri, query, @conn.
|
170
|
+
request_header ||= encode_request(@req.method, @req.uri, query, @conn.connopts.proxy)
|
159
171
|
request_header << encode_headers(head)
|
160
172
|
request_header << CRLF
|
161
173
|
@conn.send_data request_header
|
162
174
|
|
163
175
|
if body
|
164
176
|
@conn.send_data body
|
165
|
-
elsif @
|
166
|
-
@conn.stream_file_data @
|
177
|
+
elsif @req.file
|
178
|
+
@conn.stream_file_data @req.file, :http_chunks => false
|
167
179
|
end
|
168
180
|
end
|
169
181
|
|
@@ -207,6 +219,9 @@ module EventMachine
|
|
207
219
|
return
|
208
220
|
end
|
209
221
|
|
222
|
+
# add set-cookie's to cookie list
|
223
|
+
@cookies << @response_header.cookie if @response_header.cookie && @req.pass_cookies
|
224
|
+
|
210
225
|
# correct location header - some servers will incorrectly give a relative URI
|
211
226
|
if @response_header.location
|
212
227
|
begin
|
@@ -229,7 +244,7 @@ module EventMachine
|
|
229
244
|
# Fire callbacks immediately after recieving header requests
|
230
245
|
# if the request method is HEAD. In case of a redirect, terminate
|
231
246
|
# current connection and reinitialize the process.
|
232
|
-
if @method == "HEAD"
|
247
|
+
if @req.method == "HEAD"
|
233
248
|
@state = :finished
|
234
249
|
return
|
235
250
|
end
|
@@ -242,7 +257,7 @@ module EventMachine
|
|
242
257
|
@state = :body
|
243
258
|
end
|
244
259
|
|
245
|
-
if decoder_class = HttpDecoders.decoder_for_encoding(response_header[CONTENT_ENCODING])
|
260
|
+
if @req.decoding && decoder_class = HttpDecoders.decoder_for_encoding(response_header[CONTENT_ENCODING])
|
246
261
|
begin
|
247
262
|
@content_decoder = decoder_class.new do |s| on_decoded_body_data(s) end
|
248
263
|
rescue HttpDecoders::DecoderError
|
data/lib/em-http/decoders.rb
CHANGED
@@ -71,7 +71,7 @@ module EventMachine::HttpDecoders
|
|
71
71
|
class Deflate < Base
|
72
72
|
def decompress(compressed)
|
73
73
|
begin
|
74
|
-
@zstream ||= Zlib::Inflate.new(
|
74
|
+
@zstream ||= Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
75
75
|
@zstream.inflate(compressed)
|
76
76
|
rescue Zlib::Error
|
77
77
|
raise DecoderError
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class HttpClientOptions
|
2
|
+
attr_reader :uri, :method, :host, :port, :proxy
|
3
|
+
attr_reader :headers, :file, :body, :query, :path
|
4
|
+
attr_reader :keepalive, :pass_cookies, :decoding
|
5
|
+
|
6
|
+
attr_accessor :followed, :redirects
|
7
|
+
|
8
|
+
def initialize(uri, options, method)
|
9
|
+
@keepalive = options[:keepalive] || false # default to single request per connection
|
10
|
+
@redirects = options[:redirects] ||= 0 # default number of redirects to follow
|
11
|
+
@followed = options[:followed] ||= 0 # keep track of number of followed requests
|
12
|
+
|
13
|
+
@method = method.to_s.upcase
|
14
|
+
@headers = options[:head] || {}
|
15
|
+
@proxy = options[:proxy] || {}
|
16
|
+
@query = options[:query]
|
17
|
+
@path = options[:path]
|
18
|
+
|
19
|
+
@file = options[:file]
|
20
|
+
@body = options[:body]
|
21
|
+
|
22
|
+
@pass_cookies = options.fetch(:pass_cookies, true) # pass cookies between redirects
|
23
|
+
@decoding = options.fetch(:decoding, true) # auto-decode compressed response
|
24
|
+
|
25
|
+
set_uri(uri)
|
26
|
+
end
|
27
|
+
|
28
|
+
def follow_redirect?; @followed < @redirects; end
|
29
|
+
def http_proxy?; @proxy && [nil, :http].include?(@proxy[:type]); end
|
30
|
+
def ssl?; @uri.scheme == "https" || @uri.port == 443; end
|
31
|
+
|
32
|
+
def set_uri(uri)
|
33
|
+
uri = uri.kind_of?(Addressable::URI) ? uri : Addressable::URI::parse(uri.to_s)
|
34
|
+
uri.path = '/' if uri.path.empty?
|
35
|
+
uri.path = @path if @path
|
36
|
+
|
37
|
+
@uri = uri
|
38
|
+
|
39
|
+
# Make sure the ports are set as Addressable::URI doesn't
|
40
|
+
# set the port if it isn't there
|
41
|
+
if @uri.scheme == "https"
|
42
|
+
@uri.port ||= 443
|
43
|
+
else
|
44
|
+
@uri.port ||= 80
|
45
|
+
end
|
46
|
+
|
47
|
+
if !@proxy.empty?
|
48
|
+
@host = @proxy[:host]
|
49
|
+
@port = @proxy[:port]
|
50
|
+
else
|
51
|
+
@host = @uri.host
|
52
|
+
@port = @uri.port
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -8,40 +8,90 @@ module EventMachine
|
|
8
8
|
def post options = {}, &blk; setup_request(:post, options, &blk); end
|
9
9
|
end
|
10
10
|
|
11
|
-
class
|
12
|
-
include HTTPMethods
|
11
|
+
class HttpStubConnection < Connection
|
13
12
|
include Deferrable
|
13
|
+
attr_reader :parent
|
14
14
|
|
15
|
-
|
15
|
+
def parent=(p)
|
16
|
+
@parent = p
|
17
|
+
@parent.conn = self
|
18
|
+
end
|
16
19
|
|
17
|
-
def
|
18
|
-
@
|
20
|
+
def receive_data(data)
|
21
|
+
@parent.receive_data data
|
19
22
|
end
|
20
23
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
def connection_completed
|
25
|
+
@parent.connection_completed
|
26
|
+
end
|
27
|
+
|
28
|
+
def unbind
|
29
|
+
@parent.unbind
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
28
|
-
class HttpConnection
|
33
|
+
class HttpConnection
|
29
34
|
include HTTPMethods
|
30
|
-
include Deferrable
|
31
35
|
include Socksify
|
32
36
|
|
33
|
-
|
37
|
+
attr_reader :deferred
|
38
|
+
attr_accessor :error, :connopts, :uri, :conn
|
34
39
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
40
|
+
def initialize
|
41
|
+
@deferred = true
|
42
|
+
@middleware = []
|
43
|
+
end
|
44
|
+
|
45
|
+
def conn=(c)
|
46
|
+
@conn = c
|
47
|
+
@deferred = false
|
48
|
+
end
|
49
|
+
|
50
|
+
def activate_connection(client)
|
51
|
+
begin
|
52
|
+
EventMachine.connect(@connopts.host, @connopts.port, HttpStubConnection) do |conn|
|
53
|
+
post_init
|
54
|
+
|
55
|
+
@deferred = false
|
56
|
+
@conn = conn
|
57
|
+
|
58
|
+
conn.parent = self
|
59
|
+
conn.pending_connect_timeout = @connopts.connect_timeout
|
60
|
+
conn.comm_inactivity_timeout = @connopts.inactivity_timeout
|
61
|
+
end
|
62
|
+
|
63
|
+
finalize_request(client)
|
64
|
+
rescue EventMachine::ConnectionError => e
|
65
|
+
#
|
66
|
+
# Currently, this can only fire on initial connection setup
|
67
|
+
# since #connect is a synchronous method. Hence, rescue the
|
68
|
+
# exception, and return a failed deferred which will immediately
|
69
|
+
# fail any client request.
|
70
|
+
#
|
71
|
+
# Once there is async-DNS, then we'll iterate over the outstanding
|
72
|
+
# client requests and fail them in order.
|
73
|
+
#
|
74
|
+
# Net outcome: failed connection will invoke the same ConnectionError
|
75
|
+
# message on the connection deferred, and on the client deferred.
|
76
|
+
#
|
77
|
+
client.close(e.message)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def setup_request(method, options = {}, c = nil)
|
82
|
+
c ||= HttpClient.new(self, HttpClientOptions.new(@uri, options, method))
|
83
|
+
@deferred ? activate_connection(c) : finalize_request(c)
|
84
|
+
c
|
85
|
+
end
|
86
|
+
|
87
|
+
def finalize_request(c)
|
88
|
+
@conn.callback { c.connection_completed }
|
38
89
|
|
39
90
|
middleware.each do |m|
|
40
91
|
c.callback &m.method(:response) if m.respond_to?(:response)
|
41
92
|
end
|
42
93
|
|
43
94
|
@clients.push c
|
44
|
-
c
|
45
95
|
end
|
46
96
|
|
47
97
|
def middleware
|
@@ -52,19 +102,17 @@ module EventMachine
|
|
52
102
|
@clients = []
|
53
103
|
@pending = []
|
54
104
|
|
55
|
-
@middleware = []
|
56
|
-
|
57
105
|
@p = Http::Parser.new
|
58
106
|
@p.on_headers_complete = proc do |h|
|
59
|
-
|
107
|
+
client.parse_response_header(h, @p.http_version, @p.status_code)
|
60
108
|
end
|
61
109
|
|
62
110
|
@p.on_body = proc do |b|
|
63
|
-
|
111
|
+
client.on_body_data(b)
|
64
112
|
end
|
65
113
|
|
66
114
|
@p.on_message_complete = proc do
|
67
|
-
if not
|
115
|
+
if not client.continue?
|
68
116
|
c = @clients.shift
|
69
117
|
c.state = :finished
|
70
118
|
c.on_request_complete
|
@@ -72,8 +120,12 @@ module EventMachine
|
|
72
120
|
end
|
73
121
|
end
|
74
122
|
|
75
|
-
def use(klass)
|
76
|
-
@middleware << klass
|
123
|
+
def use(klass, *args, &block)
|
124
|
+
@middleware << klass.new(*args, &block)
|
125
|
+
end
|
126
|
+
|
127
|
+
def peer
|
128
|
+
Socket.unpack_sockaddr_in(@peer)[1] rescue nil
|
77
129
|
end
|
78
130
|
|
79
131
|
def receive_data(data)
|
@@ -81,35 +133,31 @@ module EventMachine
|
|
81
133
|
@p << data
|
82
134
|
rescue HTTP::Parser::Error => e
|
83
135
|
c = @clients.shift
|
84
|
-
c.on_error(e.message)
|
136
|
+
c.nil? ? unbind : c.on_error(e.message)
|
85
137
|
end
|
86
138
|
end
|
87
139
|
|
88
140
|
def connection_completed
|
89
|
-
|
90
|
-
socksify(client.req.uri.host, client.req.uri.port, *@opts.proxy[:authorization]) { start }
|
141
|
+
@peer = @conn.get_peername
|
91
142
|
|
143
|
+
if @connopts.proxy && @connopts.proxy[:type] == :socks5
|
144
|
+
socksify(client.req.uri.host, client.req.uri.port, *@connopts.proxy[:authorization]) { start }
|
92
145
|
else
|
93
146
|
start
|
94
147
|
end
|
95
148
|
end
|
96
149
|
|
97
150
|
def start
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
succeed
|
151
|
+
@conn.start_tls(@connopts.tls) if client && client.req.ssl?
|
152
|
+
@conn.succeed
|
102
153
|
end
|
103
154
|
|
104
|
-
def redirect(client
|
105
|
-
client.req.set_uri(location)
|
155
|
+
def redirect(client)
|
106
156
|
@pending.push client
|
107
|
-
rescue Exception => e
|
108
|
-
client.on_error(e.message)
|
109
157
|
end
|
110
158
|
|
111
159
|
def unbind
|
112
|
-
@clients.map {|c| c.unbind }
|
160
|
+
@clients.map { |c| c.unbind }
|
113
161
|
|
114
162
|
if r = @pending.shift
|
115
163
|
@clients.push r
|
@@ -118,19 +166,27 @@ module EventMachine
|
|
118
166
|
@p.reset!
|
119
167
|
|
120
168
|
begin
|
121
|
-
set_deferred_status :unknown
|
122
|
-
reconnect(r.req.host, r.req.port)
|
123
|
-
callback { r.connection_completed }
|
169
|
+
@conn.set_deferred_status :unknown
|
170
|
+
@conn.reconnect(r.req.host, r.req.port)
|
171
|
+
@conn.callback { r.connection_completed }
|
124
172
|
rescue EventMachine::ConnectionError => e
|
125
173
|
@clients.pop.close(e.message)
|
126
174
|
end
|
127
175
|
end
|
128
176
|
end
|
129
177
|
|
178
|
+
def send_data(data)
|
179
|
+
@conn.send_data data
|
180
|
+
end
|
181
|
+
|
182
|
+
def stream_file_data(filename, args = {})
|
183
|
+
@conn.stream_file_data filename, args
|
184
|
+
end
|
185
|
+
|
130
186
|
private
|
131
187
|
|
132
|
-
|
133
|
-
|
134
|
-
|
188
|
+
def client
|
189
|
+
@clients.first
|
190
|
+
end
|
135
191
|
end
|
136
192
|
end
|