typhoeus 0.4.2 → 0.5.0.rc
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.md +86 -28
- data/Gemfile +17 -1
- data/README.md +20 -422
- data/Rakefile +21 -12
- data/lib/typhoeus/config.rb +47 -0
- data/lib/typhoeus/errors/no_stub.rb +12 -0
- data/lib/typhoeus/errors/typhoeus_error.rb +8 -0
- data/lib/typhoeus/errors.rb +9 -0
- data/lib/typhoeus/expectation.rb +174 -0
- data/lib/typhoeus/hydra/before.rb +30 -0
- data/lib/typhoeus/hydra/block_connection.rb +35 -0
- data/lib/typhoeus/hydra/easy_factory.rb +79 -0
- data/lib/typhoeus/hydra/easy_pool.rb +42 -0
- data/lib/typhoeus/hydra/memoizable.rb +55 -0
- data/lib/typhoeus/hydra/queueable.rb +48 -0
- data/lib/typhoeus/hydra/runnable.rb +21 -0
- data/lib/typhoeus/hydra/stubbable.rb +26 -0
- data/lib/typhoeus/hydra.rb +83 -236
- data/lib/typhoeus/request/actions.rb +125 -0
- data/lib/typhoeus/request/before.rb +30 -0
- data/lib/typhoeus/request/block_connection.rb +52 -0
- data/lib/typhoeus/request/callbacks.rb +98 -0
- data/lib/typhoeus/request/marshal.rb +21 -0
- data/lib/typhoeus/request/memoizable.rb +38 -0
- data/lib/typhoeus/request/operations.rb +71 -0
- data/lib/typhoeus/request/responseable.rb +29 -0
- data/lib/typhoeus/request/stubbable.rb +28 -0
- data/lib/typhoeus/request.rb +144 -241
- data/lib/typhoeus/response/header.rb +54 -0
- data/lib/typhoeus/response/informations.rb +205 -0
- data/lib/typhoeus/response/status.rb +80 -0
- data/lib/typhoeus/response.rb +45 -118
- data/lib/typhoeus/version.rb +3 -1
- data/lib/typhoeus.rb +87 -39
- metadata +37 -143
- data/lib/typhoeus/curl.rb +0 -453
- 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/easy.rb +0 -115
- 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/hydra.rb
CHANGED
|
@@ -1,247 +1,94 @@
|
|
|
1
|
-
require 'typhoeus/hydra/
|
|
2
|
-
require 'typhoeus/hydra/
|
|
3
|
-
require 'typhoeus/hydra/
|
|
1
|
+
require 'typhoeus/hydra/before'
|
|
2
|
+
require 'typhoeus/hydra/block_connection'
|
|
3
|
+
require 'typhoeus/hydra/easy_factory'
|
|
4
|
+
require 'typhoeus/hydra/easy_pool'
|
|
5
|
+
require 'typhoeus/hydra/memoizable'
|
|
6
|
+
require 'typhoeus/hydra/queueable'
|
|
7
|
+
require 'typhoeus/hydra/runnable'
|
|
8
|
+
require 'typhoeus/hydra/stubbable'
|
|
4
9
|
|
|
5
10
|
module Typhoeus
|
|
6
|
-
class Hydra
|
|
7
|
-
include ConnectOptions
|
|
8
|
-
include Stubbing
|
|
9
|
-
extend Callbacks
|
|
10
|
-
|
|
11
|
-
def initialize(options = {})
|
|
12
|
-
@memoize_requests = true
|
|
13
|
-
@multi = Multi.new
|
|
14
|
-
@easy_pool = []
|
|
15
|
-
initial_pool_size = options[:initial_pool_size] || 10
|
|
16
|
-
@max_concurrency = options[:max_concurrency] || 200
|
|
17
|
-
initial_pool_size.times { @easy_pool << Easy.new }
|
|
18
|
-
@memoized_requests = {}
|
|
19
|
-
@retrieved_from_cache = {}
|
|
20
|
-
@queued_requests = []
|
|
21
|
-
@running_requests = 0
|
|
22
|
-
|
|
23
|
-
self.stubs = []
|
|
24
|
-
@active_stubs = []
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def self.hydra
|
|
28
|
-
@hydra ||= new
|
|
29
|
-
end
|
|
30
11
|
|
|
31
|
-
|
|
32
|
-
|
|
12
|
+
# Hydra manages making parallel HTTP requests. This
|
|
13
|
+
# is achieved by using libcurls multi interface:
|
|
14
|
+
# http://curl.haxx.se/libcurl/c/libcurl-multi.html
|
|
15
|
+
# The benefits are that you don't have to worry running
|
|
16
|
+
# the requests by yourself.
|
|
17
|
+
#
|
|
18
|
+
# Hydra will also handle how many requests you can
|
|
19
|
+
# make in parallel. Things will get flakey if you
|
|
20
|
+
# try to make too many requests at the same time.
|
|
21
|
+
# The built in limit is 200. When more requests than
|
|
22
|
+
# that are queued up, hydra will save them for later
|
|
23
|
+
# and start the requests as others are finished. You
|
|
24
|
+
# can raise or lower the concurrency limit through
|
|
25
|
+
# the Hydra constructor.
|
|
26
|
+
#
|
|
27
|
+
# Regarding the asynchronous behavior of the hydra,
|
|
28
|
+
# it is important to know that this is completely hidden
|
|
29
|
+
# from the developer and you are free to apply
|
|
30
|
+
# whatever technique you want to your code. That should not
|
|
31
|
+
# conflict with libcurls internal concurrency mechanism.
|
|
32
|
+
#
|
|
33
|
+
# @example Use the hydra to do multiple requests.
|
|
34
|
+
# hydra = Typhoeus::Hydra.new
|
|
35
|
+
# requests = (0..9).map{ Typhoeus::Request.new("www.example.com") }
|
|
36
|
+
# requests.each{ |request| hydra.queue(request) }
|
|
37
|
+
# hydra.run
|
|
38
|
+
class Hydra
|
|
39
|
+
include Hydra::EasyPool
|
|
40
|
+
include Hydra::Queueable
|
|
41
|
+
include Hydra::Runnable
|
|
42
|
+
include Hydra::Memoizable
|
|
43
|
+
include Hydra::BlockConnection
|
|
44
|
+
include Hydra::Stubbable
|
|
45
|
+
include Hydra::Before
|
|
46
|
+
|
|
47
|
+
# @example Set max_concurrency.
|
|
48
|
+
# Typhoeus::Hydra.new(:max_concurrency => 20)
|
|
49
|
+
attr_reader :max_concurrency
|
|
50
|
+
|
|
51
|
+
# @api private
|
|
52
|
+
attr_reader :multi
|
|
53
|
+
|
|
54
|
+
class << self
|
|
55
|
+
|
|
56
|
+
# Returns a memoized hydra instance.
|
|
57
|
+
#
|
|
58
|
+
# @example Get a hydra.
|
|
59
|
+
# Typhoeus::Hydra.hydra
|
|
60
|
+
#
|
|
61
|
+
# @return [Typhoeus::Hydra] A new hydra.
|
|
62
|
+
#
|
|
63
|
+
# @deprecated This is only for convenience because so
|
|
64
|
+
# much external code relies on it.
|
|
65
|
+
def hydra
|
|
66
|
+
@hydra ||= new
|
|
67
|
+
end
|
|
33
68
|
end
|
|
34
69
|
|
|
70
|
+
# Create a new hydra. All
|
|
71
|
+
# {http://rubydoc.info/github/typhoeus/ethon/Ethon/Multi#initialize-instance_method Ethon::Multi#initialize}
|
|
72
|
+
# options are also available.
|
|
35
73
|
#
|
|
36
|
-
#
|
|
74
|
+
# @example Create a hydra.
|
|
75
|
+
# Typhoeus::Hydra.new
|
|
37
76
|
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
# will be aborted as soon as possible...
|
|
77
|
+
# @example Create a hydra with max_concurrency.
|
|
78
|
+
# Typhoeus::Hydra.new(:max_concurrency => 20)
|
|
41
79
|
#
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
@
|
|
53
|
-
@multi.
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def queue(request, obey_concurrency_limit = true)
|
|
57
|
-
return if assign_to_stub(request)
|
|
58
|
-
|
|
59
|
-
# At this point, we are running over live HTTP. Make sure we haven't
|
|
60
|
-
# disabled live requests.
|
|
61
|
-
check_allow_net_connect!(request)
|
|
62
|
-
|
|
63
|
-
if @running_requests >= @max_concurrency && obey_concurrency_limit
|
|
64
|
-
@queued_requests << request
|
|
65
|
-
else
|
|
66
|
-
if request.method == :get
|
|
67
|
-
if @memoize_requests && @memoized_requests.key?(request.url)
|
|
68
|
-
if response = @retrieved_from_cache[request.url]
|
|
69
|
-
request.response = response
|
|
70
|
-
request.call_handlers
|
|
71
|
-
else
|
|
72
|
-
@memoized_requests[request.url] << request
|
|
73
|
-
end
|
|
74
|
-
else
|
|
75
|
-
@memoized_requests[request.url] = [] if @memoize_requests
|
|
76
|
-
get_from_cache_or_queue(request)
|
|
77
|
-
end
|
|
78
|
-
else
|
|
79
|
-
get_from_cache_or_queue(request)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def run
|
|
85
|
-
while !@active_stubs.empty?
|
|
86
|
-
m = @active_stubs.first
|
|
87
|
-
while request = m.requests.shift
|
|
88
|
-
response = m.response
|
|
89
|
-
response.request = request
|
|
90
|
-
handle_request(request, response)
|
|
91
|
-
end
|
|
92
|
-
@active_stubs.delete(m)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
@multi.perform
|
|
96
|
-
ensure
|
|
97
|
-
@multi.reset_easy_handles{|easy| release_easy_object(easy)}
|
|
98
|
-
@memoized_requests = {}
|
|
99
|
-
@retrieved_from_cache = {}
|
|
100
|
-
@running_requests = 0
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def disable_memoization
|
|
104
|
-
@memoize_requests = false
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def cache_getter(&block)
|
|
108
|
-
@cache_getter = block
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def cache_setter(&block)
|
|
112
|
-
@cache_setter = block
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def on_complete(&block)
|
|
116
|
-
@on_complete = block
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def on_complete=(proc)
|
|
120
|
-
@on_complete = proc
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
private
|
|
124
|
-
|
|
125
|
-
def get_from_cache_or_queue(request)
|
|
126
|
-
if @cache_getter
|
|
127
|
-
val = @cache_getter.call(request)
|
|
128
|
-
if val
|
|
129
|
-
@retrieved_from_cache[request.url] = val
|
|
130
|
-
queue_next
|
|
131
|
-
handle_request(request, val, false)
|
|
132
|
-
else
|
|
133
|
-
@multi.add(get_easy_object(request))
|
|
134
|
-
end
|
|
135
|
-
else
|
|
136
|
-
@multi.add(get_easy_object(request))
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def get_easy_object(request)
|
|
141
|
-
@running_requests += 1
|
|
142
|
-
|
|
143
|
-
easy = @easy_pool.pop || Easy.new
|
|
144
|
-
easy.verbose = request.verbose
|
|
145
|
-
if request.username || request.password
|
|
146
|
-
auth = { :username => request.username, :password => request.password }
|
|
147
|
-
auth[:method] = request.auth_method if request.auth_method
|
|
148
|
-
easy.auth = auth
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
if request.proxy
|
|
152
|
-
proxy = { :server => request.proxy }
|
|
153
|
-
proxy[:type] = request.proxy_type if request.proxy_type
|
|
154
|
-
easy.proxy = proxy if request.proxy
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
if request.proxy_username || request.proxy_password
|
|
158
|
-
auth = { :username => request.proxy_username, :password => request.proxy_password }
|
|
159
|
-
auth[:method] = request.proxy_auth_method if request.proxy_auth_method
|
|
160
|
-
easy.proxy_auth = auth
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
easy.url = request.url
|
|
164
|
-
easy.method = request.method
|
|
165
|
-
easy.params = request.params if [:post, :put].include?(request.method) && !request.params.nil?
|
|
166
|
-
easy.headers = request.headers if request.headers
|
|
167
|
-
easy.request_body = request.body if [:post, :put].include?(request.method) && !request.body.nil?
|
|
168
|
-
easy.timeout = request.timeout if request.timeout
|
|
169
|
-
easy.connect_timeout = request.connect_timeout if request.connect_timeout
|
|
170
|
-
easy.interface = request.interface if request.interface
|
|
171
|
-
easy.follow_location = request.follow_location if request.follow_location
|
|
172
|
-
easy.max_redirects = request.max_redirects if request.max_redirects
|
|
173
|
-
easy.disable_ssl_peer_verification if request.disable_ssl_peer_verification
|
|
174
|
-
easy.disable_ssl_host_verification if request.disable_ssl_host_verification
|
|
175
|
-
easy.ssl_cert = request.ssl_cert
|
|
176
|
-
easy.ssl_cert_type = request.ssl_cert_type
|
|
177
|
-
easy.ssl_key = request.ssl_key
|
|
178
|
-
easy.ssl_key_type = request.ssl_key_type
|
|
179
|
-
easy.ssl_key_password = request.ssl_key_password
|
|
180
|
-
easy.ssl_cacert = request.ssl_cacert
|
|
181
|
-
easy.ssl_capath = request.ssl_capath
|
|
182
|
-
easy.ssl_version = request.ssl_version || :default
|
|
183
|
-
easy.verbose = request.verbose
|
|
184
|
-
|
|
185
|
-
easy.on_success do |easy|
|
|
186
|
-
queue_next
|
|
187
|
-
handle_request(request, response_from_easy(easy, request))
|
|
188
|
-
release_easy_object(easy)
|
|
189
|
-
end
|
|
190
|
-
easy.on_failure do |easy|
|
|
191
|
-
queue_next
|
|
192
|
-
handle_request(request, response_from_easy(easy, request))
|
|
193
|
-
release_easy_object(easy)
|
|
194
|
-
end
|
|
195
|
-
easy.set_headers
|
|
196
|
-
easy
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
def queue_next
|
|
200
|
-
@running_requests -= 1
|
|
201
|
-
queue(@queued_requests.shift) unless @queued_requests.empty?
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def release_easy_object(easy)
|
|
205
|
-
easy.reset
|
|
206
|
-
@easy_pool.push easy
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
def handle_request(request, response, live_request = true)
|
|
210
|
-
request.response = response
|
|
211
|
-
|
|
212
|
-
self.class.run_global_hooks_for(:after_request_before_on_complete,
|
|
213
|
-
request)
|
|
214
|
-
|
|
215
|
-
if live_request && request.cache_timeout && @cache_setter
|
|
216
|
-
@cache_setter.call(request)
|
|
217
|
-
end
|
|
218
|
-
@on_complete.call(response) if @on_complete
|
|
219
|
-
|
|
220
|
-
request.call_handlers
|
|
221
|
-
if requests = @memoized_requests[request.url]
|
|
222
|
-
requests.each do |r|
|
|
223
|
-
r.response = response
|
|
224
|
-
r.call_handlers
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
def response_from_easy(easy, request)
|
|
230
|
-
Response.new(:code => easy.response_code,
|
|
231
|
-
:headers => easy.response_header,
|
|
232
|
-
:body => easy.response_body,
|
|
233
|
-
:time => easy.total_time_taken,
|
|
234
|
-
:start_transfer_time => easy.start_transfer_time,
|
|
235
|
-
:app_connect_time => easy.app_connect_time,
|
|
236
|
-
:pretransfer_time => easy.pretransfer_time,
|
|
237
|
-
:connect_time => easy.connect_time,
|
|
238
|
-
:name_lookup_time => easy.name_lookup_time,
|
|
239
|
-
:effective_url => easy.effective_url,
|
|
240
|
-
:primary_ip => easy.primary_ip,
|
|
241
|
-
:curl_return_code => easy.curl_return_code,
|
|
242
|
-
:curl_error_message => easy.curl_error_message,
|
|
243
|
-
:redirect_count => easy.redirect_count,
|
|
244
|
-
:request => request)
|
|
80
|
+
# @param [ Hash ] options The options hash.
|
|
81
|
+
#
|
|
82
|
+
# @option options :max_concurrency [ Integer ] Number
|
|
83
|
+
# of max concurrent connections to create. Default is
|
|
84
|
+
# 200.
|
|
85
|
+
#
|
|
86
|
+
# @see http://rubydoc.info/github/typhoeus/ethon/Ethon/Multi#initialize-instance_method
|
|
87
|
+
# Ethon::Multi#initialize
|
|
88
|
+
def initialize(options = {})
|
|
89
|
+
@options = options
|
|
90
|
+
@max_concurrency = @options.fetch(:max_concurrency, 200)
|
|
91
|
+
@multi = Ethon::Multi.new(options.reject{|k,_| k==:max_concurrency})
|
|
245
92
|
end
|
|
246
93
|
end
|
|
247
94
|
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
class Request
|
|
3
|
+
|
|
4
|
+
# Module containing logic about shortcuts to
|
|
5
|
+
# http methods. Like
|
|
6
|
+
# Typhoeus.get("www.example.com")
|
|
7
|
+
module Actions
|
|
8
|
+
|
|
9
|
+
# Make a get request.
|
|
10
|
+
#
|
|
11
|
+
# @example Make get request.
|
|
12
|
+
# Typhoeus.get("www.example.com")
|
|
13
|
+
#
|
|
14
|
+
# @param (see Typhoeus::Request#initialize)
|
|
15
|
+
#
|
|
16
|
+
# @option (see Typhoeus::Request#initialize)
|
|
17
|
+
#
|
|
18
|
+
# @return (see Typhoeus::Request#initialize)
|
|
19
|
+
#
|
|
20
|
+
# @note (see Typhoeus::Request#initialize)
|
|
21
|
+
def get(url, options = {})
|
|
22
|
+
Request.run(url, options.merge(:method => :get))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Make a post request.
|
|
26
|
+
#
|
|
27
|
+
# @example Make post request.
|
|
28
|
+
# Typhoeus.post("www.example.com")
|
|
29
|
+
#
|
|
30
|
+
# @param (see Typhoeus::Request#initialize)
|
|
31
|
+
#
|
|
32
|
+
# @option (see Typhoeus::Request#initialize)
|
|
33
|
+
#
|
|
34
|
+
# @return (see Typhoeus::Request#initialize)
|
|
35
|
+
#
|
|
36
|
+
# @note (see Typhoeus::Request#initialize)
|
|
37
|
+
def post(url, options = {})
|
|
38
|
+
Request.run(url, options.merge(:method => :post))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Make a put request.
|
|
42
|
+
#
|
|
43
|
+
# @example Make put request.
|
|
44
|
+
# Typhoeus.put("www.example.com")
|
|
45
|
+
#
|
|
46
|
+
# @param (see Typhoeus::Request#initialize)
|
|
47
|
+
#
|
|
48
|
+
# @option options :params [ Hash ] Params hash which
|
|
49
|
+
# is attached to the url.
|
|
50
|
+
# @option options :body [ Hash ] Body hash which
|
|
51
|
+
# becomes a PUT request body.
|
|
52
|
+
#
|
|
53
|
+
# @return (see Typhoeus::Request#initialize)
|
|
54
|
+
#
|
|
55
|
+
# @note (see Typhoeus::Request#initialize)
|
|
56
|
+
def put(url, options = {})
|
|
57
|
+
Request.run(url, options.merge(:method => :put))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Make a delete request.
|
|
61
|
+
#
|
|
62
|
+
# @example Make delete request.
|
|
63
|
+
# Typhoeus.delete("www.example.com")
|
|
64
|
+
#
|
|
65
|
+
# @param (see Typhoeus::Request#initialize)
|
|
66
|
+
#
|
|
67
|
+
# @option (see Typhoeus::Request#initialize)
|
|
68
|
+
#
|
|
69
|
+
# @return (see Typhoeus::Request#initialize)
|
|
70
|
+
#
|
|
71
|
+
# @note (see Typhoeus::Request#initialize)
|
|
72
|
+
def delete(url, options = {})
|
|
73
|
+
Request.run(url, options.merge(:method => :delete))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Make a head request.
|
|
77
|
+
#
|
|
78
|
+
# @example Make head request.
|
|
79
|
+
# Typhoeus.head("www.example.com")
|
|
80
|
+
#
|
|
81
|
+
# @param (see Typhoeus::Request#initialize)
|
|
82
|
+
#
|
|
83
|
+
# @option (see Typhoeus::Request#initialize)
|
|
84
|
+
#
|
|
85
|
+
# @return (see Typhoeus::Request#initialize)
|
|
86
|
+
#
|
|
87
|
+
# @note (see Typhoeus::Request#initialize)
|
|
88
|
+
def head(url, options = {})
|
|
89
|
+
Request.run(url, options.merge(:method => :head))
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Make a patch request.
|
|
93
|
+
#
|
|
94
|
+
# @example Make patch request.
|
|
95
|
+
# Typhoeus.patch("www.example.com")
|
|
96
|
+
#
|
|
97
|
+
# @param (see Typhoeus::Request#initialize)
|
|
98
|
+
#
|
|
99
|
+
# @option (see Typhoeus::Request#initialize)
|
|
100
|
+
#
|
|
101
|
+
# @return (see Typhoeus::Request#initialize)
|
|
102
|
+
#
|
|
103
|
+
# @note (see Typhoeus::Request#initialize)
|
|
104
|
+
def patch(url, options = {})
|
|
105
|
+
Request.run(url, options.merge(:method => :patch))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Make a options request.
|
|
109
|
+
#
|
|
110
|
+
# @example Make options request.
|
|
111
|
+
# Typhoeus.options("www.example.com")
|
|
112
|
+
#
|
|
113
|
+
# @param (see Typhoeus::Request#initialize)
|
|
114
|
+
#
|
|
115
|
+
# @option (see Typhoeus::Request#initialize)
|
|
116
|
+
#
|
|
117
|
+
# @return (see Typhoeus::Request#initialize)
|
|
118
|
+
#
|
|
119
|
+
# @note (see Typhoeus::Request#initialize)
|
|
120
|
+
def options(url, options = {})
|
|
121
|
+
Request.run(url, options.merge(:method => :options))
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
class Request
|
|
3
|
+
|
|
4
|
+
# This module provides a way to hook into before
|
|
5
|
+
# a request runs. This is very powerful
|
|
6
|
+
# and you should be careful because when you accidently
|
|
7
|
+
# return a falsy value the request won't be executed.
|
|
8
|
+
#
|
|
9
|
+
# @api private
|
|
10
|
+
module Before
|
|
11
|
+
|
|
12
|
+
# Overrride run in order to execute callbacks in
|
|
13
|
+
# Typhoeus.before. Will break and return when a
|
|
14
|
+
# callback returns nil or false. Calls super
|
|
15
|
+
# otherwise.
|
|
16
|
+
#
|
|
17
|
+
# @example Run the request.
|
|
18
|
+
# request.run
|
|
19
|
+
def run
|
|
20
|
+
Typhoeus.before.each do |callback|
|
|
21
|
+
value = callback.call(self)
|
|
22
|
+
if value.nil? || value == false || value.is_a?(Response)
|
|
23
|
+
return value
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
class Request
|
|
3
|
+
|
|
4
|
+
# This module handles the blocked connection request mode on
|
|
5
|
+
# the request side, where only stubbed requests
|
|
6
|
+
# are allowed.
|
|
7
|
+
# Connection blocking needs to be turned on:
|
|
8
|
+
# Typhoeus.configure do |config|
|
|
9
|
+
# config.block_connection = true
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# When trying to do real requests a NoStub error
|
|
13
|
+
# is raised.
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
module BlockConnection
|
|
17
|
+
|
|
18
|
+
# Overrides run in order to check before if block connection
|
|
19
|
+
# is turned on. If thats the case a NoStub error is
|
|
20
|
+
# raised.
|
|
21
|
+
#
|
|
22
|
+
# @example Run request.
|
|
23
|
+
# request.run
|
|
24
|
+
#
|
|
25
|
+
# @raise [Typhoeus::Errors::NoStub] If connection is blocked
|
|
26
|
+
# and no stub defined.
|
|
27
|
+
def run
|
|
28
|
+
if blocked?
|
|
29
|
+
raise Typhoeus::Errors::NoStub.new(self)
|
|
30
|
+
else
|
|
31
|
+
super
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Returns wether a request is blocked or not. Takes
|
|
36
|
+
# request.block_connection and Typhoeus::Config.block_connection
|
|
37
|
+
# into consideration.
|
|
38
|
+
#
|
|
39
|
+
# @example Blocked?
|
|
40
|
+
# request.blocked?
|
|
41
|
+
#
|
|
42
|
+
# @return [ Boolean ] True if blocked, false else.
|
|
43
|
+
def blocked?
|
|
44
|
+
if block_connection.nil?
|
|
45
|
+
Typhoeus::Config.block_connection
|
|
46
|
+
else
|
|
47
|
+
block_connection
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
class Request
|
|
3
|
+
|
|
4
|
+
# This module contains the logic for the response callbacks.
|
|
5
|
+
# The on_complete callback is the only one at the moment.
|
|
6
|
+
#
|
|
7
|
+
# You can set multiple callbacks, which are then executed
|
|
8
|
+
# in the same order.
|
|
9
|
+
#
|
|
10
|
+
# request.on_complete { |response| p 1 }
|
|
11
|
+
# request.on_complete { |response| p 2 }
|
|
12
|
+
# request.execute_callbacks
|
|
13
|
+
# #=> 1
|
|
14
|
+
# #=> 2
|
|
15
|
+
#
|
|
16
|
+
# You can clear the callbacks:
|
|
17
|
+
#
|
|
18
|
+
# request.on_complete { |response| p 1 }
|
|
19
|
+
# request.on_complete { |response| p 2 }
|
|
20
|
+
# request.on_complete.clear
|
|
21
|
+
# request.execute_callbacks
|
|
22
|
+
# #=> []
|
|
23
|
+
module Callbacks
|
|
24
|
+
|
|
25
|
+
module Types # :nodoc:
|
|
26
|
+
# Set on_complete callback.
|
|
27
|
+
#
|
|
28
|
+
# @example Set on_complete.
|
|
29
|
+
# request.on_complete { |response| p "yay" }
|
|
30
|
+
#
|
|
31
|
+
# @param [ Block ] block The block to execute.
|
|
32
|
+
#
|
|
33
|
+
# @yield [ Typhoeus::Response ]
|
|
34
|
+
#
|
|
35
|
+
# @return [ Array<Block> ] All on_complete blocks.
|
|
36
|
+
def on_complete(&block)
|
|
37
|
+
@on_complete ||= []
|
|
38
|
+
@on_complete << block if block_given?
|
|
39
|
+
@on_complete
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Set on_success callback.
|
|
43
|
+
#
|
|
44
|
+
# @example Set on_success.
|
|
45
|
+
# request.on_success { |response| p "yay" }
|
|
46
|
+
#
|
|
47
|
+
# @param [ Block ] block The block to execute.
|
|
48
|
+
#
|
|
49
|
+
# @yield [ Typhoeus::Response ]
|
|
50
|
+
#
|
|
51
|
+
# @return [ Array<Block> ] All on_success blocks.
|
|
52
|
+
def on_success(&block)
|
|
53
|
+
@on_success ||= []
|
|
54
|
+
@on_success << block if block_given?
|
|
55
|
+
@on_success
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Set on_failure callback.
|
|
59
|
+
#
|
|
60
|
+
# @example Set on_failure.
|
|
61
|
+
# request.on_failure { |response| p "yay" }
|
|
62
|
+
#
|
|
63
|
+
# @param [ Block ] block The block to execute.
|
|
64
|
+
#
|
|
65
|
+
# @yield [ Typhoeus::Response ]
|
|
66
|
+
#
|
|
67
|
+
# @return [ Array<Block> ] All on_failure blocks.
|
|
68
|
+
def on_failure(&block)
|
|
69
|
+
@on_failure ||= []
|
|
70
|
+
@on_failure << block if block_given?
|
|
71
|
+
@on_failure
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Execute nessecary callback and yields response. This
|
|
76
|
+
# include in every case on_complete, on_success if
|
|
77
|
+
# successful and on_failure if not.
|
|
78
|
+
#
|
|
79
|
+
# @example Execute callbacks.
|
|
80
|
+
# request.execute_callbacks
|
|
81
|
+
#
|
|
82
|
+
# @return [ void ]
|
|
83
|
+
#
|
|
84
|
+
# @api private
|
|
85
|
+
def execute_callbacks
|
|
86
|
+
callbacks = Typhoeus.on_complete + on_complete
|
|
87
|
+
|
|
88
|
+
if response && response.success?
|
|
89
|
+
callbacks += Typhoeus.on_success + on_success
|
|
90
|
+
elsif response
|
|
91
|
+
callbacks += Typhoeus.on_failure + on_failure
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
callbacks.map{ |callback| callback.call(self.response) }
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
class Request
|
|
3
|
+
|
|
4
|
+
# This module contains custom serializer.
|
|
5
|
+
module Marshal
|
|
6
|
+
|
|
7
|
+
# Return the important data needed to serialize this Request, except the
|
|
8
|
+
# `on_complete` handler, since they cannot be marshalled.
|
|
9
|
+
def marshal_dump
|
|
10
|
+
(instance_variables - ['@on_complete', :@on_complete]).map do |name|
|
|
11
|
+
[name, instance_variable_get(name)]
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Load.
|
|
16
|
+
def marshal_load(attributes)
|
|
17
|
+
attributes.each { |name, value| instance_variable_set(name, value) }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
class Request
|
|
3
|
+
|
|
4
|
+
# This module handles the GET request memoization
|
|
5
|
+
# on the request side. Memoization needs to be turned
|
|
6
|
+
# on:
|
|
7
|
+
# Typhoeus.configure do |config|
|
|
8
|
+
# config.memoize = true
|
|
9
|
+
# end
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
module Memoizable
|
|
13
|
+
|
|
14
|
+
# Override response setter and memoizes response
|
|
15
|
+
# if the request is memoizable.
|
|
16
|
+
#
|
|
17
|
+
# @param [ Response ] response The response to set.
|
|
18
|
+
#
|
|
19
|
+
# @example Set response.
|
|
20
|
+
# request.response = response
|
|
21
|
+
def response=(response)
|
|
22
|
+
hydra.memory[self] = response if memoizable?
|
|
23
|
+
super
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Return whether a request is memoizable.
|
|
27
|
+
#
|
|
28
|
+
# @example Is request memoizable?
|
|
29
|
+
# request.memoizable?
|
|
30
|
+
#
|
|
31
|
+
# @return [ Boolean ] Return true if memoizable, false else.
|
|
32
|
+
def memoizable?
|
|
33
|
+
Typhoeus::Config.memoize &&
|
|
34
|
+
(options[:method].nil? || options[:method] == :get)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|