typhoeus 0.2.0 → 0.2.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.
- data/CHANGELOG.markdown +26 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +2 -0
- data/LICENSE +20 -0
- data/README.textile +44 -5
- data/Rakefile +8 -5
- data/VERSION +1 -1
- data/examples/file.rb +12 -0
- data/examples/times.rb +40 -0
- data/ext/typhoeus/.gitignore +2 -1
- data/ext/typhoeus/native.c +1 -0
- data/ext/typhoeus/native.h +1 -0
- data/ext/typhoeus/typhoeus_easy.c +32 -7
- data/ext/typhoeus/typhoeus_easy.h +1 -0
- data/ext/typhoeus/typhoeus_form.c +59 -0
- data/ext/typhoeus/typhoeus_form.h +13 -0
- data/ext/typhoeus/typhoeus_multi.c +15 -29
- data/lib/typhoeus/easy.rb +74 -48
- data/lib/typhoeus/form.rb +32 -0
- data/lib/typhoeus/hydra/connect_options.rb +19 -3
- data/lib/typhoeus/hydra.rb +40 -7
- data/lib/typhoeus/multi.rb +7 -5
- data/lib/typhoeus/remote.rb +1 -1
- data/lib/typhoeus/remote_proxy_object.rb +2 -0
- data/lib/typhoeus/request.rb +17 -14
- data/lib/typhoeus/response.rb +16 -1
- data/lib/typhoeus/utils.rb +38 -0
- data/lib/typhoeus.rb +1 -0
- data/spec/fixtures/placeholder.gif +0 -0
- data/spec/fixtures/placeholder.txt +1 -0
- data/spec/fixtures/placeholder.ukn +0 -0
- data/spec/servers/app.rb +10 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/typhoeus/easy_spec.rb +74 -7
- data/spec/typhoeus/filter_spec.rb +2 -2
- data/spec/typhoeus/form_spec.rb +107 -0
- data/spec/typhoeus/hydra_mock_spec.rb +1 -1
- data/spec/typhoeus/hydra_spec.rb +108 -38
- data/spec/typhoeus/multi_spec.rb +1 -1
- data/spec/typhoeus/normalized_header_hash_spec.rb +1 -1
- data/spec/typhoeus/remote_method_spec.rb +2 -2
- data/spec/typhoeus/remote_proxy_object_spec.rb +1 -1
- data/spec/typhoeus/remote_spec.rb +1 -1
- data/spec/typhoeus/request_spec.rb +50 -5
- data/spec/typhoeus/response_spec.rb +13 -1
- data/spec/typhoeus/utils_spec.rb +1 -1
- data/typhoeus.gemspec +93 -75
- metadata +70 -28
- data/.gitignore +0 -3
data/lib/typhoeus/easy.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Typhoeus
|
|
2
2
|
class Easy
|
|
3
|
-
attr_reader :response_body, :response_header, :method, :headers, :url, :params
|
|
3
|
+
attr_reader :response_body, :response_header, :method, :headers, :url, :params, :curl_return_code
|
|
4
4
|
attr_accessor :start_time
|
|
5
5
|
|
|
6
6
|
# These integer codes are available in curl/curl.h
|
|
@@ -28,6 +28,9 @@ module Typhoeus
|
|
|
28
28
|
:CURLOPT_USERPWD => 10000 + 5,
|
|
29
29
|
:CURLOPT_VERBOSE => 41,
|
|
30
30
|
:CURLOPT_PROXY => 10004,
|
|
31
|
+
:CURLOPT_PROXYUSERPWD => 10000 + 6,
|
|
32
|
+
:CURLOPT_PROXYTYPE => 101,
|
|
33
|
+
:CURLOPT_PROXYAUTH => 111,
|
|
31
34
|
:CURLOPT_VERIFYPEER => 64,
|
|
32
35
|
:CURLOPT_NOBODY => 44,
|
|
33
36
|
:CURLOPT_ENCODING => 10000 + 102,
|
|
@@ -37,13 +40,19 @@ module Typhoeus
|
|
|
37
40
|
:CURLOPT_SSLKEYTYPE => 10088,
|
|
38
41
|
:CURLOPT_KEYPASSWD => 10026,
|
|
39
42
|
:CURLOPT_CAINFO => 10065,
|
|
40
|
-
:CURLOPT_CAPATH => 10097
|
|
43
|
+
:CURLOPT_CAPATH => 10097,
|
|
41
44
|
}
|
|
42
45
|
INFO_VALUES = {
|
|
43
|
-
:CURLINFO_RESPONSE_CODE
|
|
44
|
-
:CURLINFO_TOTAL_TIME
|
|
45
|
-
:CURLINFO_HTTPAUTH_AVAIL
|
|
46
|
-
:CURLINFO_EFFECTIVE_URL
|
|
46
|
+
:CURLINFO_RESPONSE_CODE => 2097154,
|
|
47
|
+
:CURLINFO_TOTAL_TIME => 3145731,
|
|
48
|
+
:CURLINFO_HTTPAUTH_AVAIL => 0x200000 + 23,
|
|
49
|
+
:CURLINFO_EFFECTIVE_URL => 0x100000 + 1,
|
|
50
|
+
:CURLINFO_NAMELOOKUP_TIME => 0x300000 + 4,
|
|
51
|
+
:CURLINFO_CONNECT_TIME => 0x300000 + 5,
|
|
52
|
+
:CURLINFO_PRETRANSFER_TIME => 0x300000 + 6,
|
|
53
|
+
:CURLINFO_STARTTRANSFER_TIME => 0x300000 + 17,
|
|
54
|
+
:CURLINFO_APPCONNECT_TIME => 0x300000 + 33,
|
|
55
|
+
|
|
47
56
|
}
|
|
48
57
|
AUTH_TYPES = {
|
|
49
58
|
:CURLAUTH_BASIC => 1,
|
|
@@ -53,6 +62,14 @@ module Typhoeus
|
|
|
53
62
|
:CURLAUTH_DIGEST_IE => 16,
|
|
54
63
|
:CURLAUTH_AUTO => 16 | 8 | 4 | 2 | 1
|
|
55
64
|
}
|
|
65
|
+
PROXY_TYPES = {
|
|
66
|
+
:CURLPROXY_HTTP => 0,
|
|
67
|
+
:CURLPROXY_HTTP_1_0 => 1,
|
|
68
|
+
:CURLPROXY_SOCKS4 => 4,
|
|
69
|
+
:CURLPROXY_SOCKS5 => 5,
|
|
70
|
+
:CURLPROXY_SOCKS4A => 6,
|
|
71
|
+
}
|
|
72
|
+
|
|
56
73
|
|
|
57
74
|
def initialize
|
|
58
75
|
@method = :get
|
|
@@ -67,7 +84,13 @@ module Typhoeus
|
|
|
67
84
|
end
|
|
68
85
|
|
|
69
86
|
def proxy=(proxy)
|
|
70
|
-
set_option(OPTION_VALUES[:CURLOPT_PROXY], proxy)
|
|
87
|
+
set_option(OPTION_VALUES[:CURLOPT_PROXY], proxy[:server])
|
|
88
|
+
set_option(OPTION_VALUES[:CURLOPT_PROXYTYPE], proxy[:type]) if proxy[:type]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def proxy_auth=(authinfo)
|
|
92
|
+
set_option(OPTION_VALUES[:CURLOPT_PROXYUSERPWD], "#{authinfo[:username]}:#{authinfo[:password]}")
|
|
93
|
+
set_option(OPTION_VALUES[:CURLOPT_PROXYAUTH], authinfo[:method]) if authinfo[:method]
|
|
71
94
|
end
|
|
72
95
|
|
|
73
96
|
def auth=(authinfo)
|
|
@@ -87,6 +110,26 @@ module Typhoeus
|
|
|
87
110
|
get_info_double(INFO_VALUES[:CURLINFO_TOTAL_TIME])
|
|
88
111
|
end
|
|
89
112
|
|
|
113
|
+
def start_transfer_time
|
|
114
|
+
get_info_double(INFO_VALUES[:CURLINFO_STARTTRANSFER_TIME])
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def app_connect_time
|
|
118
|
+
get_info_double(INFO_VALUES[:CURLINFO_APPCONNECT_TIME])
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def pretransfer_time
|
|
122
|
+
get_info_double(INFO_VALUES[:CURLINFO_PRETRANSFER_TIME])
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def connect_time
|
|
126
|
+
get_info_double(INFO_VALUES[:CURLINFO_CONNECT_TIME])
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def name_lookup_time
|
|
130
|
+
get_info_double(INFO_VALUES[:CURLINFO_NAMELOOKUP_TIME])
|
|
131
|
+
end
|
|
132
|
+
|
|
90
133
|
def effective_url
|
|
91
134
|
get_info_string(INFO_VALUES[:CURLINFO_EFFECTIVE_URL])
|
|
92
135
|
end
|
|
@@ -106,7 +149,7 @@ module Typhoeus
|
|
|
106
149
|
def max_redirects=(redirects)
|
|
107
150
|
set_option(OPTION_VALUES[:CURLOPT_MAXREDIRS], redirects)
|
|
108
151
|
end
|
|
109
|
-
|
|
152
|
+
|
|
110
153
|
def connect_timeout=(milliseconds)
|
|
111
154
|
@connect_timeout = milliseconds
|
|
112
155
|
set_option(OPTION_VALUES[:CURLOPT_NOSIGNAL], 1)
|
|
@@ -120,7 +163,7 @@ module Typhoeus
|
|
|
120
163
|
end
|
|
121
164
|
|
|
122
165
|
def timed_out?
|
|
123
|
-
|
|
166
|
+
curl_return_code == 28
|
|
124
167
|
end
|
|
125
168
|
|
|
126
169
|
def supports_zlib?
|
|
@@ -174,24 +217,22 @@ module Typhoeus
|
|
|
174
217
|
set_option(OPTION_VALUES[:CURLOPT_COPYPOSTFIELDS], data)
|
|
175
218
|
end
|
|
176
219
|
|
|
220
|
+
def params
|
|
221
|
+
@form.nil? ? {} : @form.params
|
|
222
|
+
end
|
|
223
|
+
|
|
177
224
|
def params=(params)
|
|
178
|
-
@
|
|
179
|
-
params_string = params.keys.collect do |k|
|
|
180
|
-
value = params[k]
|
|
181
|
-
if value.is_a? Hash
|
|
182
|
-
value.keys.collect {|sk| Typhoeus::Utils.escape("#{k}[#{sk}]") + "=" + Typhoeus::Utils.escape(value[sk].to_s)}
|
|
183
|
-
elsif value.is_a? Array
|
|
184
|
-
key = Typhoeus::Utils.escape(k.to_s)
|
|
185
|
-
value.collect { |v| "#{key}=#{Typhoeus::Utils.escape(v.to_s)}" }.join('&')
|
|
186
|
-
else
|
|
187
|
-
"#{Typhoeus::Utils.escape(k.to_s)}=#{Typhoeus::Utils.escape(params[k].to_s)}"
|
|
188
|
-
end
|
|
189
|
-
end.flatten.join("&")
|
|
225
|
+
@form = Typhoeus::Form.new(params)
|
|
190
226
|
|
|
191
227
|
if method == :post
|
|
192
|
-
|
|
228
|
+
@form.process!
|
|
229
|
+
if @form.multipart?
|
|
230
|
+
set_option(OPTION_VALUES[:CURLOPT_HTTPPOST], @form)
|
|
231
|
+
else
|
|
232
|
+
self.post_data = @form.to_s
|
|
233
|
+
end
|
|
193
234
|
else
|
|
194
|
-
self.url = "#{url}?#{
|
|
235
|
+
self.url = "#{url}?#{@form.to_s}"
|
|
195
236
|
end
|
|
196
237
|
end
|
|
197
238
|
|
|
@@ -205,7 +246,7 @@ module Typhoeus
|
|
|
205
246
|
# Set SSL certificate type
|
|
206
247
|
# " The string should be the format of your certificate. Supported formats are "PEM" and "DER" "
|
|
207
248
|
def ssl_cert_type=(cert_type)
|
|
208
|
-
raise "Invalid ssl cert type : '#{cert_type}'..." if cert_type and !%w(PEM DER).include?(cert_type)
|
|
249
|
+
raise "Invalid ssl cert type : '#{cert_type}'..." if cert_type and !%w(PEM DER).include?(cert_type)
|
|
209
250
|
set_option(OPTION_VALUES[:CURLOPT_SSLCERTTYPE], cert_type)
|
|
210
251
|
end
|
|
211
252
|
|
|
@@ -244,17 +285,20 @@ module Typhoeus
|
|
|
244
285
|
end
|
|
245
286
|
|
|
246
287
|
def set_option(option, value)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
288
|
+
case value
|
|
289
|
+
when String
|
|
290
|
+
easy_setopt_string(option, value)
|
|
291
|
+
when Typhoeus::Form
|
|
292
|
+
easy_setopt_form(option, value)
|
|
293
|
+
else
|
|
294
|
+
easy_setopt_long(option, value) if value
|
|
251
295
|
end
|
|
252
296
|
end
|
|
253
297
|
|
|
254
298
|
def perform
|
|
255
299
|
set_headers()
|
|
256
300
|
easy_perform()
|
|
257
|
-
resp_code = response_code()
|
|
301
|
+
resp_code = response_code()
|
|
258
302
|
if resp_code >= 200 && resp_code <= 299
|
|
259
303
|
success
|
|
260
304
|
else
|
|
@@ -283,7 +327,7 @@ module Typhoeus
|
|
|
283
327
|
@success = block
|
|
284
328
|
end
|
|
285
329
|
|
|
286
|
-
# gets called when finished and response code is 300-599
|
|
330
|
+
# gets called when finished and response code is 300-599 or curl returns an error code
|
|
287
331
|
def failure
|
|
288
332
|
@failure.call(self) if @failure
|
|
289
333
|
end
|
|
@@ -296,25 +340,7 @@ module Typhoeus
|
|
|
296
340
|
@failure = block
|
|
297
341
|
end
|
|
298
342
|
|
|
299
|
-
def retries
|
|
300
|
-
@retries ||= 0
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def increment_retries
|
|
304
|
-
@retries ||= 0
|
|
305
|
-
@retries += 1
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
def max_retries
|
|
309
|
-
@max_retries ||= 40
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
def max_retries?
|
|
313
|
-
retries >= max_retries
|
|
314
|
-
end
|
|
315
|
-
|
|
316
343
|
def reset
|
|
317
|
-
@retries = 0
|
|
318
344
|
@response_code = 0
|
|
319
345
|
@response_header = ""
|
|
320
346
|
@response_body = ""
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'mime/types'
|
|
2
|
+
|
|
3
|
+
module Typhoeus
|
|
4
|
+
class Form
|
|
5
|
+
attr_accessor :params
|
|
6
|
+
attr_reader :traversal
|
|
7
|
+
|
|
8
|
+
def initialize(params = {})
|
|
9
|
+
@params = params
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def traversal
|
|
13
|
+
@traversal ||= Typhoeus::Utils.traverse_params_hash(params)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def process!
|
|
17
|
+
# add params
|
|
18
|
+
traversal[:params].each { |p| formadd_param(p[0], p[1]) }
|
|
19
|
+
|
|
20
|
+
# add files
|
|
21
|
+
traversal[:files].each { |file_args| formadd_file(*file_args) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def multipart?
|
|
25
|
+
!traversal[:files].empty?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_s
|
|
29
|
+
Typhoeus::Utils.traversal_to_param_string(traversal, false)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -12,9 +12,10 @@ module Typhoeus
|
|
|
12
12
|
#
|
|
13
13
|
# @raises NetConnectNotAllowedError
|
|
14
14
|
def check_allow_net_connect!(request)
|
|
15
|
-
if
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
return if Typhoeus::Hydra.allow_net_connect?
|
|
16
|
+
return if Typhoeus::Hydra.ignore_hosts.include?(request.host_domain)
|
|
17
|
+
|
|
18
|
+
raise NetConnectNotAllowedError, "Real HTTP requests are not allowed. Unregistered request: #{request.inspect}"
|
|
18
19
|
end
|
|
19
20
|
private :check_allow_net_connect!
|
|
20
21
|
|
|
@@ -39,7 +40,22 @@ module Typhoeus
|
|
|
39
40
|
def ignore_localhost?
|
|
40
41
|
ignore_localhost
|
|
41
42
|
end
|
|
43
|
+
|
|
44
|
+
def ignore_hosts
|
|
45
|
+
@ignore_hosts ||= []
|
|
46
|
+
|
|
47
|
+
if ignore_localhost?
|
|
48
|
+
@ignore_hosts + Typhoeus::Request::LOCALHOST_ALIASES
|
|
49
|
+
else
|
|
50
|
+
@ignore_hosts
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def ignore_hosts=(hosts)
|
|
55
|
+
@ignore_hosts = hosts
|
|
56
|
+
end
|
|
42
57
|
end
|
|
43
58
|
end
|
|
44
59
|
end
|
|
45
60
|
end
|
|
61
|
+
|
data/lib/typhoeus/hydra.rb
CHANGED
|
@@ -32,6 +32,17 @@ module Typhoeus
|
|
|
32
32
|
@hydra = val
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
#
|
|
36
|
+
# Abort the run on a best-effort basis.
|
|
37
|
+
#
|
|
38
|
+
# It won't abort the current burst of @max_concurrency requests,
|
|
39
|
+
# however it won't fire the rest of the queued requests so the run
|
|
40
|
+
# will be aborted as soon as possible...
|
|
41
|
+
#
|
|
42
|
+
def abort
|
|
43
|
+
@queued_requests.clear
|
|
44
|
+
end
|
|
45
|
+
|
|
35
46
|
def clear_cache_callbacks
|
|
36
47
|
@cache_setter = nil
|
|
37
48
|
@cache_getter = nil
|
|
@@ -82,8 +93,11 @@ module Typhoeus
|
|
|
82
93
|
end
|
|
83
94
|
|
|
84
95
|
@multi.perform
|
|
96
|
+
ensure
|
|
97
|
+
@multi.reset_easy_handles{|easy| release_easy_object(easy)}
|
|
85
98
|
@memoized_requests = {}
|
|
86
99
|
@retrieved_from_cache = {}
|
|
100
|
+
@running_requests = 0
|
|
87
101
|
end
|
|
88
102
|
|
|
89
103
|
def disable_memoization
|
|
@@ -131,6 +145,19 @@ module Typhoeus
|
|
|
131
145
|
auth[:method] = Typhoeus::Easy::AUTH_TYPES["CURLAUTH_#{request.auth_method.to_s.upcase}".to_sym] if request.auth_method
|
|
132
146
|
easy.auth = auth
|
|
133
147
|
end
|
|
148
|
+
|
|
149
|
+
if request.proxy
|
|
150
|
+
proxy = { :server => request.proxy }
|
|
151
|
+
proxy[:type] = Typhoeus::Easy::PROXY_TYPES["CURLPROXY_#{request.proxy_type.to_s.upcase}".to_sym] if request.proxy_type
|
|
152
|
+
easy.proxy = proxy if request.proxy
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
if request.proxy_username || request.proxy_password
|
|
156
|
+
auth = { :username => request.proxy_username, :password => request.proxy_password }
|
|
157
|
+
auth[:method] = Typhoeus::Easy::AUTH_TYPES["CURLAUTH_#{request.proxy_auth_method.to_s.upcase}".to_sym] if request.proxy_auth_method
|
|
158
|
+
easy.proxy_auth = auth
|
|
159
|
+
end
|
|
160
|
+
|
|
134
161
|
easy.url = request.url
|
|
135
162
|
easy.method = request.method
|
|
136
163
|
easy.params = request.params if request.method == :post && !request.params.nil?
|
|
@@ -140,7 +167,6 @@ module Typhoeus
|
|
|
140
167
|
easy.connect_timeout = request.connect_timeout if request.connect_timeout
|
|
141
168
|
easy.follow_location = request.follow_location if request.follow_location
|
|
142
169
|
easy.max_redirects = request.max_redirects if request.max_redirects
|
|
143
|
-
easy.proxy = request.proxy if request.proxy
|
|
144
170
|
easy.disable_ssl_peer_verification if request.disable_ssl_peer_verification
|
|
145
171
|
easy.ssl_cert = request.ssl_cert
|
|
146
172
|
easy.ssl_cert_type = request.ssl_cert_type
|
|
@@ -200,12 +226,19 @@ module Typhoeus
|
|
|
200
226
|
private :handle_request
|
|
201
227
|
|
|
202
228
|
def response_from_easy(easy, request)
|
|
203
|
-
Response.new(:code
|
|
204
|
-
:headers
|
|
205
|
-
:body
|
|
206
|
-
:time
|
|
207
|
-
:
|
|
208
|
-
:
|
|
229
|
+
Response.new(:code => easy.response_code,
|
|
230
|
+
:headers => easy.response_header,
|
|
231
|
+
:body => easy.response_body,
|
|
232
|
+
:time => easy.total_time_taken,
|
|
233
|
+
:start_transfer_time => easy.start_transfer_time,
|
|
234
|
+
:app_connect_time => easy.app_connect_time,
|
|
235
|
+
:pretransfer_time => easy.pretransfer_time,
|
|
236
|
+
:connect_time => easy.connect_time,
|
|
237
|
+
:name_lookup_time => easy.name_lookup_time,
|
|
238
|
+
:effective_url => easy.effective_url,
|
|
239
|
+
:curl_return_code => easy.curl_return_code,
|
|
240
|
+
:curl_error_message => easy.curl_error_message,
|
|
241
|
+
:request => request)
|
|
209
242
|
end
|
|
210
243
|
private :response_from_easy
|
|
211
244
|
end
|
data/lib/typhoeus/multi.rb
CHANGED
|
@@ -3,16 +3,16 @@ module Typhoeus
|
|
|
3
3
|
attr_reader :easy_handles
|
|
4
4
|
|
|
5
5
|
def initialize
|
|
6
|
-
|
|
6
|
+
@easy_handles = []
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def remove(easy)
|
|
10
|
-
multi_remove_handle(easy)
|
|
10
|
+
multi_remove_handle(easy) if @easy_handles.include?(easy)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def add(easy)
|
|
14
|
+
raise "trying to add easy handle twice" if @easy_handles.include?(easy)
|
|
14
15
|
easy.set_headers() if easy.headers.empty?
|
|
15
|
-
@easy_handles << easy
|
|
16
16
|
multi_add_handle(easy)
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -27,9 +27,11 @@ module Typhoeus
|
|
|
27
27
|
multi_cleanup
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
private
|
|
31
30
|
def reset_easy_handles
|
|
32
|
-
@easy_handles
|
|
31
|
+
@easy_handles.dup.each do |easy|
|
|
32
|
+
multi_remove_handle(easy)
|
|
33
|
+
yield easy if block_given?
|
|
34
|
+
end
|
|
33
35
|
end
|
|
34
36
|
end
|
|
35
37
|
end
|
data/lib/typhoeus/remote.rb
CHANGED
|
@@ -22,6 +22,8 @@ module Typhoeus
|
|
|
22
22
|
unless @proxied_object
|
|
23
23
|
Typhoeus.perform_easy_requests
|
|
24
24
|
response = Response.new(:code => @easy.response_code,
|
|
25
|
+
:curl_return_code => @easy.curl_return_code,
|
|
26
|
+
:curl_error_message => @easy.curl_error_message,
|
|
25
27
|
:headers => @easy.response_header,
|
|
26
28
|
:body => @easy.response_body,
|
|
27
29
|
:time => @easy.total_time_taken,
|
data/lib/typhoeus/request.rb
CHANGED
|
@@ -6,10 +6,12 @@ module Typhoeus
|
|
|
6
6
|
attr_writer :headers
|
|
7
7
|
attr_accessor :method, :params, :body, :connect_timeout, :timeout,
|
|
8
8
|
:user_agent, :response, :cache_timeout, :follow_location,
|
|
9
|
-
:max_redirects, :proxy, :
|
|
9
|
+
:max_redirects, :proxy, :proxy_username,:proxy_password,
|
|
10
|
+
:disable_ssl_peer_verification,
|
|
10
11
|
:ssl_cert, :ssl_cert_type, :ssl_key, :ssl_key_type,
|
|
11
12
|
:ssl_key_password, :ssl_cacert, :ssl_capath, :verbose,
|
|
12
|
-
:username, :password, :auth_method, :user_agent
|
|
13
|
+
:username, :password, :auth_method, :user_agent,
|
|
14
|
+
:proxy_auth_method, :proxy_type
|
|
13
15
|
|
|
14
16
|
# Initialize a new Request
|
|
15
17
|
#
|
|
@@ -52,6 +54,10 @@ module Typhoeus
|
|
|
52
54
|
@follow_location = options[:follow_location]
|
|
53
55
|
@max_redirects = options[:max_redirects]
|
|
54
56
|
@proxy = options[:proxy]
|
|
57
|
+
@proxy_type = options[:proxy_type]
|
|
58
|
+
@proxy_username = options[:proxy_username]
|
|
59
|
+
@proxy_password = options[:proxy_password]
|
|
60
|
+
@proxy_auth_method = options[:proxy_auth_method]
|
|
55
61
|
@disable_ssl_peer_verification = options[:disable_ssl_peer_verification]
|
|
56
62
|
@ssl_cert = options[:ssl_cert]
|
|
57
63
|
@ssl_cert_type = options[:ssl_cert_type]
|
|
@@ -78,8 +84,10 @@ module Typhoeus
|
|
|
78
84
|
@handled_response = nil
|
|
79
85
|
end
|
|
80
86
|
|
|
87
|
+
LOCALHOST_ALIASES = %w[ localhost 127.0.0.1 0.0.0.0 ]
|
|
88
|
+
|
|
81
89
|
def localhost?
|
|
82
|
-
|
|
90
|
+
LOCALHOST_ALIASES.include?(@parsed_uri.host)
|
|
83
91
|
end
|
|
84
92
|
|
|
85
93
|
def host
|
|
@@ -92,23 +100,18 @@ module Typhoeus
|
|
|
92
100
|
end
|
|
93
101
|
end
|
|
94
102
|
|
|
103
|
+
def host_domain
|
|
104
|
+
@parsed_uri.host
|
|
105
|
+
end
|
|
106
|
+
|
|
95
107
|
def headers
|
|
96
108
|
@headers["User-Agent"] = @user_agent
|
|
97
109
|
@headers
|
|
98
110
|
end
|
|
99
111
|
|
|
100
112
|
def params_string
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if value.is_a? Hash
|
|
104
|
-
value.keys.collect {|sk| Typhoeus::Utils.escape("#{k}[#{sk}]") + "=" + Typhoeus::Utils.escape(value[sk].to_s)}
|
|
105
|
-
elsif value.is_a? Array
|
|
106
|
-
key = Typhoeus::Utils.escape(k.to_s)
|
|
107
|
-
value.collect { |v| "#{key}[]=#{Typhoeus::Utils.escape(v.to_s)}" }.join('&')
|
|
108
|
-
else
|
|
109
|
-
"#{Typhoeus::Utils.escape(k.to_s)}=#{Typhoeus::Utils.escape(params[k].to_s)}"
|
|
110
|
-
end
|
|
111
|
-
end.flatten.join("&")
|
|
113
|
+
traversal = Typhoeus::Utils.traverse_params_hash(params)
|
|
114
|
+
Typhoeus::Utils.traversal_to_param_string(traversal)
|
|
112
115
|
end
|
|
113
116
|
|
|
114
117
|
def on_complete(&block)
|
data/lib/typhoeus/response.rb
CHANGED
|
@@ -4,11 +4,17 @@ module Typhoeus
|
|
|
4
4
|
attr_reader :code, :headers, :body, :time,
|
|
5
5
|
:requested_url, :requested_remote_method,
|
|
6
6
|
:requested_http_method, :start_time,
|
|
7
|
-
:effective_url
|
|
7
|
+
:effective_url, :start_transfer_time,
|
|
8
|
+
:app_connect_time, :pretransfer_time,
|
|
9
|
+
:connect_time, :name_lookup_time,
|
|
10
|
+
:curl_return_code, :curl_error_message
|
|
11
|
+
|
|
8
12
|
attr_writer :headers_hash
|
|
9
13
|
|
|
10
14
|
def initialize(params = {})
|
|
11
15
|
@code = params[:code]
|
|
16
|
+
@curl_return_code = params[:curl_return_code]
|
|
17
|
+
@curl_error_message = params[:curl_error_message]
|
|
12
18
|
@status_message = params[:status_message]
|
|
13
19
|
@http_version = params[:http_version]
|
|
14
20
|
@headers = params[:headers] || ''
|
|
@@ -17,6 +23,11 @@ module Typhoeus
|
|
|
17
23
|
@requested_url = params[:requested_url]
|
|
18
24
|
@requested_http_method = params[:requested_http_method]
|
|
19
25
|
@start_time = params[:start_time]
|
|
26
|
+
@start_transfer_time = params[:start_transfer_time]
|
|
27
|
+
@app_connect_time = params[:app_connect_time]
|
|
28
|
+
@pretransfer_time = params[:pretransfer_time]
|
|
29
|
+
@connect_time = params[:connect_time]
|
|
30
|
+
@name_lookup_time = params[:name_lookup_time]
|
|
20
31
|
@request = params[:request]
|
|
21
32
|
@effective_url = params[:effective_url]
|
|
22
33
|
@mock = params[:mock] || false # default
|
|
@@ -67,6 +78,10 @@ module Typhoeus
|
|
|
67
78
|
@code != 304
|
|
68
79
|
end
|
|
69
80
|
|
|
81
|
+
def timed_out?
|
|
82
|
+
curl_return_code == 28
|
|
83
|
+
end
|
|
84
|
+
|
|
70
85
|
private
|
|
71
86
|
|
|
72
87
|
def first_header_line
|
data/lib/typhoeus/utils.rb
CHANGED
|
@@ -8,6 +8,44 @@ module Typhoeus
|
|
|
8
8
|
end
|
|
9
9
|
module_function :escape
|
|
10
10
|
|
|
11
|
+
# Params are NOT escaped.
|
|
12
|
+
def traverse_params_hash(hash, result = nil, current_key = nil)
|
|
13
|
+
result ||= { :files => [], :params => [] }
|
|
14
|
+
|
|
15
|
+
hash.keys.sort { |a, b| a.to_s <=> b.to_s }.collect do |key|
|
|
16
|
+
new_key = (current_key ? "#{current_key}[#{key}]" : key).to_s
|
|
17
|
+
case hash[key]
|
|
18
|
+
when Hash
|
|
19
|
+
traverse_params_hash(hash[key], result, new_key)
|
|
20
|
+
when Array
|
|
21
|
+
array_key = "#{new_key}[]"
|
|
22
|
+
hash[key].each do |v|
|
|
23
|
+
result[:params] << [array_key, v.to_s]
|
|
24
|
+
end
|
|
25
|
+
when File
|
|
26
|
+
filename = File.basename(hash[key].path)
|
|
27
|
+
types = MIME::Types.type_for(filename)
|
|
28
|
+
result[:files] << [
|
|
29
|
+
new_key,
|
|
30
|
+
filename,
|
|
31
|
+
types.empty? ? 'application/octet-stream' : types[0].to_s,
|
|
32
|
+
File.expand_path(hash[key].path)
|
|
33
|
+
]
|
|
34
|
+
else
|
|
35
|
+
result[:params] << [new_key, hash[key].to_s]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
result
|
|
39
|
+
end
|
|
40
|
+
module_function :traverse_params_hash
|
|
41
|
+
|
|
42
|
+
def traversal_to_param_string(traversal, escape = true)
|
|
43
|
+
traversal[:params].collect { |param|
|
|
44
|
+
"#{Typhoeus::Utils.escape(param[0])}=#{Typhoeus::Utils.escape(param[1])}"
|
|
45
|
+
}.join('&')
|
|
46
|
+
end
|
|
47
|
+
module_function :traversal_to_param_string
|
|
48
|
+
|
|
11
49
|
# Return the bytesize of String; uses String#size under Ruby 1.8 and
|
|
12
50
|
# String#bytesize under 1.9.
|
|
13
51
|
if ''.respond_to?(:bytesize)
|
data/lib/typhoeus.rb
CHANGED
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This file is used to test uploading.
|
|
File without changes
|
data/spec/servers/app.rb
CHANGED
|
@@ -5,6 +5,16 @@ require 'json'
|
|
|
5
5
|
require 'zlib'
|
|
6
6
|
|
|
7
7
|
@@fail_count = 0
|
|
8
|
+
|
|
9
|
+
post '/file' do
|
|
10
|
+
{
|
|
11
|
+
'content-type' => params[:file][:type],
|
|
12
|
+
'filename' => params[:file][:filename],
|
|
13
|
+
'content' => params[:file][:tempfile].read,
|
|
14
|
+
'request-content-type' => request.env['CONTENT_TYPE']
|
|
15
|
+
}.to_json
|
|
16
|
+
end
|
|
17
|
+
|
|
8
18
|
get '/fail/:number' do
|
|
9
19
|
if @@fail_count >= params[:number].to_i
|
|
10
20
|
"ok"
|
data/spec/spec.opts
CHANGED