typhoeus 0.3.3 → 0.4.0

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.
Files changed (59) hide show
  1. data/{CHANGELOG.markdown → CHANGELOG.md} +21 -12
  2. data/LICENSE +2 -0
  3. data/README.md +455 -0
  4. data/Rakefile +6 -26
  5. data/lib/typhoeus.rb +4 -6
  6. data/lib/typhoeus/curl.rb +453 -0
  7. data/lib/typhoeus/easy.rb +60 -358
  8. data/lib/typhoeus/easy/auth.rb +14 -0
  9. data/lib/typhoeus/easy/callbacks.rb +33 -0
  10. data/lib/typhoeus/easy/ffi_helper.rb +61 -0
  11. data/lib/typhoeus/easy/infos.rb +90 -0
  12. data/lib/typhoeus/easy/options.rb +115 -0
  13. data/lib/typhoeus/easy/proxy.rb +20 -0
  14. data/lib/typhoeus/easy/ssl.rb +82 -0
  15. data/lib/typhoeus/form.rb +30 -1
  16. data/lib/typhoeus/{normalized_header_hash.rb → header.rb} +2 -6
  17. data/lib/typhoeus/hydra.rb +9 -12
  18. data/lib/typhoeus/hydra_mock.rb +2 -2
  19. data/lib/typhoeus/multi.rb +118 -9
  20. data/lib/typhoeus/param_processor.rb +43 -0
  21. data/lib/typhoeus/request.rb +18 -21
  22. data/lib/typhoeus/response.rb +5 -4
  23. data/lib/typhoeus/utils.rb +14 -27
  24. data/lib/typhoeus/version.rb +1 -1
  25. metadata +155 -152
  26. data/Gemfile.lock +0 -37
  27. data/ext/typhoeus/.gitignore +0 -7
  28. data/ext/typhoeus/extconf.rb +0 -65
  29. data/ext/typhoeus/native.c +0 -12
  30. data/ext/typhoeus/native.h +0 -22
  31. data/ext/typhoeus/typhoeus_easy.c +0 -232
  32. data/ext/typhoeus/typhoeus_easy.h +0 -20
  33. data/ext/typhoeus/typhoeus_form.c +0 -59
  34. data/ext/typhoeus/typhoeus_form.h +0 -13
  35. data/ext/typhoeus/typhoeus_multi.c +0 -217
  36. data/ext/typhoeus/typhoeus_multi.h +0 -16
  37. data/lib/typhoeus/.gitignore +0 -1
  38. data/lib/typhoeus/service.rb +0 -20
  39. data/spec/fixtures/placeholder.gif +0 -0
  40. data/spec/fixtures/placeholder.txt +0 -1
  41. data/spec/fixtures/placeholder.ukn +0 -0
  42. data/spec/fixtures/result_set.xml +0 -60
  43. data/spec/servers/app.rb +0 -97
  44. data/spec/spec_helper.rb +0 -19
  45. data/spec/support/typhoeus_localhost_server.rb +0 -58
  46. data/spec/typhoeus/easy_spec.rb +0 -391
  47. data/spec/typhoeus/filter_spec.rb +0 -35
  48. data/spec/typhoeus/form_spec.rb +0 -117
  49. data/spec/typhoeus/hydra_mock_spec.rb +0 -300
  50. data/spec/typhoeus/hydra_spec.rb +0 -602
  51. data/spec/typhoeus/multi_spec.rb +0 -74
  52. data/spec/typhoeus/normalized_header_hash_spec.rb +0 -41
  53. data/spec/typhoeus/remote_method_spec.rb +0 -141
  54. data/spec/typhoeus/remote_proxy_object_spec.rb +0 -65
  55. data/spec/typhoeus/remote_spec.rb +0 -695
  56. data/spec/typhoeus/request_spec.rb +0 -387
  57. data/spec/typhoeus/response_spec.rb +0 -192
  58. data/spec/typhoeus/utils_spec.rb +0 -22
  59. data/typhoeus.gemspec +0 -33
