dcu-typhoeus 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.
@@ -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
@@ -0,0 +1,115 @@
1
+ require 'typhoeus/easy/ffi_helper'
2
+ require 'typhoeus/easy/options'
3
+ require 'typhoeus/easy/ssl'
4
+ require 'typhoeus/easy/auth'
5
+ require 'typhoeus/easy/proxy'
6
+ require 'typhoeus/easy/callbacks'
7
+ require 'typhoeus/easy/infos'
8
+
9
+ module Typhoeus
10
+ class Easy
11
+ include Typhoeus::EasyFu::FFIHelper
12
+ include Typhoeus::EasyFu::Options
13
+ include Typhoeus::EasyFu::SSL
14
+ include Typhoeus::EasyFu::Auth
15
+ include Typhoeus::EasyFu::Proxy
16
+ include Typhoeus::EasyFu::Callbacks
17
+ include Typhoeus::EasyFu::Infos
18
+
19
+ OPTION_VALUES = Curl::Option.to_hash.dup
20
+ Curl::Option.to_hash.each {|key, value| OPTION_VALUES["CURLOPT_#{key.to_s.upcase}".to_sym] = value }
21
+ INFO_VALUES = Curl::Info.to_hash.dup
22
+ Curl::Info.to_hash.each {|key, value| INFO_VALUES["CURLINFO_#{key.to_s.upcase}".to_sym] = value }
23
+ AUTH_TYPES = Curl::Auth.to_hash.dup
24
+ Curl::Auth.to_hash.each {|key, value| AUTH_TYPES["CURLAUTH_#{key.to_s.upcase}".to_sym] = value }
25
+ PROXY_TYPES = Curl::Proxy.to_hash.dup
26
+ Curl::Proxy.to_hash.each {|key, value| PROXY_TYPES["CURLPROXY_#{key.to_s.upcase}".to_sym] = value }
27
+ SSL_VERSIONS = Curl::SSLVersion.to_hash.dup
28
+ Curl::SSLVersion.to_hash.each {|key, value| SSL_VERSIONS["CURL_SSLVERSION_#{key.to_s.upcase}".to_sym] = value }
29
+
30
+ attr_reader :url, :header_list
31
+ attr_accessor :start_time
32
+
33
+ def initialize
34
+ Curl.init
35
+ reset(true)
36
+ ObjectSpace.define_finalizer(self, self.class.finalizer(self))
37
+ end
38
+
39
+ def method
40
+ @method ||= :get
41
+ end
42
+
43
+ def headers
44
+ @header ||= {}
45
+ end
46
+
47
+ def response_body
48
+ @response_body ||= ""
49
+ end
50
+
51
+ def response_header
52
+ @response_header ||= ""
53
+ end
54
+
55
+ def headers=(hash)
56
+ @headers = hash
57
+ end
58
+
59
+ def params
60
+ @form.nil? ? {} : @form.params
61
+ end
62
+
63
+ def params=(params)
64
+ @form = Typhoeus::Form.new(params)
65
+
66
+ if method == :post
67
+ @form.process!
68
+ if @form.multipart?
69
+ set_option(:httppost, @form)
70
+ else
71
+ self.post_data = @form.to_s
72
+ end
73
+ else
74
+ self.url = "#{url}?#{@form.to_s}"
75
+ end
76
+ end
77
+
78
+ def perform
79
+ set_headers()
80
+ @curl_return_code = Curl.easy_perform(handle)
81
+ resp_code = response_code()
82
+ if resp_code >= 200 && resp_code <= 299
83
+ success
84
+ else
85
+ failure
86
+ end
87
+ resp_code
88
+ end
89
+
90
+ def reset(fresh = nil)
91
+ unless fresh
92
+ @response_code = 0
93
+ @response_header = ""
94
+ @response_body = ""
95
+ @request_body = ""
96
+
97
+ if @header_list
98
+ Curl.slist_free_all(@header_list)
99
+ @header_list = nil
100
+ end
101
+
102
+ Curl.easy_reset(handle)
103
+ end
104
+
105
+ self.write_function = body_write_callback
106
+ self.header_function = header_write_callback
107
+ self.encoding = ''
108
+ self.ssl_version = :default
109
+ end
110
+
111
+ def curl_return_code=(code)
112
+ @curl_return_code = (code.class == Symbol ? code : Curl::EasyCode[code])
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,28 @@
1
+ module Typhoeus
2
+ class Filter
3
+ attr_reader :method_name
4
+
5
+ def initialize(method_name, options = {})
6
+ @method_name = method_name
7
+ @options = options
8
+ end
9
+
10
+ def apply_filter?(method_name)
11
+ if @options[:only]
12
+ if @options[:only].instance_of? Symbol
13
+ @options[:only] == method_name
14
+ else
15
+ @options[:only].include?(method_name)
16
+ end
17
+ elsif @options[:except]
18
+ if @options[:except].instance_of? Symbol
19
+ @options[:except] != method_name
20
+ else
21
+ !@options[:except].include?(method_name)
22
+ end
23
+ else
24
+ true
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,61 @@
1
+ require 'mime/types'
2
+
3
+ module Typhoeus
4
+ class Form
5
+ attr_accessor :params
6
+ attr_reader :first, :traversal
7
+
8
+ def initialize(params = {})
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) }
18
+ end
19
+
20
+ def traversal
21
+ @traversal ||= Typhoeus::Utils.traverse_params_hash(params)
22
+ end
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
+
45
+ def process!
46
+ # add params
47
+ traversal[:params].each { |p| formadd_param(p[0], p[1]) }
48
+
49
+ # add files
50
+ traversal[:files].each { |file_args| formadd_file(*file_args) }
51
+ end
52
+
53
+ def multipart?
54
+ !traversal[:files].empty?
55
+ end
56
+
57
+ def to_s
58
+ Typhoeus::Utils.traversal_to_param_string(traversal, false)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,54 @@
1
+ module Typhoeus
2
+ class Header < ::Hash
3
+ def initialize(constructor = {})
4
+ if constructor.is_a?(Hash)
5
+ super
6
+ update(constructor)
7
+ else
8
+ super(constructor)
9
+ end
10
+ end
11
+
12
+ def fetch(key, *extras)
13
+ super(convert_key(key), *extras)
14
+ end
15
+
16
+ def key?(key)
17
+ super(convert_key(key))
18
+ end
19
+
20
+ def [](key)
21
+ super(convert_key(key))
22
+ end
23
+
24
+ def []=(key, value)
25
+ super(convert_key(key), value)
26
+ end
27
+
28
+ def update(other_hash)
29
+ other_hash.each_pair do |key, value|
30
+ self[convert_key(key)] = value
31
+ end
32
+ self
33
+ end
34
+
35
+ alias_method :merge!, :update
36
+
37
+ def dup
38
+ self.class.new(Marshal.load(Marshal.dump(self)))
39
+ end
40
+
41
+ def merge(hash)
42
+ self.dup.update(hash)
43
+ end
44
+
45
+ def delete(key)
46
+ super(convert_key(key))
47
+ end
48
+
49
+ private
50
+ def convert_key(key)
51
+ key.to_s.split(/_|-/).map { |segment| segment.capitalize }.join("-")
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,24 @@
1
+ module Typhoeus
2
+ class Hydra
3
+ module Callbacks
4
+ def self.extended(base)
5
+ class << base
6
+ attr_accessor :global_hooks
7
+ end
8
+ base.global_hooks = Hash.new { |h, k| h[k] = [] }
9
+ end
10
+
11
+ def after_request_before_on_complete(&block)
12
+ global_hooks[:after_request_before_on_complete] << block
13
+ end
14
+
15
+ def run_global_hooks_for(name, request)
16
+ global_hooks[name].each { |hook| hook.call(request) }
17
+ end
18
+
19
+ def clear_global_hooks
20
+ global_hooks.clear
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,61 @@
1
+ module Typhoeus
2
+ class Hydra
3
+ class NetConnectNotAllowedError < StandardError; end
4
+
5
+ module ConnectOptions
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ # This method checks to see if we should raise an error on
11
+ # a request.
12
+ #
13
+ # @raises NetConnectNotAllowedError
14
+ def check_allow_net_connect!(request)
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}"
19
+ end
20
+ private :check_allow_net_connect!
21
+
22
+ module ClassMethods
23
+ def self.extended(base)
24
+ class << base
25
+ attr_accessor :allow_net_connect
26
+ attr_accessor :ignore_localhost
27
+ end
28
+ base.allow_net_connect = true
29
+ base.ignore_localhost = false
30
+ end
31
+
32
+ # Returns whether we allow external HTTP connections.
33
+ # Useful for mocking/tests.
34
+ #
35
+ # @return [boolean] true/false
36
+ def allow_net_connect?
37
+ allow_net_connect
38
+ end
39
+
40
+ def ignore_localhost?
41
+ ignore_localhost
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
57
+ end
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,68 @@
1
+ module Typhoeus
2
+ class Hydra
3
+ module Stubbing
4
+ module SharedMethods
5
+ def stub(method, url, options = {})
6
+ stubs << HydraMock.new(url, method, options)
7
+ stubs.last
8
+ end
9
+
10
+ def clear_stubs
11
+ self.stubs = []
12
+ end
13
+
14
+ def register_stub_finder(&block)
15
+ stub_finders << block
16
+ end
17
+
18
+ def find_stub_from_request(request)
19
+ stub_finders.each do |finder|
20
+ if response = finder.call(request)
21
+ mock = HydraMock.new(/.*/, :any)
22
+ mock.and_return(response)
23
+ return mock
24
+ end
25
+ end
26
+
27
+ stubs.detect { |stub| stub.matches?(request) }
28
+ end
29
+
30
+ def stub_finders
31
+ @stub_finders ||= []
32
+ end
33
+
34
+ def self.extended(base)
35
+ class << base
36
+ attr_accessor :stubs
37
+ end
38
+ base.stubs = []
39
+ end
40
+ end
41
+
42
+ def self.included(base)
43
+ base.extend(SharedMethods)
44
+ base.class_eval do
45
+ attr_accessor :stubs
46
+ end
47
+ end
48
+
49
+ def assign_to_stub(request)
50
+ m = find_stub_from_request(request)
51
+
52
+ # Fallback to global stubs.
53
+ m ||= self.class.find_stub_from_request(request)
54
+
55
+ if m
56
+ m.add_request(request)
57
+ @active_stubs << m
58
+ m
59
+ else
60
+ nil
61
+ end
62
+ end
63
+ private :assign_to_stub
64
+
65
+ include SharedMethods
66
+ end
67
+ end
68
+ end