dcu-typhoeus 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,453 @@
1
+ require 'ffi'
2
+ require 'rbconfig'
3
+ require 'thread'
4
+
5
+ module Typhoeus
6
+ module Curl
7
+ # this does not implement the full curl lib. just what is needed for typhoeus
8
+
9
+ def Curl.windows?
10
+ !(RbConfig::CONFIG['host_os'] !~ /mingw|mswin|bccwin/)
11
+ end
12
+
13
+ extend ::FFI::Library
14
+
15
+ VERSION_NOW = 3
16
+
17
+ GLOBAL_SSL = 0x01
18
+ GLOBAL_WIN32 = 0x02
19
+ GLOBAL_ALL = (GLOBAL_SSL | GLOBAL_WIN32)
20
+ GLOBAL_DEFAULT = GLOBAL_ALL
21
+
22
+ EasyCode = enum :easy_code, [
23
+ :ok,
24
+ :unsupported_protocol,
25
+ :failed_init,
26
+ :url_malformat,
27
+ :not_built_in,
28
+ :couldnt_resolve_proxy,
29
+ :couldnt_resolve_host,
30
+ :couldnt_connect,
31
+ :ftp_weird_server_reply,
32
+ :remote_access_denied,
33
+ :ftp_accept_failed,
34
+ :ftp_weird_pass_reply,
35
+ :ftp_accept_timeout,
36
+ :ftp_weird_pasv_reply,
37
+ :ftp_weird_227_format,
38
+ :ftp_cant_get_host,
39
+ :obsolete16,
40
+ :ftp_couldnt_set_type,
41
+ :partial_file,
42
+ :ftp_couldnt_retr_file,
43
+ :obsolete20,
44
+ :quote_error,
45
+ :http_returned_error,
46
+ :write_error,
47
+ :obsolete24,
48
+ :upload_failed,
49
+ :read_error,
50
+ :out_of_memory,
51
+ :operation_timedout,
52
+ :obsolete29,
53
+ :ftp_port_failed,
54
+ :ftp_couldnt_use_rest,
55
+ :obsolete32,
56
+ :range_error,
57
+ :http_post_error,
58
+ :ssl_connect_error,
59
+ :bad_download_resume,
60
+ :file_couldnt_read_file,
61
+ :ldap_cannot_bind,
62
+ :ldap_search_failed,
63
+ :obsolete40,
64
+ :function_not_found,
65
+ :aborted_by_callback,
66
+ :bad_function_argument,
67
+ :obsolete44,
68
+ :interface_failed,
69
+ :obsolete46,
70
+ :too_many_redirects ,
71
+ :unknown_option,
72
+ :telnet_option_syntax ,
73
+ :obsolete50,
74
+ :peer_failed_verification,
75
+ :got_nothing,
76
+ :ssl_engine_notfound,
77
+ :ssl_engine_setfailed,
78
+ :send_error,
79
+ :recv_error,
80
+ :obsolete57,
81
+ :ssl_certproblem,
82
+ :ssl_cipher,
83
+ :ssl_cacert,
84
+ :bad_content_encoding,
85
+ :ldap_invalid_url,
86
+ :filesize_exceeded,
87
+ :use_ssl_failed,
88
+ :send_fail_rewind,
89
+ :ssl_engine_initfailed,
90
+ :login_denied,
91
+ :tftp_notfound,
92
+ :tftp_perm,
93
+ :remote_disk_full,
94
+ :tftp_illegal,
95
+ :tftp_unknownid,
96
+ :remote_file_exists,
97
+ :tftp_nosuchuser,
98
+ :conv_failed,
99
+ :conv_reqd,
100
+ :ssl_cacert_badfile,
101
+ :remote_file_not_found,
102
+ :ssh,
103
+ :ssl_shutdown_failed,
104
+ :again,
105
+ :ssl_crl_badfile,
106
+ :ssl_issuer_error,
107
+ :ftp_pret_failed,
108
+ :rtsp_cseq_error,
109
+ :rtsp_session_error,
110
+ :ftp_bad_file_list,
111
+ :chunk_failed,
112
+ :last]
113
+
114
+ MultiCode = enum :multi_code, [
115
+ :call_multi_perform, -1,
116
+ :ok,
117
+ :bad_handle,
118
+ :bad_easy_handle,
119
+ :out_of_memory,
120
+ :internal_error,
121
+ :bad_socket,
122
+ :unknown_option,
123
+ :last]
124
+
125
+ OptionType = enum [
126
+ :long, 0,
127
+ :object_point, 10000,
128
+ :function_point, 20000,
129
+ :off_t, 30000]
130
+
131
+ Option = enum :option, [
132
+ :file, OptionType[:object_point] + 1,
133
+ :writedata, OptionType[:object_point] + 1,
134
+ :url, OptionType[:object_point] + 2,
135
+ :port, OptionType[:long] + 3,
136
+ :proxy, OptionType[:object_point] + 4,
137
+ :userpwd, OptionType[:object_point] + 5,
138
+ :proxyuserpwd, OptionType[:object_point] + 6,
139
+ :range, OptionType[:object_point] + 7,
140
+ :infile, OptionType[:object_point] + 9,
141
+ :readdata, OptionType[:object_point] + 9,
142
+ :errorbuffer, OptionType[:object_point] + 10,
143
+ :writefunction, OptionType[:function_point] + 11,
144
+ :readfunction, OptionType[:function_point] + 12,
145
+ :timeout, OptionType[:long] + 13,
146
+ :infilesize, OptionType[:long] + 14,
147
+ :postfields, OptionType[:object_point] + 15,
148
+ :referer, OptionType[:object_point] + 16,
149
+ :ftpport, OptionType[:object_point] + 17,
150
+ :useragent, OptionType[:object_point] + 18,
151
+ :low_speed_time, OptionType[:long] + 20,
152
+ :resume_from, OptionType[:long] + 21,
153
+ :cookie, OptionType[:object_point] + 22,
154
+ :httpheader, OptionType[:object_point] + 23,
155
+ :httppost, OptionType[:object_point] + 24,
156
+ :sslcert, OptionType[:object_point] + 25,
157
+ :sslcertpasswd, OptionType[:object_point] + 26,
158
+ :sslkeypasswd, OptionType[:object_point] + 26,
159
+ :crlf, OptionType[:long] + 27,
160
+ :quote, OptionType[:object_point] + 28,
161
+ :writeheader, OptionType[:object_point] + 29,
162
+ :headerdata, OptionType[:object_point] + 29,
163
+ :cookiefile, OptionType[:object_point] + 31,
164
+ :sslversion, OptionType[:long] + 32,
165
+ :timecondition, OptionType[:long] + 33,
166
+ :timevalue, OptionType[:long] + 34,
167
+ :customrequest, OptionType[:object_point] + 36,
168
+ :stderr, OptionType[:object_point] + 37,
169
+ :postquote, OptionType[:object_point] + 39,
170
+ :writeinfo, OptionType[:object_point] + 40,
171
+ :verbose, OptionType[:long] + 41,
172
+ :header, OptionType[:long] + 42,
173
+ :noprogress, OptionType[:long] + 43,
174
+ :nobody, OptionType[:long] + 44,
175
+ :failonerror, OptionType[:long] + 45,
176
+ :upload, OptionType[:long] + 46,
177
+ :post, OptionType[:long] + 47,
178
+ :ftplistonly, OptionType[:long] + 48,
179
+ :ftpappend, OptionType[:long] + 50,
180
+ :netrc, OptionType[:long] + 51,
181
+ :followlocation, OptionType[:long] + 52,
182
+ :transfertext, OptionType[:long] + 53,
183
+ :put, OptionType[:long] + 54,
184
+ :progressfunction, OptionType[:function_point] + 56,
185
+ :progressdata, OptionType[:object_point] + 57,
186
+ :autoreferer, OptionType[:long] + 58,
187
+ :proxyport, OptionType[:long] + 59,
188
+ :postfieldsize, OptionType[:long] + 60,
189
+ :httpproxytunnel, OptionType[:long] + 61,
190
+ :interface, OptionType[:object_point] + 62,
191
+ :ssl_verifypeer, OptionType[:long] + 64,
192
+ :cainfo, OptionType[:object_point] + 65,
193
+ :maxredirs, OptionType[:long] + 68,
194
+ :filetime, OptionType[:long] + 69,
195
+ :telnetoptions, OptionType[:object_point] + 70,
196
+ :maxconnects, OptionType[:long] + 71,
197
+ :closepolicy, OptionType[:long] + 72,
198
+ :fresh_connect, OptionType[:long] + 74,
199
+ :forbid_reuse, OptionType[:long] + 75,
200
+ :random_file, OptionType[:object_point] + 76,
201
+ :egdsocket, OptionType[:object_point] + 77,
202
+ :connecttimeout, OptionType[:long] + 78,
203
+ :headerfunction, OptionType[:function_point] + 79,
204
+ :httpget, OptionType[:long] + 80,
205
+ :ssl_verifyhost, OptionType[:long] + 81,
206
+ :cookiejar, OptionType[:object_point] + 82,
207
+ :ssl_cipher_list, OptionType[:object_point] + 83,
208
+ :http_version, OptionType[:long] + 84,
209
+ :ftp_use_epsv, OptionType[:long] + 85,
210
+ :sslcerttype, OptionType[:object_point] + 86,
211
+ :sslkey, OptionType[:object_point] + 87,
212
+ :sslkeytype, OptionType[:object_point] + 88,
213
+ :sslengine, OptionType[:object_point] + 89,
214
+ :sslengine_default, OptionType[:long] + 90,
215
+ :dns_use_global_cache, OptionType[:long] + 91,
216
+ :dns_cache_timeout, OptionType[:long] + 92,
217
+ :prequote, OptionType[:object_point] + 93,
218
+ :debugfunction, OptionType[:function_point] + 94,
219
+ :debugdata, OptionType[:object_point] + 95,
220
+ :cookiesession, OptionType[:long] + 96,
221
+ :capath, OptionType[:object_point] + 97,
222
+ :buffersize, OptionType[:long] + 98,
223
+ :nosignal, OptionType[:long] + 99,
224
+ :share, OptionType[:object_point] + 100,
225
+ :proxytype, OptionType[:long] + 101,
226
+ :encoding, OptionType[:object_point] + 102,
227
+ :private, OptionType[:object_point] + 103,
228
+ :unrestricted_auth, OptionType[:long] + 105,
229
+ :ftp_use_eprt, OptionType[:long] + 106,
230
+ :httpauth, OptionType[:long] + 107,
231
+ :ssl_ctx_function, OptionType[:function_point] + 108,
232
+ :ssl_ctx_data, OptionType[:object_point] + 109,
233
+ :ftp_create_missing_dirs, OptionType[:long] + 110,
234
+ :proxyauth, OptionType[:long] + 111,
235
+ :ipresolve, OptionType[:long] + 113,
236
+ :maxfilesize, OptionType[:long] + 114,
237
+ :infilesize_large, OptionType[:off_t] + 115,
238
+ :resume_from_large, OptionType[:off_t] + 116,
239
+ :maxfilesize_large, OptionType[:off_t] + 117,
240
+ :netrc_file, OptionType[:object_point] + 118,
241
+ :ftp_ssl, OptionType[:long] + 119,
242
+ :postfieldsize_large, OptionType[:off_t] + 120,
243
+ :tcp_nodelay, OptionType[:long] + 121,
244
+ :ftpsslauth, OptionType[:long] + 129,
245
+ :ioctlfunction, OptionType[:function_point] + 130,
246
+ :ioctldata, OptionType[:object_point] + 131,
247
+ :ftp_account, OptionType[:object_point] + 134,
248
+ :cookielist, OptionType[:object_point] + 135,
249
+ :ignore_content_length, OptionType[:long] + 136,
250
+ :ftp_skip_pasv_ip, OptionType[:long] + 137,
251
+ :ftp_filemethod, OptionType[:long] + 138,
252
+ :localport, OptionType[:long] + 139,
253
+ :localportrange, OptionType[:long] + 140,
254
+ :connect_only, OptionType[:long] + 141,
255
+ :conv_from_network_function, OptionType[:function_point] + 142,
256
+ :conv_to_network_function, OptionType[:function_point] + 143,
257
+ :max_send_speed_large, OptionType[:off_t] + 145,
258
+ :max_recv_speed_large, OptionType[:off_t] + 146,
259
+ :ftp_alternative_to_user, OptionType[:object_point] + 147,
260
+ :sockoptfunction, OptionType[:function_point] + 148,
261
+ :sockoptdata, OptionType[:object_point] + 149,
262
+ :ssl_sessionid_cache, OptionType[:long] + 150,
263
+ :ssh_auth_types, OptionType[:long] + 151,
264
+ :ssh_public_keyfile, OptionType[:object_point] + 152,
265
+ :ssh_private_keyfile, OptionType[:object_point] + 153,
266
+ :ftp_ssl_ccc, OptionType[:long] + 154,
267
+ :timeout_ms, OptionType[:long] + 155,
268
+ :connecttimeout_ms, OptionType[:long] + 156,
269
+ :http_transfer_decoding, OptionType[:long] + 157,
270
+ :http_content_decoding, OptionType[:long] + 158,
271
+ :copypostfields, OptionType[:object_point] + 165]
272
+
273
+ InfoType = enum [
274
+ :string, 0x100000,
275
+ :long, 0x200000,
276
+ :double, 0x300000,
277
+ :slist, 0x400000]
278
+
279
+ Info = enum :info, [
280
+ :effective_url, InfoType[:string] + 1,
281
+ :response_code, InfoType[:long] + 2,
282
+ :total_time, InfoType[:double] + 3,
283
+ :namelookup_time, InfoType[:double] + 4,
284
+ :connect_time, InfoType[:double] + 5,
285
+ :pretransfer_time, InfoType[:double] + 6,
286
+ :size_upload, InfoType[:double] + 7,
287
+ :size_download, InfoType[:double] + 8,
288
+ :speed_download, InfoType[:double] + 9,
289
+ :speed_upload, InfoType[:double] + 10,
290
+ :header_size, InfoType[:long] + 11,
291
+ :request_size, InfoType[:long] + 12,
292
+ :ssl_verifyresult, InfoType[:long] + 13,
293
+ :filetime, InfoType[:long] + 14,
294
+ :content_length_download, InfoType[:double] + 15,
295
+ :content_length_upload, InfoType[:double] + 16,
296
+ :starttransfer_time, InfoType[:double] + 17,
297
+ :content_type, InfoType[:string] + 18,
298
+ :redirect_time, InfoType[:double] + 19,
299
+ :redirect_count, InfoType[:long] + 20,
300
+ :private, InfoType[:string] + 21,
301
+ :http_connectcode, InfoType[:long] + 22,
302
+ :httpauth_avail, InfoType[:long] + 23,
303
+ :proxyauth_avail, InfoType[:long] + 24,
304
+ :os_errno, InfoType[:long] + 25,
305
+ :num_connects, InfoType[:long] + 26,
306
+ :ssl_engines, InfoType[:slist] + 27,
307
+ :cookielist, InfoType[:slist] + 28,
308
+ :lastsocket, InfoType[:long] + 29,
309
+ :ftp_entry_path, InfoType[:string] + 30,
310
+ :redirect_url, InfoType[:string] + 31,
311
+ :primary_ip, InfoType[:string] + 32,
312
+ :appconnect_time, InfoType[:double] + 33,
313
+ :certinfo, InfoType[:slist] + 34,
314
+ :condition_unmet, InfoType[:long] + 35,
315
+ :rtsp_session_id, InfoType[:string] + 36,
316
+ :rtsp_client_cseq, InfoType[:long] + 37,
317
+ :rtsp_server_cseq, InfoType[:long] + 38,
318
+ :rtsp_cseq_recv, InfoType[:long] + 39,
319
+ :primary_port, InfoType[:long] + 40,
320
+ :local_ip, InfoType[:string] + 41,
321
+ :local_port, InfoType[:long] + 42,
322
+ :last, 42]
323
+
324
+ FormOption = enum :form_option, [
325
+ :none,
326
+ :copyname,
327
+ :ptrname,
328
+ :namelength,
329
+ :copycontents,
330
+ :ptrcontents,
331
+ :contentslength,
332
+ :filecontent,
333
+ :array,
334
+ :obsolete,
335
+ :file,
336
+ :buffer,
337
+ :bufferptr,
338
+ :bufferlength,
339
+ :contenttype,
340
+ :contentheader,
341
+ :filename,
342
+ :end,
343
+ :obsolete2,
344
+ :stream,
345
+ :last]
346
+
347
+ Auth = enum [
348
+ :basic, 0x01,
349
+ :digest, 0x02,
350
+ :gssnegotiate, 0x04,
351
+ :ntlm, 0x08,
352
+ :digest_ie, 0x10,
353
+ :auto, 0x1f] # all options or'd together
354
+
355
+ Proxy = enum [
356
+ :http, 0,
357
+ :http_1_0, 1,
358
+ :socks4, 4,
359
+ :socks5, 5,
360
+ :socks4a, 6]
361
+
362
+ SSLVersion = enum [
363
+ :default, 0,
364
+ :tlsv1, 1,
365
+ :sslv2, 2,
366
+ :sslv3, 3]
367
+
368
+ MsgCode = enum :msg_code, [:none, :done, :last]
369
+
370
+ class MsgData < ::FFI::Union
371
+ layout :whatever, :pointer,
372
+ :code, :easy_code
373
+ end
374
+
375
+ class Msg < ::FFI::Struct
376
+ layout :code, :msg_code,
377
+ :easy_handle, :pointer,
378
+ :data, MsgData
379
+ end
380
+
381
+ class FDSet < ::FFI::Struct
382
+ # XXX how does this work on non-windows? how can curl know the new size...
383
+ FD_SETSIZE = 524288 # set a higher maximum number of fds. this has never applied to windows, so just use the default there
384
+
385
+ if Curl.windows?
386
+ layout :fd_count, :u_int,
387
+ :fd_array, [:u_int, 64] # 2048 FDs
388
+
389
+ def clear; self[:fd_count] = 0; end
390
+ else
391
+ layout :fds_bits, [:long, FD_SETSIZE / ::FFI::Type::LONG.size]
392
+
393
+ def clear; super; end
394
+ end
395
+ end
396
+
397
+ class Timeval < ::FFI::Struct
398
+ layout :sec, :time_t,
399
+ :usec, :suseconds_t
400
+ end
401
+
402
+ callback :callback, [:pointer, :size_t, :size_t, :pointer], :size_t
403
+
404
+ ffi_lib_flags :now, :global
405
+ ffi_lib 'libcurl'
406
+
407
+ attach_function :global_init, :curl_global_init, [:long], :int
408
+
409
+ attach_function :easy_init, :curl_easy_init, [], :pointer
410
+ attach_function :easy_cleanup, :curl_easy_cleanup, [:pointer], :void
411
+ attach_function :easy_getinfo, :curl_easy_getinfo, [:pointer, :info, :pointer], :easy_code
412
+ attach_function :easy_setopt, :curl_easy_setopt, [:pointer, :option, :pointer], :easy_code
413
+ attach_function :easy_setopt_string, :curl_easy_setopt, [:pointer, :option, :string], :easy_code
414
+ attach_function :easy_setopt_long, :curl_easy_setopt, [:pointer, :option, :long], :easy_code
415
+ attach_function :easy_setopt_callback, :curl_easy_setopt, [:pointer, :option, :callback], :easy_code
416
+ attach_function :easy_perform, :curl_easy_perform, [:pointer], :easy_code
417
+ attach_function :easy_strerror, :curl_easy_strerror, [:int], :string
418
+ attach_function :easy_escape, :curl_easy_escape, [:pointer, :pointer, :int], :string
419
+ attach_function :easy_reset, :curl_easy_reset, [:pointer], :void
420
+
421
+ attach_function :formadd, :curl_formadd, [:pointer, :pointer, :varargs], :int
422
+
423
+ attach_function :multi_init, :curl_multi_init, [], :pointer
424
+ attach_function :multi_add_handle, :curl_multi_add_handle, [:pointer, :pointer], :multi_code
425
+ attach_function :multi_remove_handle, :curl_multi_remove_handle, [:pointer, :pointer], :multi_code
426
+ attach_function :multi_info_read, :curl_multi_info_read, [:pointer, :pointer], Msg.ptr
427
+ attach_function :multi_perform, :curl_multi_perform, [:pointer, :pointer], :multi_code
428
+ attach_function :multi_timeout, :curl_multi_timeout, [:pointer, :pointer], :multi_code
429
+ attach_function :multi_fdset, :curl_multi_fdset, [:pointer, FDSet.ptr, FDSet.ptr, FDSet.ptr, :pointer], :multi_code
430
+ attach_function :multi_strerror, :curl_multi_strerror, [:int], :string
431
+
432
+ attach_function :version, :curl_version, [], :string
433
+ attach_function :slist_append, :curl_slist_append, [:pointer, :string], :pointer
434
+ attach_function :slist_free_all, :curl_slist_free_all, [:pointer], :void
435
+
436
+ ffi_lib (windows? ? 'ws2_32' : ::FFI::Library::LIBC)
437
+ @blocking = true
438
+ attach_function :select, [:int, FDSet.ptr, FDSet.ptr, FDSet.ptr, Timeval.ptr], :int
439
+
440
+ @@initialized = false
441
+ @@init_mutex = Mutex.new
442
+
443
+ def Curl.init
444
+ # ensure curl lib is initialised. not thread-safe so must be wrapped in a mutex
445
+ @@init_mutex.synchronize {
446
+ if not @@initialized
447
+ raise RuntimeError.new('curl failed to initialise') if Curl.global_init(GLOBAL_ALL) != 0
448
+ @@initialized = true
449
+ end
450
+ }
451
+ end
452
+ end
453
+ end
@@ -0,0 +1,14 @@
1
+ module Typhoeus
2
+ module EasyFu
3
+ module Auth
4
+ def auth=(authinfo)
5
+ set_option(:userpwd, auth_credentials(authinfo))
6
+ set_option(:httpauth, Typhoeus::Easy::AUTH_TYPES[authinfo[:method]]) if authinfo[:method]
7
+ end
8
+
9
+ def auth_credentials(authinfo)
10
+ "#{authinfo[:username]}:#{authinfo[:password]}"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ module Typhoeus
2
+ module EasyFu
3
+ module Callbacks
4
+ # gets called when finished and response code is not 2xx,
5
+ # or curl returns an error code.
6
+ def success
7
+ @success.call(self) if @success
8
+ end
9
+
10
+ def on_success(&block)
11
+ @success = block
12
+ end
13
+
14
+ def on_success=(block)
15
+ @success = block
16
+ end
17
+
18
+ # gets called when finished and response code is 300-599
19
+ # or curl returns an error code
20
+ def failure
21
+ @failure.call(self) if @failure
22
+ end
23
+
24
+ def on_failure(&block)
25
+ @failure = block
26
+ end
27
+
28
+ def on_failure=(block)
29
+ @failure = block
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,61 @@
1
+ module Typhoeus
2
+ module EasyFu
3
+ module FFIHelper
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def finalizer(easy)
10
+ proc {
11
+ Curl.slist_free_all(easy.header_list) if easy.header_list
12
+ Curl.easy_cleanup(easy.handle)
13
+ }
14
+ end
15
+ end
16
+
17
+ def handle
18
+ @handle ||= Curl.easy_init
19
+ end
20
+
21
+ def body_write_callback
22
+ @body_write_callback ||= proc {|stream, size, num, object|
23
+ response_body << stream.read_string(size * num)
24
+ size * num
25
+ }
26
+ end
27
+
28
+ def header_write_callback
29
+ @header_write_callback ||= proc {|stream, size, num, object|
30
+ response_header << stream.read_string(size * num)
31
+ size * num
32
+ }
33
+ end
34
+
35
+ def read_callback
36
+ @read_callback ||= proc {|stream, size, num, object|
37
+ size = size * num
38
+ left = Utils.bytesize(@request_body) - @request_body_read
39
+ size = left if size > left
40
+ if size > 0
41
+ stream.write_string(Utils.byteslice(@request_body, @request_body_read, size), size)
42
+ @request_body_read += size
43
+ end
44
+ size
45
+ }
46
+ end
47
+
48
+ def string_ptr
49
+ @string_ptr ||= ::FFI::MemoryPointer.new(:pointer)
50
+ end
51
+
52
+ def long_ptr
53
+ @long_ptr ||= ::FFI::MemoryPointer.new(:long)
54
+ end
55
+
56
+ def double_ptr
57
+ @double_ptr ||= ::FFI::MemoryPointer.new(:double)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,86 @@
1
+ module Typhoeus
2
+ module EasyFu
3
+ module Infos
4
+ def get_info_string(option)
5
+ if Curl.easy_getinfo(@handle, option, string_ptr) == :ok
6
+ string_ptr.read_pointer.read_string
7
+ else nil
8
+ end
9
+ end
10
+
11
+ def get_info_long(option)
12
+ if Curl.easy_getinfo(@handle, option, long_ptr) == :ok
13
+ long_ptr.read_long
14
+ else nil
15
+ end
16
+ end
17
+
18
+ def get_info_double(option)
19
+ if Curl.easy_getinfo(@handle, option, double_ptr) == :ok
20
+ double_ptr.read_double
21
+ else nil
22
+ end
23
+ end
24
+
25
+ def auth_methods
26
+ get_info_long(:httpauth_avail)
27
+ end
28
+
29
+ def total_time_taken
30
+ get_info_double(:total_time)
31
+ end
32
+
33
+ def start_transfer_time
34
+ get_info_double(:starttransfer_time)
35
+ end
36
+
37
+ def app_connect_time
38
+ get_info_double(:appconnect_time)
39
+ end
40
+
41
+ def pretransfer_time
42
+ get_info_double(:pretransfer_time)
43
+ end
44
+
45
+ def connect_time
46
+ get_info_double(:connect_time)
47
+ end
48
+
49
+ def name_lookup_time
50
+ get_info_double(:namelookup_time)
51
+ end
52
+
53
+ def effective_url
54
+ get_info_string(:effective_url)
55
+ end
56
+
57
+ def primary_ip
58
+ get_info_string(:primary_ip)
59
+ end
60
+
61
+ def response_code
62
+ get_info_long(:response_code)
63
+ end
64
+
65
+ def timed_out?
66
+ @curl_return_code == :operation_timedout
67
+ end
68
+
69
+ def curl_return_code
70
+ Curl::EasyCode[@curl_return_code]
71
+ end
72
+
73
+ def curl_error_message(code = @curl_return_code)
74
+ code ? Curl.easy_strerror(code) : nil
75
+ end
76
+
77
+ def curl_version
78
+ Curl.version
79
+ end
80
+
81
+ def supports_zlib?
82
+ !!(curl_version.match(/zlib/))
83
+ end
84
+ end
85
+ end
86
+ end