@@ -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,90 @@
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 redirect_count
70
+ get_info_long(:redirect_count)
71
+ end
72
+
73
+ def curl_return_code
74
+ Curl::EasyCode[@curl_return_code]
75
+ end
76
+
77
+ def curl_error_message(code = @curl_return_code)
78
+ code ? Curl.easy_strerror(code) : nil
79
+ end
80
+
81
+ def curl_version
82
+ Curl.version
83
+ end
84
+
85
+ def supports_zlib?
86
+ !!(curl_version.match(/zlib/))
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,115 @@
1
+ module Typhoeus
2
+ module EasyFu
3
+ module Options
4
+ def write_function=(callback)
5
+ set_option(:writefunction, body_write_callback)
6
+ end
7
+
8
+ def header_function=(callback)
9
+ set_option(:headerfunction, header_write_callback)
10
+ end
11
+
12
+ def encoding=(encoding)
13
+ # Enable encoding/compression support
14
+ set_option(:encoding, encoding)
15
+ end
16
+
17
+ def interface=(interface)
18
+ @interface = interface
19
+ set_option(:interface, interface)
20
+ end
21
+
22
+ def verbose=(boolean)
23
+ set_option(:verbose, !!boolean ? 1 : 0)
24
+ end
25
+
26
+ def follow_location=(boolean)
27
+ if boolean
28
+ set_option(:followlocation, 1)
29
+ else
30
+ set_option(:followlocation, 0)
31
+ end
32
+ end
33
+
34
+ def max_redirects=(redirects)
35
+ set_option(:maxredirs, redirects)
36
+ end
37
+
38
+ def connect_timeout=(milliseconds)
39
+ @connect_timeout = milliseconds
40
+ set_option(:nosignal, 1)
41
+ set_option(:connecttimeout_ms, milliseconds)
42
+ end
43
+
44
+ def timeout=(milliseconds)
45
+ @timeout = milliseconds
46
+ set_option(:nosignal, 1)
47
+ set_option(:timeout_ms, milliseconds)
48
+ end
49
+
50
+ def request_body=(request_body)
51
+ @request_body = request_body
52
+ if method == :put
53
+ @request_body_read = 0
54
+ set_option(:infilesize, Utils.bytesize(@request_body))
55
+ set_option(:readfunction, read_callback)
56
+ else
57
+ self.post_data = request_body
58
+ end
59
+ end
60
+
61
+ def user_agent=(user_agent)
62
+ set_option(:useragent, user_agent)
63
+ end
64
+
65
+ def url=(url)
66
+ @url = url
67
+ set_option(:url, url)
68
+ end
69
+
70
+ def method=(method)
71
+ @method = method
72
+ if method == :get
73
+ set_option(:httpget, 1)
74
+ elsif method == :post
75
+ set_option(:httppost, 1)
76
+ self.post_data = ""
77
+ elsif method == :put
78
+ set_option(:upload, 1)
79
+ self.request_body = @request_body.to_s
80
+ elsif method == :head
81
+ set_option(:nobody, 1)
82
+ else
83
+ set_option(:customrequest, method.to_s.upcase)
84
+ end
85
+ end
86
+
87
+ def post_data=(data)
88
+ @post_data_set = true
89
+ set_option(:postfieldsize, Utils.bytesize(data))
90
+ set_option(:copypostfields, data)
91
+ end
92
+
93
+ def set_option(option, value)
94
+ case value
95
+ when String
96
+ Curl.easy_setopt_string(handle, option, value.to_s)
97
+ when Integer
98
+ Curl.easy_setopt_long(handle, option, value)
99
+ when Proc, ::FFI::Function
100
+ Curl.easy_setopt_callback(handle, option, value)
101
+ when Typhoeus::Form
102
+ Curl.easy_setopt(handle, option, value.first.read_pointer)
103
+ else
104
+ Curl.easy_setopt(handle, option, value) if value
105
+ end
106
+ end
107
+
108
+ def set_headers
109
+ @header_list = nil
110
+ headers.each {|key, value| @header_list = Curl.slist_append(@header_list, "#{key}: #{value}") }
111
+ set_option(:httpheader, @header_list) unless headers.empty?
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,20 @@
1
+ module Typhoeus
2
+ module EasyFu
3
+ module Proxy
4
+ def proxy=(proxy)
5
+ set_option(:proxy, proxy[:server])
6
+ set_option(:proxytype, Typhoeus::Easy::PROXY_TYPES[proxy[:type]]) if proxy[:type]
7
+ end
8
+
9
+ def proxy_auth=(authinfo)
10
+ set_option(:proxyuserpwd, proxy_credentials(authinfo))
11
+ set_option(:proxyauth, Typhoeus::Easy::PROXY_TYPES[proxy[:type]]) if authinfo[:method]
12
+ end
13
+
14
+ def proxy_credentials(authinfo)
15
+ "#{authinfo[:username]}:#{authinfo[:password]}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,82 @@
1
+ module Typhoeus
2
+ module EasyFu
3
+ module SSL
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def valid_ssl_version(version)
10
+ Typhoeus::Easy::SSL_VERSIONS.key?(version.to_sym)
11
+ end
12
+ end
13
+
14
+ def ssl_version
15
+ @ssl_version
16
+ end
17
+
18
+ def ssl_version=(version)
19
+ raise "Invalid SSL version: '#{version}' supplied! Please supply one as listed in Typhoeus::Easy::SSL_VERSIONS" unless self.class.valid_ssl_version(version)
20
+ @ssl_version = version
21
+
22
+ set_option(:sslversion, Typhoeus::Easy::SSL_VERSIONS[version])
23
+ end
24
+
25
+ def disable_ssl_peer_verification
26
+ set_option(:verifypeer, 0)
27
+ end
28
+
29
+ def disable_ssl_host_verification
30
+ set_option(:verifyhost, 0)
31
+ end
32
+
33
+ # Set SSL certificate
34
+ # " The string should be the file name of your certificate. "
35
+ # The default format is "PEM" and can be changed with ssl_cert_type=
36
+ def ssl_cert=(cert)
37
+ set_option(:sslcert, cert)
38
+ end
39
+
40
+ # Set SSL certificate type
41
+ # " The string should be the format of your certificate. Supported formats are "PEM" and "DER" "
42
+ def ssl_cert_type=(cert_type)
43
+ raise "Invalid ssl cert type : '#{cert_type}'..." if cert_type and !%w(PEM DER p12).include?(cert_type)
44
+ set_option(:sslcerttype, cert_type)
45
+ end
46
+
47
+ # Set SSL Key file
48
+ # " The string should be the file name of your private key. "
49
+ # The default format is "PEM" and can be changed with ssl_key_type=
50
+ #
51
+ def ssl_key=(key)
52
+ set_option(:sslkey, key)
53
+ end
54
+
55
+ # Set SSL Key type
56
+ # " The string should be the format of your private key. Supported formats are "PEM", "DER" and "ENG". "
57
+ #
58
+ def ssl_key_type=(key_type)
59
+ raise "Invalid ssl key type : '#{key_type}'..." if key_type and !%w(PEM DER ENG).include?(key_type)
60
+ set_option(:sslkeytype, key_type)
61
+ end
62
+
63
+ def ssl_key_password=(key_password)
64
+ set_option(:keypasswd, key_password)
65
+ end
66
+
67
+ # Set SSL CACERT
68
+ # " File holding one or more certificates to verify the peer with. "
69
+ #
70
+ def ssl_cacert=(cacert)
71
+ set_option(:cainfo, cacert)
72
+ end
73
+
74
+ # Set CAPATH
75
+ # " directory holding multiple CA certificates to verify the peer with. The certificate directory must be prepared using the openssl c_rehash utility. "
76
+ #
77
+ def ssl_capath=(capath)
78
+ set_option(:capath, capath)
79
+ end
80
+ end
81
+ end
82
+ end
data/lib/typhoeus/form.rb CHANGED
@@ -3,16 +3,45 @@ require 'mime/types'
3
3
  module Typhoeus
