typhoeus 0.1.6 → 0.2.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.
- data/.gitignore +3 -0
- data/CHANGELOG.markdown +31 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +30 -0
- data/README.textile +333 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/benchmarks/profile.rb +25 -0
- data/benchmarks/vs_nethttp.rb +35 -0
- data/examples/twitter.rb +21 -0
- data/ext/typhoeus/.gitignore +6 -0
- data/ext/typhoeus/extconf.rb +3 -2
- data/ext/typhoeus/native.h +7 -0
- data/ext/typhoeus/typhoeus_multi.c +1 -2
- data/lib/typhoeus/.gitignore +1 -0
- data/lib/typhoeus/easy.rb +172 -42
- data/lib/typhoeus/hydra/callbacks.rb +24 -0
- data/lib/typhoeus/hydra/connect_options.rb +45 -0
- data/lib/typhoeus/hydra/stubbing.rb +52 -0
- data/lib/typhoeus/hydra.rb +85 -59
- data/lib/typhoeus/hydra_mock.rb +131 -0
- data/lib/typhoeus/multi.rb +4 -3
- data/lib/typhoeus/normalized_header_hash.rb +58 -0
- data/lib/typhoeus/remote_proxy_object.rb +6 -6
- data/lib/typhoeus/request.rb +118 -31
- data/lib/typhoeus/response.rb +61 -4
- data/lib/typhoeus/service.rb +20 -0
- data/lib/typhoeus/utils.rb +24 -0
- data/lib/typhoeus.rb +11 -8
- data/profilers/valgrind.rb +24 -0
- data/spec/fixtures/result_set.xml +60 -0
- data/spec/servers/app.rb +48 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/typhoeus/easy_spec.rb +126 -4
- data/spec/typhoeus/hydra_mock_spec.rb +300 -0
- data/spec/typhoeus/hydra_spec.rb +456 -0
- data/spec/typhoeus/normalized_header_hash_spec.rb +41 -0
- data/spec/typhoeus/remote_spec.rb +2 -2
- data/spec/typhoeus/request_spec.rb +247 -0
- data/spec/typhoeus/response_spec.rb +104 -1
- data/spec/typhoeus/utils_spec.rb +22 -0
- data/typhoeus.gemspec +123 -0
- metadata +145 -34
- data/ext/typhoeus/Makefile +0 -157
data/lib/typhoeus/easy.rb
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
module Typhoeus
|
|
2
2
|
class Easy
|
|
3
|
-
attr_reader :response_body, :response_header, :method, :headers, :url
|
|
3
|
+
attr_reader :response_body, :response_header, :method, :headers, :url, :params
|
|
4
4
|
attr_accessor :start_time
|
|
5
5
|
|
|
6
|
+
# These integer codes are available in curl/curl.h
|
|
6
7
|
CURLINFO_STRING = 1048576
|
|
7
8
|
OPTION_VALUES = {
|
|
8
9
|
:CURLOPT_URL => 10002,
|
|
@@ -11,36 +12,89 @@ module Typhoeus
|
|
|
11
12
|
:CURLOPT_UPLOAD => 46,
|
|
12
13
|
:CURLOPT_CUSTOMREQUEST => 10036,
|
|
13
14
|
:CURLOPT_POSTFIELDS => 10015,
|
|
15
|
+
:CURLOPT_COPYPOSTFIELDS => 10165,
|
|
14
16
|
:CURLOPT_POSTFIELDSIZE => 60,
|
|
15
17
|
:CURLOPT_USERAGENT => 10018,
|
|
16
18
|
:CURLOPT_TIMEOUT_MS => 155,
|
|
19
|
+
# Time-out connect operations after this amount of milliseconds.
|
|
20
|
+
# [Only works on unix-style/SIGALRM operating systems. IOW, does
|
|
21
|
+
# not work on Windows.
|
|
22
|
+
:CURLOPT_CONNECTTIMEOUT_MS => 156,
|
|
17
23
|
:CURLOPT_NOSIGNAL => 99,
|
|
18
24
|
:CURLOPT_HTTPHEADER => 10023,
|
|
19
|
-
:CURLOPT_FOLLOWLOCATION => 52
|
|
25
|
+
:CURLOPT_FOLLOWLOCATION => 52,
|
|
26
|
+
:CURLOPT_MAXREDIRS => 68,
|
|
27
|
+
:CURLOPT_HTTPAUTH => 107,
|
|
28
|
+
:CURLOPT_USERPWD => 10000 + 5,
|
|
29
|
+
:CURLOPT_VERBOSE => 41,
|
|
30
|
+
:CURLOPT_PROXY => 10004,
|
|
31
|
+
:CURLOPT_VERIFYPEER => 64,
|
|
32
|
+
:CURLOPT_NOBODY => 44,
|
|
33
|
+
:CURLOPT_ENCODING => 10000 + 102,
|
|
34
|
+
:CURLOPT_SSLCERT => 10025,
|
|
35
|
+
:CURLOPT_SSLCERTTYPE => 10086,
|
|
36
|
+
:CURLOPT_SSLKEY => 10087,
|
|
37
|
+
:CURLOPT_SSLKEYTYPE => 10088,
|
|
38
|
+
:CURLOPT_KEYPASSWD => 10026,
|
|
39
|
+
:CURLOPT_CAINFO => 10065,
|
|
40
|
+
:CURLOPT_CAPATH => 10097
|
|
20
41
|
}
|
|
21
42
|
INFO_VALUES = {
|
|
22
43
|
:CURLINFO_RESPONSE_CODE => 2097154,
|
|
23
|
-
:CURLINFO_TOTAL_TIME => 3145731
|
|
44
|
+
:CURLINFO_TOTAL_TIME => 3145731,
|
|
45
|
+
:CURLINFO_HTTPAUTH_AVAIL => 0x200000 + 23,
|
|
46
|
+
:CURLINFO_EFFECTIVE_URL => 0x100000 + 1
|
|
24
47
|
}
|
|
25
|
-
|
|
48
|
+
AUTH_TYPES = {
|
|
49
|
+
:CURLAUTH_BASIC => 1,
|
|
50
|
+
:CURLAUTH_DIGEST => 2,
|
|
51
|
+
:CURLAUTH_GSSNEGOTIATE => 4,
|
|
52
|
+
:CURLAUTH_NTLM => 8,
|
|
53
|
+
:CURLAUTH_DIGEST_IE => 16,
|
|
54
|
+
:CURLAUTH_AUTO => 16 | 8 | 4 | 2 | 1
|
|
55
|
+
}
|
|
56
|
+
|
|
26
57
|
def initialize
|
|
27
58
|
@method = :get
|
|
28
|
-
@post_dat_set = nil
|
|
29
59
|
@headers = {}
|
|
60
|
+
|
|
61
|
+
# Enable encoding/compression support
|
|
62
|
+
set_option(OPTION_VALUES[:CURLOPT_ENCODING], '')
|
|
30
63
|
end
|
|
31
|
-
|
|
64
|
+
|
|
32
65
|
def headers=(hash)
|
|
33
66
|
@headers = hash
|
|
34
67
|
end
|
|
35
|
-
|
|
68
|
+
|
|
69
|
+
def proxy=(proxy)
|
|
70
|
+
set_option(OPTION_VALUES[:CURLOPT_PROXY], proxy)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def auth=(authinfo)
|
|
74
|
+
set_option(OPTION_VALUES[:CURLOPT_USERPWD], "#{authinfo[:username]}:#{authinfo[:password]}")
|
|
75
|
+
set_option(OPTION_VALUES[:CURLOPT_HTTPAUTH], authinfo[:method]) if authinfo[:method]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def auth_methods
|
|
79
|
+
get_info_long(INFO_VALUES[:CURLINFO_HTTPAUTH_AVAIL])
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def verbose=(boolean)
|
|
83
|
+
set_option(OPTION_VALUES[:CURLOPT_VERBOSE], !!boolean ? 1 : 0)
|
|
84
|
+
end
|
|
85
|
+
|
|
36
86
|
def total_time_taken
|
|
37
87
|
get_info_double(INFO_VALUES[:CURLINFO_TOTAL_TIME])
|
|
38
88
|
end
|
|
39
|
-
|
|
89
|
+
|
|
90
|
+
def effective_url
|
|
91
|
+
get_info_string(INFO_VALUES[:CURLINFO_EFFECTIVE_URL])
|
|
92
|
+
end
|
|
93
|
+
|
|
40
94
|
def response_code
|
|
41
95
|
get_info_long(INFO_VALUES[:CURLINFO_RESPONSE_CODE])
|
|
42
96
|
end
|
|
43
|
-
|
|
97
|
+
|
|
44
98
|
def follow_location=(boolean)
|
|
45
99
|
if boolean
|
|
46
100
|
set_option(OPTION_VALUES[:CURLOPT_FOLLOWLOCATION], 1)
|
|
@@ -48,17 +102,31 @@ module Typhoeus
|
|
|
48
102
|
set_option(OPTION_VALUES[:CURLOPT_FOLLOWLOCATION], 0)
|
|
49
103
|
end
|
|
50
104
|
end
|
|
105
|
+
|
|
106
|
+
def max_redirects=(redirects)
|
|
107
|
+
set_option(OPTION_VALUES[:CURLOPT_MAXREDIRS], redirects)
|
|
108
|
+
end
|
|
51
109
|
|
|
110
|
+
def connect_timeout=(milliseconds)
|
|
111
|
+
@connect_timeout = milliseconds
|
|
112
|
+
set_option(OPTION_VALUES[:CURLOPT_NOSIGNAL], 1)
|
|
113
|
+
set_option(OPTION_VALUES[:CURLOPT_CONNECTTIMEOUT_MS], milliseconds)
|
|
114
|
+
end
|
|
115
|
+
|
|
52
116
|
def timeout=(milliseconds)
|
|
53
117
|
@timeout = milliseconds
|
|
54
118
|
set_option(OPTION_VALUES[:CURLOPT_NOSIGNAL], 1)
|
|
55
119
|
set_option(OPTION_VALUES[:CURLOPT_TIMEOUT_MS], milliseconds)
|
|
56
120
|
end
|
|
57
|
-
|
|
121
|
+
|
|
58
122
|
def timed_out?
|
|
59
123
|
@timeout && total_time_taken > @timeout && response_code == 0
|
|
60
124
|
end
|
|
61
|
-
|
|
125
|
+
|
|
126
|
+
def supports_zlib?
|
|
127
|
+
!!(curl_version.match(/zlib/))
|
|
128
|
+
end
|
|
129
|
+
|
|
62
130
|
def request_body=(request_body)
|
|
63
131
|
@request_body = request_body
|
|
64
132
|
if @method == :put
|
|
@@ -69,16 +137,20 @@ module Typhoeus
|
|
|
69
137
|
self.post_data = request_body
|
|
70
138
|
end
|
|
71
139
|
end
|
|
72
|
-
|
|
140
|
+
|
|
73
141
|
def user_agent=(user_agent)
|
|
74
142
|
set_option(OPTION_VALUES[:CURLOPT_USERAGENT], user_agent)
|
|
75
143
|
end
|
|
76
|
-
|
|
144
|
+
|
|
77
145
|
def url=(url)
|
|
78
146
|
@url = url
|
|
79
147
|
set_option(OPTION_VALUES[:CURLOPT_URL], url)
|
|
80
148
|
end
|
|
81
|
-
|
|
149
|
+
|
|
150
|
+
def disable_ssl_peer_verification
|
|
151
|
+
set_option(OPTION_VALUES[:CURLOPT_VERIFYPEER], 0)
|
|
152
|
+
end
|
|
153
|
+
|
|
82
154
|
def method=(method)
|
|
83
155
|
@method = method
|
|
84
156
|
if method == :get
|
|
@@ -89,80 +161,137 @@ module Typhoeus
|
|
|
89
161
|
elsif method == :put
|
|
90
162
|
set_option(OPTION_VALUES[:CURLOPT_UPLOAD], 1)
|
|
91
163
|
self.request_body = "" unless @request_body
|
|
164
|
+
elsif method == :head
|
|
165
|
+
set_option(OPTION_VALUES[:CURLOPT_NOBODY], 1)
|
|
92
166
|
else
|
|
93
|
-
set_option(OPTION_VALUES[:CURLOPT_CUSTOMREQUEST],
|
|
167
|
+
set_option(OPTION_VALUES[:CURLOPT_CUSTOMREQUEST], method.to_s.upcase)
|
|
94
168
|
end
|
|
95
169
|
end
|
|
96
|
-
|
|
170
|
+
|
|
97
171
|
def post_data=(data)
|
|
98
172
|
@post_data_set = true
|
|
99
|
-
set_option(OPTION_VALUES[:CURLOPT_POSTFIELDS], data)
|
|
100
173
|
set_option(OPTION_VALUES[:CURLOPT_POSTFIELDSIZE], data.length)
|
|
174
|
+
set_option(OPTION_VALUES[:CURLOPT_COPYPOSTFIELDS], data)
|
|
101
175
|
end
|
|
102
|
-
|
|
176
|
+
|
|
103
177
|
def params=(params)
|
|
178
|
+
@params = params
|
|
104
179
|
params_string = params.keys.collect do |k|
|
|
105
180
|
value = params[k]
|
|
106
181
|
if value.is_a? Hash
|
|
107
|
-
value.keys.collect {|sk|
|
|
182
|
+
value.keys.collect {|sk| Typhoeus::Utils.escape("#{k}[#{sk}]") + "=" + Typhoeus::Utils.escape(value[sk].to_s)}
|
|
108
183
|
elsif value.is_a? Array
|
|
109
|
-
key =
|
|
110
|
-
value.collect { |v| "#{key}=#{
|
|
184
|
+
key = Typhoeus::Utils.escape(k.to_s)
|
|
185
|
+
value.collect { |v| "#{key}=#{Typhoeus::Utils.escape(v.to_s)}" }.join('&')
|
|
111
186
|
else
|
|
112
|
-
"#{
|
|
187
|
+
"#{Typhoeus::Utils.escape(k.to_s)}=#{Typhoeus::Utils.escape(params[k].to_s)}"
|
|
113
188
|
end
|
|
114
189
|
end.flatten.join("&")
|
|
115
|
-
|
|
190
|
+
|
|
116
191
|
if method == :post
|
|
117
192
|
self.post_data = params_string
|
|
118
193
|
else
|
|
119
194
|
self.url = "#{url}?#{params_string}"
|
|
120
195
|
end
|
|
121
196
|
end
|
|
122
|
-
|
|
197
|
+
|
|
198
|
+
# Set SSL certificate
|
|
199
|
+
# " The string should be the file name of your certificate. "
|
|
200
|
+
# The default format is "PEM" and can be changed with ssl_cert_type=
|
|
201
|
+
def ssl_cert=(cert)
|
|
202
|
+
set_option(OPTION_VALUES[:CURLOPT_SSLCERT], cert)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Set SSL certificate type
|
|
206
|
+
# " The string should be the format of your certificate. Supported formats are "PEM" and "DER" "
|
|
207
|
+
def ssl_cert_type=(cert_type)
|
|
208
|
+
raise "Invalid ssl cert type : '#{cert_type}'..." if cert_type and !%w(PEM DER).include?(cert_type)
|
|
209
|
+
set_option(OPTION_VALUES[:CURLOPT_SSLCERTTYPE], cert_type)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Set SSL Key file
|
|
213
|
+
# " The string should be the file name of your private key. "
|
|
214
|
+
# The default format is "PEM" and can be changed with ssl_key_type=
|
|
215
|
+
#
|
|
216
|
+
def ssl_key=(key)
|
|
217
|
+
set_option(OPTION_VALUES[:CURLOPT_SSLKEY], key)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Set SSL Key type
|
|
221
|
+
# " The string should be the format of your private key. Supported formats are "PEM", "DER" and "ENG". "
|
|
222
|
+
#
|
|
223
|
+
def ssl_key_type=(key_type)
|
|
224
|
+
raise "Invalid ssl key type : '#{key_type}'..." if key_type and !%w(PEM DER ENG).include?(key_type)
|
|
225
|
+
set_option(OPTION_VALUES[:CURLOPT_SSLKEYTYPE], key_type)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def ssl_key_password=(key_password)
|
|
229
|
+
set_option(OPTION_VALUES[:CURLOPT_KEYPASSWD], key_password)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Set SSL CACERT
|
|
233
|
+
# " File holding one or more certificates to verify the peer with. "
|
|
234
|
+
#
|
|
235
|
+
def ssl_cacert=(cacert)
|
|
236
|
+
set_option(OPTION_VALUES[:CURLOPT_CAINFO], cacert)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Set CAPATH
|
|
240
|
+
# " directory holding multiple CA certificates to verify the peer with. The certificate directory must be prepared using the openssl c_rehash utility. "
|
|
241
|
+
#
|
|
242
|
+
def ssl_capath=(capath)
|
|
243
|
+
set_option(OPTION_VALUES[:CURLOPT_CAPATH], capath)
|
|
244
|
+
end
|
|
245
|
+
|
|
123
246
|
def set_option(option, value)
|
|
124
247
|
if value.class == String
|
|
125
248
|
easy_setopt_string(option, value)
|
|
126
|
-
|
|
249
|
+
elsif value
|
|
127
250
|
easy_setopt_long(option, value)
|
|
128
251
|
end
|
|
129
252
|
end
|
|
130
|
-
|
|
253
|
+
|
|
131
254
|
def perform
|
|
132
255
|
set_headers()
|
|
133
256
|
easy_perform()
|
|
134
|
-
response_code()
|
|
257
|
+
resp_code = response_code()
|
|
258
|
+
if resp_code >= 200 && resp_code <= 299
|
|
259
|
+
success
|
|
260
|
+
else
|
|
261
|
+
failure
|
|
262
|
+
end
|
|
263
|
+
resp_code
|
|
135
264
|
end
|
|
136
|
-
|
|
265
|
+
|
|
137
266
|
def set_headers
|
|
138
267
|
headers.each_pair do |key, value|
|
|
139
268
|
easy_add_header("#{key}: #{value}")
|
|
140
269
|
end
|
|
141
270
|
easy_set_headers() unless headers.empty?
|
|
142
271
|
end
|
|
143
|
-
|
|
272
|
+
|
|
144
273
|
# gets called when finished and response code is 200-299
|
|
145
274
|
def success
|
|
146
275
|
@success.call(self) if @success
|
|
147
276
|
end
|
|
148
|
-
|
|
277
|
+
|
|
149
278
|
def on_success(&block)
|
|
150
279
|
@success = block
|
|
151
280
|
end
|
|
152
|
-
|
|
281
|
+
|
|
153
282
|
def on_success=(block)
|
|
154
283
|
@success = block
|
|
155
284
|
end
|
|
156
|
-
|
|
285
|
+
|
|
157
286
|
# gets called when finished and response code is 300-599
|
|
158
287
|
def failure
|
|
159
288
|
@failure.call(self) if @failure
|
|
160
289
|
end
|
|
161
|
-
|
|
290
|
+
|
|
162
291
|
def on_failure(&block)
|
|
163
292
|
@failure = block
|
|
164
293
|
end
|
|
165
|
-
|
|
294
|
+
|
|
166
295
|
def on_failure=(block)
|
|
167
296
|
@failure = block
|
|
168
297
|
end
|
|
@@ -170,20 +299,20 @@ module Typhoeus
|
|
|
170
299
|
def retries
|
|
171
300
|
@retries ||= 0
|
|
172
301
|
end
|
|
173
|
-
|
|
302
|
+
|
|
174
303
|
def increment_retries
|
|
175
304
|
@retries ||= 0
|
|
176
305
|
@retries += 1
|
|
177
306
|
end
|
|
178
|
-
|
|
307
|
+
|
|
179
308
|
def max_retries
|
|
180
309
|
@max_retries ||= 40
|
|
181
310
|
end
|
|
182
|
-
|
|
311
|
+
|
|
183
312
|
def max_retries?
|
|
184
313
|
retries >= max_retries
|
|
185
314
|
end
|
|
186
|
-
|
|
315
|
+
|
|
187
316
|
def reset
|
|
188
317
|
@retries = 0
|
|
189
318
|
@response_code = 0
|
|
@@ -191,21 +320,22 @@ module Typhoeus
|
|
|
191
320
|
@response_body = ""
|
|
192
321
|
easy_reset()
|
|
193
322
|
end
|
|
194
|
-
|
|
323
|
+
|
|
195
324
|
def get_info_string(option)
|
|
196
325
|
easy_getinfo_string(option)
|
|
197
326
|
end
|
|
198
|
-
|
|
327
|
+
|
|
199
328
|
def get_info_long(option)
|
|
200
329
|
easy_getinfo_long(option)
|
|
201
330
|
end
|
|
202
|
-
|
|
331
|
+
|
|
203
332
|
def get_info_double(option)
|
|
204
333
|
easy_getinfo_double(option)
|
|
205
334
|
end
|
|
206
|
-
|
|
335
|
+
|
|
207
336
|
def curl_version
|
|
208
337
|
version
|
|
209
338
|
end
|
|
339
|
+
|
|
210
340
|
end
|
|
211
341
|
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,45 @@
|
|
|
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
|
+
if !Typhoeus::Hydra.allow_net_connect? and (!Typhoeus::Hydra.ignore_localhost? or !request.localhost?)
|
|
16
|
+
raise NetConnectNotAllowedError, "Real HTTP requests are not allowed. Unregistered request: #{request.inspect}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
private :check_allow_net_connect!
|
|
20
|
+
|
|
21
|
+
module ClassMethods
|
|
22
|
+
def self.extended(base)
|
|
23
|
+
class << base
|
|
24
|
+
attr_accessor :allow_net_connect
|
|
25
|
+
attr_accessor :ignore_localhost
|
|
26
|
+
end
|
|
27
|
+
base.allow_net_connect = true
|
|
28
|
+
base.ignore_localhost = false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Returns whether we allow external HTTP connections.
|
|
32
|
+
# Useful for mocking/tests.
|
|
33
|
+
#
|
|
34
|
+
# @return [boolean] true/false
|
|
35
|
+
def allow_net_connect?
|
|
36
|
+
allow_net_connect
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def ignore_localhost?
|
|
40
|
+
ignore_localhost
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
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 find_stub_from_request(request)
|
|
15
|
+
stubs.detect { |stub| stub.matches?(request) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.extended(base)
|
|
19
|
+
class << base
|
|
20
|
+
attr_accessor :stubs
|
|
21
|
+
end
|
|
22
|
+
base.stubs = []
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.included(base)
|
|
27
|
+
base.extend(SharedMethods)
|
|
28
|
+
base.class_eval do
|
|
29
|
+
attr_accessor :stubs
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def assign_to_stub(request)
|
|
34
|
+
m = find_stub_from_request(request)
|
|
35
|
+
|
|
36
|
+
# Fallback to global stubs.
|
|
37
|
+
m ||= self.class.find_stub_from_request(request)
|
|
38
|
+
|
|
39
|
+
if m
|
|
40
|
+
m.add_request(request)
|
|
41
|
+
@active_stubs << m
|
|
42
|
+
m
|
|
43
|
+
else
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
private :assign_to_stub
|
|
48
|
+
|
|
49
|
+
include SharedMethods
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|