typhoeus 0.4.2 → 0.5.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +86 -28
- data/Gemfile +17 -1
- data/README.md +20 -422
- data/Rakefile +21 -12
- data/lib/typhoeus.rb +58 -41
- data/lib/typhoeus/config.rb +14 -0
- data/lib/typhoeus/errors.rb +9 -0
- data/lib/typhoeus/errors/no_stub.rb +12 -0
- data/lib/typhoeus/errors/typhoeus_error.rb +8 -0
- data/lib/typhoeus/expectation.rb +126 -0
- data/lib/typhoeus/hydra.rb +31 -236
- data/lib/typhoeus/hydras/block_connection.rb +33 -0
- data/lib/typhoeus/hydras/easy_factory.rb +67 -0
- data/lib/typhoeus/hydras/easy_pool.rb +40 -0
- data/lib/typhoeus/hydras/memoizable.rb +53 -0
- data/lib/typhoeus/hydras/queueable.rb +46 -0
- data/lib/typhoeus/hydras/runnable.rb +18 -0
- data/lib/typhoeus/hydras/stubbable.rb +27 -0
- data/lib/typhoeus/request.rb +68 -243
- data/lib/typhoeus/requests/actions.rb +101 -0
- data/lib/typhoeus/requests/block_connection.rb +31 -0
- data/lib/typhoeus/requests/callbacks.rb +82 -0
- data/lib/typhoeus/requests/marshal.rb +21 -0
- data/lib/typhoeus/requests/memoizable.rb +36 -0
- data/lib/typhoeus/requests/operations.rb +52 -0
- data/lib/typhoeus/requests/responseable.rb +29 -0
- data/lib/typhoeus/requests/stubbable.rb +29 -0
- data/lib/typhoeus/response.rb +24 -118
- data/lib/typhoeus/responses/header.rb +50 -0
- data/lib/typhoeus/responses/informations.rb +43 -0
- data/lib/typhoeus/responses/legacy.rb +27 -0
- data/lib/typhoeus/responses/status.rb +78 -0
- data/lib/typhoeus/version.rb +3 -1
- metadata +34 -141
- data/lib/typhoeus/curl.rb +0 -453
- data/lib/typhoeus/easy.rb +0 -115
- data/lib/typhoeus/easy/auth.rb +0 -14
- data/lib/typhoeus/easy/callbacks.rb +0 -33
- data/lib/typhoeus/easy/ffi_helper.rb +0 -61
- data/lib/typhoeus/easy/infos.rb +0 -90
- data/lib/typhoeus/easy/options.rb +0 -115
- data/lib/typhoeus/easy/proxy.rb +0 -20
- data/lib/typhoeus/easy/ssl.rb +0 -82
- data/lib/typhoeus/filter.rb +0 -28
- data/lib/typhoeus/form.rb +0 -61
- data/lib/typhoeus/header.rb +0 -54
- data/lib/typhoeus/hydra/callbacks.rb +0 -24
- data/lib/typhoeus/hydra/connect_options.rb +0 -61
- data/lib/typhoeus/hydra/stubbing.rb +0 -68
- data/lib/typhoeus/hydra_mock.rb +0 -131
- data/lib/typhoeus/multi.rb +0 -146
- data/lib/typhoeus/param_processor.rb +0 -43
- data/lib/typhoeus/remote.rb +0 -306
- data/lib/typhoeus/remote_method.rb +0 -108
- data/lib/typhoeus/remote_proxy_object.rb +0 -50
- data/lib/typhoeus/utils.rb +0 -50
data/lib/typhoeus/easy/ssl.rb
DELETED
@@ -1,82 +0,0 @@
|
|
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(:ssl_verifypeer, 0)
|
27
|
-
end
|
28
|
-
|
29
|
-
def disable_ssl_host_verification
|
30
|
-
set_option(:ssl_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/filter.rb
DELETED
@@ -1,28 +0,0 @@
|
|
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
|
data/lib/typhoeus/form.rb
DELETED
@@ -1,61 +0,0 @@
|
|
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
|
data/lib/typhoeus/header.rb
DELETED
@@ -1,54 +0,0 @@
|
|
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
|
@@ -1,24 +0,0 @@
|
|
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
|
@@ -1,61 +0,0 @@
|
|
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
|
-
|
@@ -1,68 +0,0 @@
|
|
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
|
data/lib/typhoeus/hydra_mock.rb
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
module Typhoeus
|
2
|
-
class HydraMock
|
3
|
-
attr_reader :url, :method, :requests, :uri
|
4
|
-
|
5
|
-
def initialize(url, method, options = {})
|
6
|
-
@url = url
|
7
|
-
@uri = URI.parse(url) if url.kind_of?(String)
|
8
|
-
@method = method
|
9
|
-
@requests = []
|
10
|
-
@options = options
|
11
|
-
if @options[:headers]
|
12
|
-
@options[:headers] = Typhoeus::Header.new(@options[:headers])
|
13
|
-
end
|
14
|
-
|
15
|
-
@current_response_index = 0
|
16
|
-
end
|
17
|
-
|
18
|
-
def body
|
19
|
-
@options[:body]
|
20
|
-
end
|
21
|
-
|
22
|
-
def body?
|
23
|
-
@options.has_key?(:body)
|
24
|
-
end
|
25
|
-
|
26
|
-
def headers
|
27
|
-
@options[:headers]
|
28
|
-
end
|
29
|
-
|
30
|
-
def headers?
|
31
|
-
@options.has_key?(:headers)
|
32
|
-
end
|
33
|
-
|
34
|
-
def add_request(request)
|
35
|
-
@requests << request
|
36
|
-
end
|
37
|
-
|
38
|
-
def and_return(val)
|
39
|
-
if val.respond_to?(:each)
|
40
|
-
@responses = val
|
41
|
-
else
|
42
|
-
@responses = [val]
|
43
|
-
end
|
44
|
-
|
45
|
-
# make sure to mark them as a mock.
|
46
|
-
@responses.each { |r| r.mock = true }
|
47
|
-
|
48
|
-
val
|
49
|
-
end
|
50
|
-
|
51
|
-
def response
|
52
|
-
if @current_response_index == (@responses.length - 1)
|
53
|
-
@responses.last
|
54
|
-
else
|
55
|
-
value = @responses[@current_response_index]
|
56
|
-
@current_response_index += 1
|
57
|
-
value
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def matches?(request)
|
62
|
-
if !method_matches?(request) or !url_matches?(request)
|
63
|
-
return false
|
64
|
-
end
|
65
|
-
|
66
|
-
if body?
|
67
|
-
return false unless body_matches?(request)
|
68
|
-
end
|
69
|
-
|
70
|
-
if headers?
|
71
|
-
return false unless headers_match?(request)
|
72
|
-
end
|
73
|
-
|
74
|
-
true
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
def method_matches?(request)
|
79
|
-
self.method == :any or self.method == request.method
|
80
|
-
end
|
81
|
-
|
82
|
-
def url_matches?(request)
|
83
|
-
if url.kind_of?(String)
|
84
|
-
request_uri = URI.parse(request.url)
|
85
|
-
request_uri == self.uri
|
86
|
-
else
|
87
|
-
self.url =~ request.url
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def body_matches?(request)
|
92
|
-
!request.body.nil? && !request.body.empty? && request.body == self.body
|
93
|
-
end
|
94
|
-
|
95
|
-
def headers_match?(request)
|
96
|
-
request_headers = Header.new(request.headers)
|
97
|
-
|
98
|
-
if empty_headers?(self.headers)
|
99
|
-
empty_headers?(request_headers)
|
100
|
-
else
|
101
|
-
return false if empty_headers?(request_headers)
|
102
|
-
|
103
|
-
headers.each do |key, value|
|
104
|
-
return false unless header_value_matches?(value, request_headers[key])
|
105
|
-
end
|
106
|
-
|
107
|
-
true
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def header_value_matches?(mock_value, request_value)
|
112
|
-
mock_arr = mock_value.is_a?(Array) ? mock_value : [mock_value]
|
113
|
-
request_arr = request_value.is_a?(Array) ? request_value : [request_value]
|
114
|
-
|
115
|
-
return false unless mock_arr.size == request_arr.size
|
116
|
-
mock_arr.all? do |value|
|
117
|
-
request_arr.any? { |a| value === a }
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def empty_headers?(headers)
|
122
|
-
# We consider the default User-Agent header to be empty since
|
123
|
-
# Typhoeus always adds that.
|
124
|
-
headers.nil? || headers.empty? || default_typhoeus_headers?(headers)
|
125
|
-
end
|
126
|
-
|
127
|
-
def default_typhoeus_headers?(headers)
|
128
|
-
headers.size == 1 && headers['User-Agent'] == Typhoeus::USER_AGENT
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|