typhoeus 0.1.6 → 0.1.28
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.
- data/.gitignore +2 -0
- data/CHANGELOG.markdown +9 -0
- data/README.textile +312 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/benchmarks/profile.rb +25 -0
- data/benchmarks/vs_nethttp.rb +35 -0
- data/examples/twitter.rb +21 -0
- data/ext/typhoeus/.gitignore +5 -0
- data/ext/typhoeus/extconf.rb +3 -2
- data/ext/typhoeus/native.h +7 -0
- data/ext/typhoeus/typhoeus_multi.c +1 -2
- data/lib/typhoeus/.gitignore +1 -0
- data/lib/typhoeus/easy.rb +155 -37
- data/lib/typhoeus/hydra.rb +69 -21
- data/lib/typhoeus/multi.rb +4 -3
- data/lib/typhoeus/remote_proxy_object.rb +6 -6
- data/lib/typhoeus/request.rb +72 -26
- data/lib/typhoeus/response.rb +32 -2
- data/lib/typhoeus/service.rb +20 -0
- data/lib/typhoeus.rb +7 -7
- data/profilers/valgrind.rb +24 -0
- data/spec/fixtures/result_set.xml +60 -0
- data/spec/servers/app.rb +37 -1
- data/spec/typhoeus/easy_spec.rb +112 -3
- data/spec/typhoeus/hydra_spec.rb +311 -0
- data/spec/typhoeus/remote_spec.rb +1 -1
- data/spec/typhoeus/request_spec.rb +169 -0
- data/spec/typhoeus/response_spec.rb +27 -0
- data/typhoeus.gemspec +113 -0
- metadata +127 -32
data/lib/typhoeus/easy.rb
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
module Typhoeus
|
|
2
2
|
class Easy
|
|
3
|
-
attr_reader :response_body, :response_header, :method, :headers, :url
|
|
3
|
+
attr_reader :response_body, :response_header, :method, :headers, :url, :params
|
|
4
4
|
attr_accessor :start_time
|
|
5
5
|
|
|
6
|
+
# These integer codes are available in curl/curl.h
|
|
6
7
|
CURLINFO_STRING = 1048576
|
|
7
8
|
OPTION_VALUES = {
|
|
8
9
|
:CURLOPT_URL => 10002,
|
|
@@ -16,31 +17,78 @@ module Typhoeus
|
|
|
16
17
|
:CURLOPT_TIMEOUT_MS => 155,
|
|
17
18
|
:CURLOPT_NOSIGNAL => 99,
|
|
18
19
|
:CURLOPT_HTTPHEADER => 10023,
|
|
19
|
-
:CURLOPT_FOLLOWLOCATION => 52
|
|
20
|
+
:CURLOPT_FOLLOWLOCATION => 52,
|
|
21
|
+
:CURLOPT_MAXREDIRS => 68,
|
|
22
|
+
:CURLOPT_HTTPAUTH => 107,
|
|
23
|
+
:CURLOPT_USERPWD => 10000 + 5,
|
|
24
|
+
:CURLOPT_VERBOSE => 41,
|
|
25
|
+
:CURLOPT_PROXY => 10004,
|
|
26
|
+
:CURLOPT_VERIFYPEER => 64,
|
|
27
|
+
:CURLOPT_NOBODY => 44,
|
|
28
|
+
:CURLOPT_ENCODING => 102,
|
|
29
|
+
:CURLOPT_SSLCERT => 10025,
|
|
30
|
+
:CURLOPT_SSLCERTTYPE => 10086,
|
|
31
|
+
:CURLOPT_SSLKEY => 10087,
|
|
32
|
+
:CURLOPT_SSLKEYTYPE => 10088,
|
|
33
|
+
:CURLOPT_KEYPASSWD => 10026,
|
|
34
|
+
:CURLOPT_CAINFO => 10065,
|
|
35
|
+
:CURLOPT_CAPATH => 10097
|
|
20
36
|
}
|
|
21
37
|
INFO_VALUES = {
|
|
22
38
|
:CURLINFO_RESPONSE_CODE => 2097154,
|
|
23
|
-
:CURLINFO_TOTAL_TIME => 3145731
|
|
39
|
+
:CURLINFO_TOTAL_TIME => 3145731,
|
|
40
|
+
:CURLINFO_HTTPAUTH_AVAIL => 0x200000 + 23,
|
|
41
|
+
:CURLINFO_EFFECTIVE_URL => 0x100000 + 1
|
|
24
42
|
}
|
|
25
|
-
|
|
43
|
+
AUTH_TYPES = {
|
|
44
|
+
:CURLAUTH_BASIC => 1,
|
|
45
|
+
:CURLAUTH_DIGEST => 2,
|
|
46
|
+
:CURLAUTH_GSSNEGOTIATE => 4,
|
|
47
|
+
:CURLAUTH_NTLM => 8,
|
|
48
|
+
:CURLAUTH_DIGEST_IE => 16
|
|
49
|
+
}
|
|
50
|
+
|
|
26
51
|
def initialize
|
|
27
52
|
@method = :get
|
|
28
53
|
@post_dat_set = nil
|
|
29
54
|
@headers = {}
|
|
55
|
+
|
|
56
|
+
set_option(OPTION_VALUES[:CURLOPT_ENCODING], 'zlib') if supports_zlib?
|
|
30
57
|
end
|
|
31
|
-
|
|
58
|
+
|
|
32
59
|
def headers=(hash)
|
|
33
60
|
@headers = hash
|
|
34
61
|
end
|
|
35
|
-
|
|
62
|
+
|
|
63
|
+
def proxy=(proxy)
|
|
64
|
+
set_option(OPTION_VALUES[:CURLOPT_PROXY], proxy)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def auth=(authinfo)
|
|
68
|
+
set_option(OPTION_VALUES[:CURLOPT_USERPWD], "#{authinfo[:username]}:#{authinfo[:password]}")
|
|
69
|
+
set_option(OPTION_VALUES[:CURLOPT_HTTPAUTH], authinfo[:method]) if authinfo[:method]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def auth_methods
|
|
73
|
+
get_info_long(INFO_VALUES[:CURLINFO_HTTPAUTH_AVAIL])
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def verbose=(boolean)
|
|
77
|
+
set_option(OPTION_VALUES[:CURLOPT_VERBOSE], !!boolean ? 1 : 0)
|
|
78
|
+
end
|
|
79
|
+
|
|
36
80
|
def total_time_taken
|
|
37
81
|
get_info_double(INFO_VALUES[:CURLINFO_TOTAL_TIME])
|
|
38
82
|
end
|
|
39
|
-
|
|
83
|
+
|
|
84
|
+
def effective_url
|
|
85
|
+
get_info_string(INFO_VALUES[:CURLINFO_EFFECTIVE_URL])
|
|
86
|
+
end
|
|
87
|
+
|
|
40
88
|
def response_code
|
|
41
89
|
get_info_long(INFO_VALUES[:CURLINFO_RESPONSE_CODE])
|
|
42
90
|
end
|
|
43
|
-
|
|
91
|
+
|
|
44
92
|
def follow_location=(boolean)
|
|
45
93
|
if boolean
|
|
46
94
|
set_option(OPTION_VALUES[:CURLOPT_FOLLOWLOCATION], 1)
|
|
@@ -48,17 +96,25 @@ module Typhoeus
|
|
|
48
96
|
set_option(OPTION_VALUES[:CURLOPT_FOLLOWLOCATION], 0)
|
|
49
97
|
end
|
|
50
98
|
end
|
|
51
|
-
|
|
99
|
+
|
|
100
|
+
def max_redirects=(redirects)
|
|
101
|
+
set_option(OPTION_VALUES[:CURLOPT_MAXREDIRS], redirects)
|
|
102
|
+
end
|
|
103
|
+
|
|
52
104
|
def timeout=(milliseconds)
|
|
53
105
|
@timeout = milliseconds
|
|
54
106
|
set_option(OPTION_VALUES[:CURLOPT_NOSIGNAL], 1)
|
|
55
107
|
set_option(OPTION_VALUES[:CURLOPT_TIMEOUT_MS], milliseconds)
|
|
56
108
|
end
|
|
57
|
-
|
|
109
|
+
|
|
58
110
|
def timed_out?
|
|
59
111
|
@timeout && total_time_taken > @timeout && response_code == 0
|
|
60
112
|
end
|
|
61
|
-
|
|
113
|
+
|
|
114
|
+
def supports_zlib?
|
|
115
|
+
!!(curl_version.match(/zlib/))
|
|
116
|
+
end
|
|
117
|
+
|
|
62
118
|
def request_body=(request_body)
|
|
63
119
|
@request_body = request_body
|
|
64
120
|
if @method == :put
|
|
@@ -69,16 +125,20 @@ module Typhoeus
|
|
|
69
125
|
self.post_data = request_body
|
|
70
126
|
end
|
|
71
127
|
end
|
|
72
|
-
|
|
128
|
+
|
|
73
129
|
def user_agent=(user_agent)
|
|
74
130
|
set_option(OPTION_VALUES[:CURLOPT_USERAGENT], user_agent)
|
|
75
131
|
end
|
|
76
|
-
|
|
132
|
+
|
|
77
133
|
def url=(url)
|
|
78
134
|
@url = url
|
|
79
135
|
set_option(OPTION_VALUES[:CURLOPT_URL], url)
|
|
80
136
|
end
|
|
81
|
-
|
|
137
|
+
|
|
138
|
+
def disable_ssl_peer_verification
|
|
139
|
+
set_option(OPTION_VALUES[:CURLOPT_VERIFYPEER], 0)
|
|
140
|
+
end
|
|
141
|
+
|
|
82
142
|
def method=(method)
|
|
83
143
|
@method = method
|
|
84
144
|
if method == :get
|
|
@@ -89,18 +149,21 @@ module Typhoeus
|
|
|
89
149
|
elsif method == :put
|
|
90
150
|
set_option(OPTION_VALUES[:CURLOPT_UPLOAD], 1)
|
|
91
151
|
self.request_body = "" unless @request_body
|
|
152
|
+
elsif method == :head
|
|
153
|
+
set_option(OPTION_VALUES[:CURLOPT_NOBODY], 1)
|
|
92
154
|
else
|
|
93
|
-
set_option(OPTION_VALUES[:CURLOPT_CUSTOMREQUEST],
|
|
155
|
+
set_option(OPTION_VALUES[:CURLOPT_CUSTOMREQUEST], method.to_s.upcase)
|
|
94
156
|
end
|
|
95
157
|
end
|
|
96
|
-
|
|
158
|
+
|
|
97
159
|
def post_data=(data)
|
|
98
160
|
@post_data_set = true
|
|
99
161
|
set_option(OPTION_VALUES[:CURLOPT_POSTFIELDS], data)
|
|
100
162
|
set_option(OPTION_VALUES[:CURLOPT_POSTFIELDSIZE], data.length)
|
|
101
163
|
end
|
|
102
|
-
|
|
164
|
+
|
|
103
165
|
def params=(params)
|
|
166
|
+
@params = params
|
|
104
167
|
params_string = params.keys.collect do |k|
|
|
105
168
|
value = params[k]
|
|
106
169
|
if value.is_a? Hash
|
|
@@ -112,57 +175,111 @@ module Typhoeus
|
|
|
112
175
|
"#{Rack::Utils.escape(k.to_s)}=#{Rack::Utils.escape(params[k].to_s)}"
|
|
113
176
|
end
|
|
114
177
|
end.flatten.join("&")
|
|
115
|
-
|
|
178
|
+
|
|
116
179
|
if method == :post
|
|
117
180
|
self.post_data = params_string
|
|
118
181
|
else
|
|
119
182
|
self.url = "#{url}?#{params_string}"
|
|
120
183
|
end
|
|
121
184
|
end
|
|
122
|
-
|
|
185
|
+
|
|
186
|
+
# Set SSL certificate
|
|
187
|
+
# " The string should be the file name of your certificate. "
|
|
188
|
+
# The default format is "PEM" and can be changed with ssl_cert_type=
|
|
189
|
+
def ssl_cert=(cert)
|
|
190
|
+
set_option(OPTION_VALUES[:CURLOPT_SSLCERT], cert)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Set SSL certificate type
|
|
194
|
+
# " The string should be the format of your certificate. Supported formats are "PEM" and "DER" "
|
|
195
|
+
def ssl_cert_type=(cert_type)
|
|
196
|
+
raise "Invalid ssl cert type : '#{cert_type}'..." if cert_type and !%w(PEM DER).include?(cert_type)
|
|
197
|
+
set_option(OPTION_VALUES[:CURLOPT_SSLCERTTYPE], cert_type)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Set SSL Key file
|
|
201
|
+
# " The string should be the file name of your private key. "
|
|
202
|
+
# The default format is "PEM" and can be changed with ssl_key_type=
|
|
203
|
+
#
|
|
204
|
+
def ssl_key=(key)
|
|
205
|
+
set_option(OPTION_VALUES[:CURLOPT_SSLKEY], key)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Set SSL Key type
|
|
209
|
+
# " The string should be the format of your private key. Supported formats are "PEM", "DER" and "ENG". "
|
|
210
|
+
#
|
|
211
|
+
def ssl_key_type=(key_type)
|
|
212
|
+
raise "Invalid ssl key type : '#{key_type}'..." if key_type and !%w(PEM DER ENG).include?(key_type)
|
|
213
|
+
set_option(OPTION_VALUES[:CURLOPT_SSLKEYTYPE], key_type)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def ssl_key_password=(key_password)
|
|
217
|
+
set_option(OPTION_VALUES[:CURLOPT_KEYPASSWD], key_password)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Set SSL CACERT
|
|
221
|
+
# " File holding one or more certificates to verify the peer with. "
|
|
222
|
+
#
|
|
223
|
+
def ssl_cacert=(cacert)
|
|
224
|
+
set_option(OPTION_VALUES[:CURLOPT_CAINFO], cacert)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Set CAPATH
|
|
228
|
+
# " directory holding multiple CA certificates to verify the peer with. The certificate directory must be prepared using the openssl c_rehash utility. "
|
|
229
|
+
#
|
|
230
|
+
def ssl_capath=(capath)
|
|
231
|
+
set_option(OPTION_VALUES[:CURLOPT_CAPATH], capath)
|
|
232
|
+
end
|
|
233
|
+
|
|
123
234
|
def set_option(option, value)
|
|
124
235
|
if value.class == String
|
|
125
236
|
easy_setopt_string(option, value)
|
|
126
|
-
|
|
237
|
+
elsif value
|
|
127
238
|
easy_setopt_long(option, value)
|
|
128
239
|
end
|
|
129
240
|
end
|
|
130
|
-
|
|
241
|
+
|
|
131
242
|
def perform
|
|
132
243
|
set_headers()
|
|
133
244
|
easy_perform()
|
|
134
|
-
response_code()
|
|
245
|
+
resp_code = response_code()
|
|
246
|
+
if resp_code >= 200 && resp_code <= 299
|
|
247
|
+
success
|
|
248
|
+
else
|
|
249
|
+
failure
|
|
250
|
+
end
|
|
251
|
+
resp_code
|
|
135
252
|
end
|
|
136
|
-
|
|
253
|
+
|
|
137
254
|
def set_headers
|
|
138
255
|
headers.each_pair do |key, value|
|
|
139
256
|
easy_add_header("#{key}: #{value}")
|
|
140
257
|
end
|
|
141
258
|
easy_set_headers() unless headers.empty?
|
|
142
259
|
end
|
|
143
|
-
|
|
260
|
+
|
|
144
261
|
# gets called when finished and response code is 200-299
|
|
145
262
|
def success
|
|
146
263
|
@success.call(self) if @success
|
|
147
264
|
end
|
|
148
|
-
|
|
265
|
+
|
|
149
266
|
def on_success(&block)
|
|
150
267
|
@success = block
|
|
151
268
|
end
|
|
152
|
-
|
|
269
|
+
|
|
153
270
|
def on_success=(block)
|
|
154
271
|
@success = block
|
|
155
272
|
end
|
|
156
|
-
|
|
273
|
+
|
|
157
274
|
# gets called when finished and response code is 300-599
|
|
158
275
|
def failure
|
|
159
276
|
@failure.call(self) if @failure
|
|
160
277
|
end
|
|
161
|
-
|
|
278
|
+
|
|
162
279
|
def on_failure(&block)
|
|
163
280
|
@failure = block
|
|
164
281
|
end
|
|
165
|
-
|
|
282
|
+
|
|
166
283
|
def on_failure=(block)
|
|
167
284
|
@failure = block
|
|
168
285
|
end
|
|
@@ -170,20 +287,20 @@ module Typhoeus
|
|
|
170
287
|
def retries
|
|
171
288
|
@retries ||= 0
|
|
172
289
|
end
|
|
173
|
-
|
|
290
|
+
|
|
174
291
|
def increment_retries
|
|
175
292
|
@retries ||= 0
|
|
176
293
|
@retries += 1
|
|
177
294
|
end
|
|
178
|
-
|
|
295
|
+
|
|
179
296
|
def max_retries
|
|
180
297
|
@max_retries ||= 40
|
|
181
298
|
end
|
|
182
|
-
|
|
299
|
+
|
|
183
300
|
def max_retries?
|
|
184
301
|
retries >= max_retries
|
|
185
302
|
end
|
|
186
|
-
|
|
303
|
+
|
|
187
304
|
def reset
|
|
188
305
|
@retries = 0
|
|
189
306
|
@response_code = 0
|
|
@@ -191,21 +308,22 @@ module Typhoeus
|
|
|
191
308
|
@response_body = ""
|
|
192
309
|
easy_reset()
|
|
193
310
|
end
|
|
194
|
-
|
|
311
|
+
|
|
195
312
|
def get_info_string(option)
|
|
196
313
|
easy_getinfo_string(option)
|
|
197
314
|
end
|
|
198
|
-
|
|
315
|
+
|
|
199
316
|
def get_info_long(option)
|
|
200
317
|
easy_getinfo_long(option)
|
|
201
318
|
end
|
|
202
|
-
|
|
319
|
+
|
|
203
320
|
def get_info_double(option)
|
|
204
321
|
easy_getinfo_double(option)
|
|
205
322
|
end
|
|
206
|
-
|
|
323
|
+
|
|
207
324
|
def curl_version
|
|
208
325
|
version
|
|
209
326
|
end
|
|
327
|
+
|
|
210
328
|
end
|
|
211
329
|
end
|
data/lib/typhoeus/hydra.rb
CHANGED
|
@@ -1,63 +1,82 @@
|
|
|
1
1
|
module Typhoeus
|
|
2
2
|
class Hydra
|
|
3
|
-
def initialize(
|
|
3
|
+
def initialize(options = {})
|
|
4
4
|
@memoize_requests = true
|
|
5
5
|
@multi = Multi.new
|
|
6
6
|
@easy_pool = []
|
|
7
|
+
initial_pool_size = options[:initial_pool_size] || 10
|
|
8
|
+
@max_concurrency = options[:max_concurrency] || 200
|
|
7
9
|
initial_pool_size.times { @easy_pool << Easy.new }
|
|
8
10
|
@stubs = []
|
|
9
11
|
@memoized_requests = {}
|
|
10
12
|
@retrieved_from_cache = {}
|
|
13
|
+
@queued_requests = []
|
|
14
|
+
@running_requests = 0
|
|
15
|
+
@stubbed_request_count = 0
|
|
11
16
|
end
|
|
12
17
|
|
|
13
18
|
def self.hydra
|
|
14
19
|
@hydra ||= new
|
|
15
20
|
end
|
|
16
|
-
|
|
21
|
+
|
|
17
22
|
def self.hydra=(val)
|
|
18
23
|
@hydra = val
|
|
19
24
|
end
|
|
20
|
-
|
|
25
|
+
|
|
26
|
+
def clear_cache_callbacks
|
|
27
|
+
@cache_setter = nil
|
|
28
|
+
@cache_getter = nil
|
|
29
|
+
end
|
|
30
|
+
|
|
21
31
|
def clear_stubs
|
|
22
32
|
@stubs = []
|
|
23
33
|
end
|
|
24
|
-
|
|
34
|
+
|
|
25
35
|
def fire_and_forget
|
|
36
|
+
@queued_requests.each {|r| queue(r, false)}
|
|
26
37
|
@multi.fire_and_forget
|
|
27
38
|
end
|
|
28
39
|
|
|
29
|
-
def queue(request)
|
|
40
|
+
def queue(request, obey_concurrency_limit = true)
|
|
30
41
|
return if assign_to_stub(request)
|
|
31
42
|
|
|
32
|
-
if
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
if @running_requests >= @max_concurrency && obey_concurrency_limit
|
|
44
|
+
@queued_requests << request
|
|
45
|
+
else
|
|
46
|
+
if request.method == :get
|
|
47
|
+
if @memoize_requests && @memoized_requests.has_key?(request.url)
|
|
48
|
+
if response = @retrieved_from_cache[request.url]
|
|
49
|
+
request.response = response
|
|
50
|
+
request.call_handlers
|
|
51
|
+
else
|
|
52
|
+
@memoized_requests[request.url] << request
|
|
53
|
+
end
|
|
37
54
|
else
|
|
38
|
-
@memoized_requests[request.url]
|
|
55
|
+
@memoized_requests[request.url] = [] if @memoize_requests
|
|
56
|
+
get_from_cache_or_queue(request)
|
|
39
57
|
end
|
|
40
58
|
else
|
|
41
|
-
@memoized_requests[request.url] = [] if @memoize_requests
|
|
42
59
|
get_from_cache_or_queue(request)
|
|
43
60
|
end
|
|
44
|
-
else
|
|
45
|
-
get_from_cache_or_queue(request)
|
|
46
61
|
end
|
|
47
62
|
end
|
|
48
63
|
|
|
49
64
|
def run
|
|
50
|
-
@
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
while @stubbed_request_count > 0
|
|
66
|
+
@stubs.each do |m|
|
|
67
|
+
while request = m.requests.shift
|
|
68
|
+
@stubbed_request_count -= 1
|
|
69
|
+
m.response.request = request
|
|
70
|
+
handle_request(request, m.response)
|
|
71
|
+
end
|
|
54
72
|
end
|
|
55
73
|
end
|
|
74
|
+
|
|
56
75
|
@multi.perform
|
|
57
76
|
@memoized_requests = {}
|
|
58
77
|
@retrieved_from_cache = {}
|
|
59
78
|
end
|
|
60
|
-
|
|
79
|
+
|
|
61
80
|
def disable_memoization
|
|
62
81
|
@memoize_requests = false
|
|
63
82
|
end
|
|
@@ -85,7 +104,12 @@ module Typhoeus
|
|
|
85
104
|
|
|
86
105
|
def assign_to_stub(request)
|
|
87
106
|
m = @stubs.detect {|stub| stub.matches? request}
|
|
88
|
-
|
|
107
|
+
if m
|
|
108
|
+
m.add_request(request)
|
|
109
|
+
@stubbed_request_count += 1
|
|
110
|
+
else
|
|
111
|
+
nil
|
|
112
|
+
end
|
|
89
113
|
end
|
|
90
114
|
private :assign_to_stub
|
|
91
115
|
|
|
@@ -105,17 +129,34 @@ module Typhoeus
|
|
|
105
129
|
private :get_from_cache_or_queue
|
|
106
130
|
|
|
107
131
|
def get_easy_object(request)
|
|
132
|
+
@running_requests += 1
|
|
133
|
+
|
|
108
134
|
easy = @easy_pool.pop || Easy.new
|
|
109
135
|
easy.url = request.url
|
|
110
136
|
easy.method = request.method
|
|
137
|
+
easy.params = request.params if request.method == :post && !request.params.nil?
|
|
111
138
|
easy.headers = request.headers if request.headers
|
|
112
139
|
easy.request_body = request.body if request.body
|
|
113
140
|
easy.timeout = request.timeout if request.timeout
|
|
141
|
+
easy.follow_location = request.follow_location if request.follow_location
|
|
142
|
+
easy.max_redirects = request.max_redirects if request.max_redirects
|
|
143
|
+
easy.proxy = request.proxy if request.proxy
|
|
144
|
+
easy.disable_ssl_peer_verification if request.disable_ssl_peer_verification
|
|
145
|
+
easy.ssl_cert = request.ssl_cert
|
|
146
|
+
easy.ssl_cert_type = request.ssl_cert_type
|
|
147
|
+
easy.ssl_key = request.ssl_key
|
|
148
|
+
easy.ssl_key_type = request.ssl_key_type
|
|
149
|
+
easy.ssl_key_password = request.ssl_key_password
|
|
150
|
+
easy.ssl_cacert = request.ssl_cacert
|
|
151
|
+
easy.ssl_capath = request.ssl_capath
|
|
152
|
+
|
|
114
153
|
easy.on_success do |easy|
|
|
154
|
+
queue_next
|
|
115
155
|
handle_request(request, response_from_easy(easy, request))
|
|
116
156
|
release_easy_object(easy)
|
|
117
157
|
end
|
|
118
158
|
easy.on_failure do |easy|
|
|
159
|
+
queue_next
|
|
119
160
|
handle_request(request, response_from_easy(easy, request))
|
|
120
161
|
release_easy_object(easy)
|
|
121
162
|
end
|
|
@@ -124,6 +165,12 @@ module Typhoeus
|
|
|
124
165
|
end
|
|
125
166
|
private :get_easy_object
|
|
126
167
|
|
|
168
|
+
def queue_next
|
|
169
|
+
@running_requests -= 1
|
|
170
|
+
queue(@queued_requests.pop) unless @queued_requests.empty?
|
|
171
|
+
end
|
|
172
|
+
private :queue_next
|
|
173
|
+
|
|
127
174
|
def release_easy_object(easy)
|
|
128
175
|
easy.reset
|
|
129
176
|
@easy_pool.push easy
|
|
@@ -153,6 +200,7 @@ module Typhoeus
|
|
|
153
200
|
:headers => easy.response_header,
|
|
154
201
|
:body => easy.response_body,
|
|
155
202
|
:time => easy.total_time_taken,
|
|
203
|
+
:effective_url => easy.effective_url,
|
|
156
204
|
:request => request)
|
|
157
205
|
end
|
|
158
206
|
private :response_from_easy
|
|
@@ -174,7 +222,7 @@ module Typhoeus
|
|
|
174
222
|
def and_return(val)
|
|
175
223
|
@response = val
|
|
176
224
|
end
|
|
177
|
-
|
|
225
|
+
|
|
178
226
|
def matches?(request)
|
|
179
227
|
if url.kind_of?(String)
|
|
180
228
|
request.method == method && request.url == url
|
data/lib/typhoeus/multi.rb
CHANGED
|
@@ -9,19 +9,20 @@ module Typhoeus
|
|
|
9
9
|
def remove(easy)
|
|
10
10
|
multi_remove_handle(easy)
|
|
11
11
|
end
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
def add(easy)
|
|
14
|
+
easy.set_headers()
|
|
14
15
|
@easy_handles << easy
|
|
15
16
|
multi_add_handle(easy)
|
|
16
17
|
end
|
|
17
|
-
|
|
18
|
+
|
|
18
19
|
def perform()
|
|
19
20
|
while active_handle_count > 0 do
|
|
20
21
|
multi_perform
|
|
21
22
|
end
|
|
22
23
|
reset_easy_handles
|
|
23
24
|
end
|
|
24
|
-
|
|
25
|
+
|
|
25
26
|
def cleanup()
|
|
26
27
|
multi_cleanup
|
|
27
28
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Typhoeus
|
|
2
2
|
class RemoteProxyObject
|
|
3
|
-
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
|
4
|
-
|
|
3
|
+
instance_methods.each { |m| undef_method m unless m =~ /^__|object_id/ }
|
|
4
|
+
|
|
5
5
|
def initialize(clear_memoized_store_proc, easy, options = {})
|
|
6
6
|
@clear_memoized_store_proc = clear_memoized_store_proc
|
|
7
7
|
@easy = easy
|
|
@@ -12,13 +12,13 @@ module Typhoeus
|
|
|
12
12
|
@timeout = options.delete(:cache_timeout)
|
|
13
13
|
Typhoeus.add_easy_request(@easy)
|
|
14
14
|
end
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
def method_missing(sym, *args, &block)
|
|
17
17
|
unless @proxied_object
|
|
18
18
|
if @cache && @cache_key
|
|
19
19
|
@proxied_object = @cache.get(@cache_key) rescue nil
|
|
20
20
|
end
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
unless @proxied_object
|
|
23
23
|
Typhoeus.perform_easy_requests
|
|
24
24
|
response = Response.new(:code => @easy.response_code,
|
|
@@ -31,7 +31,7 @@ module Typhoeus
|
|
|
31
31
|
if @easy.response_code >= 200 && @easy.response_code < 300
|
|
32
32
|
Typhoeus.release_easy_object(@easy)
|
|
33
33
|
@proxied_object = @success.nil? ? response : @success.call(response)
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
if @cache && @cache_key
|
|
36
36
|
@cache.set(@cache_key, @proxied_object, @timeout)
|
|
37
37
|
end
|
|
@@ -41,7 +41,7 @@ module Typhoeus
|
|
|
41
41
|
@clear_memoized_store_proc.call
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
@proxied_object.__send__(sym, *args, &block)
|
|
46
46
|
end
|
|
47
47
|
end
|