4
4
  class Form
5
5
  attr_accessor :params
6
- attr_reader :traversal
6
+ attr_reader :first, :traversal
7
7
 
8
8
  def initialize(params = {})
9
9
  @params = params
10
+ @first = ::FFI::MemoryPointer.new(:pointer)
11
+ @last = ::FFI::MemoryPointer.new(:pointer)
12
+
13
+ ObjectSpace.define_finalizer(self, self.class.finalizer(self))
14
+ end
15
+
16
+ def self.finalizer(form)
17
+ proc { Curl.formfree(form.first) }
10
18
  end
11
19
 
12
20
  def traversal
13
21
  @traversal ||= Typhoeus::Utils.traverse_params_hash(params)
14
22
  end
15
23
 
24
+ def formadd_param(name, contents)
25
+ Curl.formadd(@first, @last,
26
+ :form_option, :copyname, :pointer, name,
27
+ :form_option, :namelength, :long, Utils.bytesize(name),
28
+ :form_option, :copycontents, :pointer, contents,
29
+ :form_option, :contentslength, :long, Utils.bytesize(contents),
30
+ :form_option, :end)
31
+ end
32
+ private :formadd_param
33
+
34
+ def formadd_file(name, filename, contenttype, file)
35
+ Curl.formadd(@first, @last,
36
+ :form_option, :copyname, :pointer, name,
37
+ :form_option, :namelength, :long, Utils.bytesize(name),
38
+ :form_option, :file, :string, file,
39
+ :form_option, :filename, :string, filename,
40
+ :form_option, :contenttype, :string, contenttype,
41
+ :form_option, :end)
42
+ end
43
+ private :formadd_file
44
+
16
45
  def process!
17
46
  # add params
18
47
  traversal[:params].each { |p| formadd_param(p[0], p[1]) }