typhoeus 0.4.2 → 0.5.0.pre
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 +74 -28
- data/README.md +20 -422
- data/Rakefile +21 -12
- data/lib/typhoeus/config.rb +11 -0
- data/lib/typhoeus/hydra.rb +26 -236
- 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/request.rb +56 -241
- data/lib/typhoeus/requests/actions.rb +17 -0
- data/lib/typhoeus/requests/callbacks.rb +48 -0
- data/lib/typhoeus/requests/marshal.rb +21 -0
- data/lib/typhoeus/requests/memoizable.rb +36 -0
- data/lib/typhoeus/requests/operations.rb +51 -0
- data/lib/typhoeus/requests/responseable.rb +29 -0
- data/lib/typhoeus/response.rb +23 -118
- data/lib/typhoeus/responses/header.rb +50 -0
- data/lib/typhoeus/responses/informations.rb +43 -0
- data/lib/typhoeus/responses/legacy.rb +26 -0
- data/lib/typhoeus/responses/status.rb +77 -0
- data/lib/typhoeus/version.rb +3 -1
- data/lib/typhoeus.rb +31 -45
- metadata +45 -48
- 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/request.rb
CHANGED
|
@@ -1,266 +1,81 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'typhoeus/requests/callbacks'
|
|
2
|
+
require 'typhoeus/requests/actions'
|
|
3
|
+
require 'typhoeus/requests/operations'
|
|
4
|
+
require 'typhoeus/requests/marshal'
|
|
5
|
+
require 'typhoeus/requests/responseable'
|
|
6
|
+
require 'typhoeus/requests/memoizable'
|
|
2
7
|
|
|
3
8
|
module Typhoeus
|
|
9
|
+
|
|
10
|
+
# This class represents a request.
|
|
4
11
|
class Request
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
:connect_timeout,
|
|
12
|
-
:timeout,
|
|
13
|
-
:user_agent,
|
|
14
|
-
:response,
|
|
15
|
-
:cache_timeout,
|
|
16
|
-
:follow_location,
|
|
17
|
-
:max_redirects,
|
|
18
|
-
:proxy,
|
|
19
|
-
:proxy_username,
|
|
20
|
-
:proxy_password,
|
|
21
|
-
:disable_ssl_peer_verification,
|
|
22
|
-
:disable_ssl_host_verification,
|
|
23
|
-
:interface,
|
|
24
|
-
:ssl_cert,
|
|
25
|
-
:ssl_cert_type,
|
|
26
|
-
:ssl_key,
|
|
27
|
-
:ssl_key_type,
|
|
28
|
-
:ssl_key_password,
|
|
29
|
-
:ssl_cacert,
|
|
30
|
-
:ssl_capath,
|
|
31
|
-
:ssl_version,
|
|
32
|
-
:verbose,
|
|
33
|
-
:username,
|
|
34
|
-
:password,
|
|
35
|
-
:auth_method,
|
|
36
|
-
:proxy_auth_method,
|
|
37
|
-
:proxy_type
|
|
38
|
-
]
|
|
12
|
+
include Requests::Callbacks
|
|
13
|
+
include Requests::Marshal
|
|
14
|
+
include Requests::Operations
|
|
15
|
+
extend Requests::Actions
|
|
16
|
+
include Requests::Responseable
|
|
17
|
+
include Requests::Memoizable
|
|
39
18
|
|
|
40
|
-
attr_accessor
|
|
19
|
+
attr_accessor :options, :url, :hydra
|
|
41
20
|
|
|
42
|
-
#
|
|
21
|
+
# Create a new request.
|
|
22
|
+
#
|
|
23
|
+
# @example Create a request.
|
|
24
|
+
# Request.new("www.example.com")
|
|
43
25
|
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
# * +options+ : A hash containing options among :
|
|
47
|
-
# ** +:method+ : :get (default) / :post / :put
|
|
48
|
-
# ** +:params+ : params as a Hash
|
|
49
|
-
# ** +:body+
|
|
50
|
-
# ** +:timeout+ : timeout (ms)
|
|
51
|
-
# ** +:interface+ : interface or ip address (string)
|
|
52
|
-
# ** +:connect_timeout+ : connect timeout (ms)
|
|
53
|
-
# ** +:headers+ : headers as Hash
|
|
54
|
-
# ** +:cache_timeout+ : cache timeout (ms)
|
|
55
|
-
# ** +:follow_location
|
|
56
|
-
# ** +:max_redirects
|
|
57
|
-
# ** +:proxy
|
|
58
|
-
# ** +:disable_ssl_peer_verification
|
|
59
|
-
# ** +:disable_ssl_host_verification
|
|
60
|
-
# ** +:ssl_cert
|
|
61
|
-
# ** +:ssl_cert_type
|
|
62
|
-
# ** +:ssl_key
|
|
63
|
-
# ** +:ssl_key_type
|
|
64
|
-
# ** +:ssl_key_password
|
|
65
|
-
# ** +:ssl_cacert
|
|
66
|
-
# ** +:ssl_capath
|
|
67
|
-
# ** +:verbose
|
|
68
|
-
# ** +:username
|
|
69
|
-
# ** +:password
|
|
70
|
-
# ** +:auth_method
|
|
26
|
+
# @param [ String ] url The url to request.
|
|
27
|
+
# @param [ Hash ] options The options.
|
|
71
28
|
#
|
|
29
|
+
# #return [ Request ] The new request.
|
|
72
30
|
def initialize(url, options = {})
|
|
73
31
|
@url = url
|
|
74
|
-
@
|
|
75
|
-
@params = options[:params]
|
|
76
|
-
@body = options[:body]
|
|
77
|
-
@timeout = safe_to_i(options[:timeout])
|
|
78
|
-
@connect_timeout = safe_to_i(options[:connect_timeout])
|
|
79
|
-
@interface = options[:interface]
|
|
80
|
-
@headers = options[:headers] || {}
|
|
81
|
-
|
|
82
|
-
@cache_timeout = safe_to_i(options[:cache_timeout])
|
|
83
|
-
@follow_location = options[:follow_location]
|
|
84
|
-
@max_redirects = options[:max_redirects]
|
|
85
|
-
@proxy = options[:proxy]
|
|
86
|
-
@proxy_type = options[:proxy_type]
|
|
87
|
-
@proxy_username = options[:proxy_username]
|
|
88
|
-
@proxy_password = options[:proxy_password]
|
|
89
|
-
@proxy_auth_method = options[:proxy_auth_method]
|
|
90
|
-
@disable_ssl_peer_verification = options[:disable_ssl_peer_verification]
|
|
91
|
-
@disable_ssl_host_verification = options[:disable_ssl_host_verification]
|
|
92
|
-
@ssl_cert = options[:ssl_cert]
|
|
93
|
-
@ssl_cert_type = options[:ssl_cert_type]
|
|
94
|
-
@ssl_key = options[:ssl_key]
|
|
95
|
-
@ssl_key_type = options[:ssl_key_type]
|
|
96
|
-
@ssl_key_password = options[:ssl_key_password]
|
|
97
|
-
@ssl_cacert = options[:ssl_cacert]
|
|
98
|
-
@ssl_capath = options[:ssl_capath]
|
|
99
|
-
@ssl_version = options[:ssl_version]
|
|
100
|
-
@verbose = options[:verbose]
|
|
101
|
-
@username = options[:username]
|
|
102
|
-
@password = options[:password]
|
|
103
|
-
@auth_method = options[:auth_method]
|
|
104
|
-
|
|
105
|
-
@on_complete = nil
|
|
106
|
-
@after_complete = nil
|
|
107
|
-
@handled_response = nil
|
|
108
|
-
end
|
|
32
|
+
@options = options.dup
|
|
109
33
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def localhost?
|
|
113
|
-
LOCALHOST_ALIASES.include?(parsed_uri.host)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def user_agent
|
|
117
|
-
headers['User-Agent']
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def url
|
|
121
|
-
if [:post, :put].include?(@method)
|
|
122
|
-
@url
|
|
123
|
-
else
|
|
124
|
-
url = "#{@url}?#{params_string}"
|
|
125
|
-
url += "&#{URI.escape(@body)}" if @body
|
|
126
|
-
url.gsub("?&", "?").gsub(/\?$/, '')
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def parsed_uri
|
|
131
|
-
@parsed_uri ||= URI.parse(@url)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def host
|
|
135
|
-
slash_location = @url.index('/', 8)
|
|
136
|
-
if slash_location
|
|
137
|
-
@url.slice(0, slash_location)
|
|
34
|
+
if @options[:headers]
|
|
35
|
+
@options[:headers] = {'User-Agent' => Typhoeus::USER_AGENT}.merge(options[:headers])
|
|
138
36
|
else
|
|
139
|
-
|
|
140
|
-
return query_string_location ? @url.slice(0, query_string_location) : @url
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def host_domain
|
|
145
|
-
parsed_uri.host
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def params_string
|
|
149
|
-
return nil unless params
|
|
150
|
-
traversal = Typhoeus::Utils.traverse_params_hash(params)
|
|
151
|
-
Typhoeus::Utils.traversal_to_param_string(traversal)
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
def on_complete(&block)
|
|
155
|
-
@on_complete = block
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def on_complete=(proc)
|
|
159
|
-
@on_complete = proc
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def after_complete(&block)
|
|
163
|
-
@after_complete = block
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def after_complete=(proc)
|
|
167
|
-
@after_complete = proc
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def call_handlers
|
|
171
|
-
if @on_complete
|
|
172
|
-
@handled_response = @on_complete.call(response)
|
|
173
|
-
call_after_complete
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def call_after_complete
|
|
178
|
-
@after_complete.call(@handled_response) if @after_complete
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def handled_response=(val)
|
|
182
|
-
@handled_response = val
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
def handled_response
|
|
186
|
-
@handled_response || response
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
def inspect
|
|
190
|
-
result = ":method => #{self.method.inspect},\n" <<
|
|
191
|
-
"\t:url => #{URI.parse(self.url).to_s}"
|
|
192
|
-
if self.body and !self.body.empty?
|
|
193
|
-
result << ",\n\t:body => #{self.body.inspect}"
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
if self.params and !self.params.empty?
|
|
197
|
-
result << ",\n\t:params => #{self.params.inspect}"
|
|
37
|
+
@options[:headers] = {'User-Agent' => Typhoeus::USER_AGENT}
|
|
198
38
|
end
|
|
199
|
-
|
|
200
|
-
if self.headers and !self.headers.empty?
|
|
201
|
-
result << ",\n\t:headers => #{self.headers.inspect}"
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
result
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
def cache_key
|
|
208
|
-
Digest::SHA1.hexdigest(cache_key_basis || url)
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
def self.run(url, params)
|
|
212
|
-
r = new(url, params)
|
|
213
|
-
Typhoeus::Hydra.hydra.queue r
|
|
214
|
-
Typhoeus::Hydra.hydra.run
|
|
215
|
-
r.response
|
|
39
|
+
@options[:verbose] = Typhoeus::Config.verbose unless @options[:verbose]
|
|
216
40
|
end
|
|
217
41
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
def
|
|
227
|
-
|
|
42
|
+
# Returns wether other is equal to self.
|
|
43
|
+
#
|
|
44
|
+
# @example Are request equal?
|
|
45
|
+
# request.eql?(other_request)
|
|
46
|
+
#
|
|
47
|
+
# @param [ Object ] other The object to check.
|
|
48
|
+
#
|
|
49
|
+
# @return [ Boolean ] Returns true if equals, else false.
|
|
50
|
+
def eql?(other)
|
|
51
|
+
self.class == other.class &&
|
|
52
|
+
self.url == other.url &&
|
|
53
|
+
fuzzy_hash_eql?(self.options, other.options)
|
|
228
54
|
end
|
|
229
55
|
|
|
230
|
-
|
|
231
|
-
|
|
56
|
+
# Overrides Object#hash.
|
|
57
|
+
#
|
|
58
|
+
# @return [ Integer ] The integer representing the request.
|
|
59
|
+
def hash
|
|
60
|
+
[ self.class, self.url, self.options ].hash
|
|
232
61
|
end
|
|
233
62
|
|
|
234
|
-
|
|
235
|
-
run(url, params.merge(:method => :head))
|
|
236
|
-
end
|
|
63
|
+
protected
|
|
237
64
|
|
|
238
|
-
|
|
65
|
+
# Checks if two hashes are equal or not, discarding first-level hash order
|
|
66
|
+
#
|
|
67
|
+
# @param [ Hash ] hash
|
|
68
|
+
# @param [ Hash ] other hash to check for equality
|
|
69
|
+
#
|
|
70
|
+
# @return [ Boolean ] Returns true if hashes have same values for same keys and same length,
|
|
71
|
+
# even if the keys are given in a different order.
|
|
72
|
+
def fuzzy_hash_eql?(left, right)
|
|
73
|
+
return true if (left == right)
|
|
239
74
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
# marshalled.
|
|
243
|
-
def marshal_dump
|
|
244
|
-
(instance_variables - ['@on_complete', '@after_complete', :@on_complete, :@after_complete]).map do |name|
|
|
245
|
-
[name, instance_variable_get(name)]
|
|
75
|
+
(left.count == right.count) && left.inject(true) do |res, kvp|
|
|
76
|
+
res && (kvp[1] == right[kvp[0]])
|
|
246
77
|
end
|
|
247
78
|
end
|
|
248
79
|
|
|
249
|
-
def marshal_load(attributes)
|
|
250
|
-
attributes.each { |name, value| instance_variable_set(name, value) }
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
def self.options
|
|
254
|
-
ACCESSOR_OPTIONS
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
private
|
|
258
|
-
|
|
259
|
-
def safe_to_i(value)
|
|
260
|
-
return value if value.is_a?(Fixnum)
|
|
261
|
-
return nil if value.nil?
|
|
262
|
-
return nil if value.respond_to?(:empty?) && value.empty?
|
|
263
|
-
value.to_i
|
|
264
|
-
end
|
|
265
80
|
end
|
|
266
81
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
module Requests # :nodoc:
|
|
3
|
+
|
|
4
|
+
# Module containing logic about shortcuts to
|
|
5
|
+
# http methods. Like
|
|
6
|
+
# Typhoeus.get("www.example.com")
|
|
7
|
+
module Actions
|
|
8
|
+
[:get, :post, :put, :delete, :head, :patch, :options].each do |name|
|
|
9
|
+
define_method(name) do |*args|
|
|
10
|
+
url = args[0]
|
|
11
|
+
options = args.fetch(1, {})
|
|
12
|
+
Request.run(url, options.merge(:method => name))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
module Requests
|
|
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 { p 1 }
|
|
11
|
+
# request.on_complete { p 2 }
|
|
12
|
+
# request.complete
|
|
13
|
+
# #=> 1
|
|
14
|
+
# #=> 2
|
|
15
|
+
#
|
|
16
|
+
# You can clear the callbacks:
|
|
17
|
+
#
|
|
18
|
+
# request.on_complete { p 1 }
|
|
19
|
+
# request.on_complete { p 2 }
|
|
20
|
+
# request.on_complete.clear
|
|
21
|
+
# request.on_complete
|
|
22
|
+
# #=> []
|
|
23
|
+
module Callbacks
|
|
24
|
+
|
|
25
|
+
# Set on_complete callback.
|
|
26
|
+
#
|
|
27
|
+
# @example Set on_complete.
|
|
28
|
+
# request.on_complete { p "yay" }
|
|
29
|
+
#
|
|
30
|
+
# @param [ Block ] block The block to execute.
|
|
31
|
+
def on_complete(&block)
|
|
32
|
+
@on_complete ||= []
|
|
33
|
+
@on_complete << block if block_given?
|
|
34
|
+
@on_complete
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Execute on_complete callbacks.
|
|
38
|
+
#
|
|
39
|
+
# @example Execute on_completes.
|
|
40
|
+
# request.complete
|
|
41
|
+
def complete
|
|
42
|
+
if defined?(@on_complete)
|
|
43
|
+
@on_complete.map{ |callback| callback.call(self) }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
module Requests
|
|
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,36 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
module Requests
|
|
3
|
+
|
|
4
|
+
# This module handles the GET request memoization
|
|
5
|
+
# on the request side. Memoization needs to be turned
|
|
6
|
+
# on:
|
|
7
|
+
# Typhoeus.configre do |config|
|
|
8
|
+
# config.memoize = true
|
|
9
|
+
# end
|
|
10
|
+
module Memoizable
|
|
11
|
+
|
|
12
|
+
# Override response setter and memoizes response
|
|
13
|
+
# if the request is memoizable.
|
|
14
|
+
#
|
|
15
|
+
# @param [ Response ] response The response to set.
|
|
16
|
+
#
|
|
17
|
+
# @example Set response.
|
|
18
|
+
# request.response = response
|
|
19
|
+
def response=(response)
|
|
20
|
+
hydra.memory[self] = response if memoizable?
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Return whether a request is memoizable.
|
|
25
|
+
#
|
|
26
|
+
# @example Is request memoizable?
|
|
27
|
+
# request.memoizable?
|
|
28
|
+
#
|
|
29
|
+
# @return [ Boolean ] Return true if memoizable, false else.
|
|
30
|
+
def memoizable?
|
|
31
|
+
Typhoeus::Config.memoize &&
|
|
32
|
+
(options[:method].nil? || options[:method] == :get)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
module Requests
|
|
3
|
+
|
|
4
|
+
# This module contains everything what is necessary
|
|
5
|
+
# to make a single request.
|
|
6
|
+
module Operations
|
|
7
|
+
|
|
8
|
+
# :nodoc:
|
|
9
|
+
def self.included(base)
|
|
10
|
+
base.extend ClassMethods
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module ClassMethods # :nodoc:
|
|
14
|
+
|
|
15
|
+
# Shortcut to perform a single request.
|
|
16
|
+
#
|
|
17
|
+
# @example Perform request.
|
|
18
|
+
# Request.run("www.example.com")
|
|
19
|
+
#
|
|
20
|
+
# @param [ String ] url The url to request.
|
|
21
|
+
# @param [ Hash ] options The options hash.
|
|
22
|
+
#
|
|
23
|
+
# @return [ Response ] The response.
|
|
24
|
+
def run(url, options = {})
|
|
25
|
+
new(url, options).run
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Run a request.
|
|
30
|
+
#
|
|
31
|
+
# @example Run a request.
|
|
32
|
+
# request.run
|
|
33
|
+
#
|
|
34
|
+
# @return [ Response ] The response.
|
|
35
|
+
def run
|
|
36
|
+
easy = Typhoeus.get_easy
|
|
37
|
+
easy.http_request(
|
|
38
|
+
url,
|
|
39
|
+
options.fetch(:method, :get),
|
|
40
|
+
options.reject{|k,_| k==:method}
|
|
41
|
+
)
|
|
42
|
+
easy.prepare
|
|
43
|
+
easy.perform
|
|
44
|
+
@response = Response.new(easy.to_hash)
|
|
45
|
+
Typhoeus.release_easy(easy)
|
|
46
|
+
complete
|
|
47
|
+
@response
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Typhoeus
|
|
2
|
+
module Requests
|
|
3
|
+
|
|
4
|
+
# This module contains logic for having a reponse
|
|
5
|
+
# getter and setter.
|
|
6
|
+
module Responseable
|
|
7
|
+
|
|
8
|
+
# Set the response.
|
|
9
|
+
#
|
|
10
|
+
# @example Set response.
|
|
11
|
+
# request.response = response
|
|
12
|
+
#
|
|
13
|
+
# @param [ Response ] value The response to set.
|
|
14
|
+
def response=(value)
|
|
15
|
+
@response = value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Return the response.
|
|
19
|
+
#
|
|
20
|
+
# @example Return response.
|
|
21
|
+
# request.response
|
|
22
|
+
#
|
|
23
|
+
# @return [ Response ] The response.
|
|
24
|
+
def response
|
|
25
|
+
@response ||= nil
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/typhoeus/response.rb
CHANGED
|
@@ -1,123 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
:requested_url, :requested_remote_method,
|
|
6
|
-
:requested_http_method, :start_time,
|
|
7
|
-
:effective_url, :start_transfer_time,
|
|
8
|
-
:app_connect_time, :pretransfer_time,
|
|
9
|
-
:connect_time, :name_lookup_time,
|
|
10
|
-
:curl_return_code, :curl_error_message,
|
|
11
|
-
:primary_ip, :redirect_count
|
|
12
|
-
|
|
13
|
-
attr_writer :headers_hash
|
|
14
|
-
|
|
15
|
-
def initialize(params = {})
|
|
16
|
-
@code = params[:code]
|
|
17
|
-
@curl_return_code = params[:curl_return_code]
|
|
18
|
-
@curl_error_message = params[:curl_error_message]
|
|
19
|
-
@status_message = params[:status_message]
|
|
20
|
-
@http_version = params[:http_version]
|
|
21
|
-
@headers = params[:headers]
|
|
22
|
-
@body = params[:body]
|
|
23
|
-
@time = params[:time]
|
|
24
|
-
@requested_url = params[:requested_url]
|
|
25
|
-
@requested_http_method = params[:requested_http_method]
|
|
26
|
-
@start_time = params[:start_time]
|
|
27
|
-
@start_transfer_time = params[:start_transfer_time]
|
|
28
|
-
@app_connect_time = params[:app_connect_time]
|
|
29
|
-
@pretransfer_time = params[:pretransfer_time]
|
|
30
|
-
@connect_time = params[:connect_time]
|
|
31
|
-
@name_lookup_time = params[:name_lookup_time]
|
|
32
|
-
@request = params[:request]
|
|
33
|
-
@effective_url = params[:effective_url]
|
|
34
|
-
@primary_ip = params[:primary_ip]
|
|
35
|
-
@redirect_count = params[:redirect_count]
|
|
36
|
-
@mock = params[:mock] || false # default
|
|
37
|
-
@headers_hash = Header.new(params[:headers_hash]) if params[:headers_hash]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Returns true if this is a mock response.
|
|
41
|
-
def mock?
|
|
42
|
-
@mock
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def headers
|
|
46
|
-
@headers ||= @headers_hash ? construct_header_string : ''
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def headers_hash
|
|
50
|
-
@headers_hash ||= begin
|
|
51
|
-
headers.split("\n").map {|o| o.strip}.inject(Typhoeus::Header.new) do |hash, o|
|
|
52
|
-
if o.empty? || o =~ /^HTTP\/[\d\.]+/
|
|
53
|
-
hash
|
|
54
|
-
else
|
|
55
|
-
i = o.index(":") || o.size
|
|
56
|
-
key = o.slice(0, i)
|
|
57
|
-
value = o.slice(i + 1, o.size)
|
|
58
|
-
value = value.strip unless value.nil?
|
|
59
|
-
if hash.key? key
|
|
60
|
-
hash[key] = [hash[key], value].flatten
|
|
61
|
-
else
|
|
62
|
-
hash[key] = value
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
hash
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def status_message
|
|
72
|
-
return @status_message if @status_message != nil
|
|
73
|
-
|
|
74
|
-
# HTTP servers can choose not to include the explanation to HTTP codes. The RFC
|
|
75
|
-
# states this (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4):
|
|
76
|
-
# Except when responding to a HEAD request, the server SHOULD include an entity containing
|
|
77
|
-
# an explanation of the error situation [...]
|
|
78
|
-
# This means 'HTTP/1.1 404' is as valid as 'HTTP/1.1 404 Not Found' and we have to handle it.
|
|
1
|
+
require 'typhoeus/responses/legacy'
|
|
2
|
+
require 'typhoeus/responses/informations'
|
|
3
|
+
require 'typhoeus/responses/status'
|
|
4
|
+
require 'typhoeus/responses/header'
|
|
79
5
|
|
|
80
|
-
|
|
81
|
-
if first_header_line != nil and first_header_line[/\d{3} (.*)$/, 1] != nil
|
|
82
|
-
@status_message = first_header_line[/\d{3} (.*)$/, 1].chomp
|
|
83
|
-
else
|
|
84
|
-
@status_message = nil
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def http_version
|
|
89
|
-
@http_version ||= first_header_line ? first_header_line[/HTTP\/(\S+)/, 1] : nil
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def success?
|
|
93
|
-
@code >= 200 && @code < 300
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def modified?
|
|
97
|
-
@code != 304
|
|
98
|
-
end
|
|
6
|
+
module Typhoeus
|
|
99
7
|
|
|
100
|
-
|
|
101
|
-
|
|
8
|
+
# This class respresents the response.
|
|
9
|
+
class Response
|
|
10
|
+
include Responses::Status
|
|
11
|
+
include Responses::Informations
|
|
12
|
+
include Responses::Legacy
|
|
13
|
+
|
|
14
|
+
attr_accessor :request, :options
|
|
15
|
+
|
|
16
|
+
# Create a new response.
|
|
17
|
+
#
|
|
18
|
+
# @example Create a response.
|
|
19
|
+
# Response.new
|
|
20
|
+
#
|
|
21
|
+
# @param [ Hash ] options The options hash.
|
|
22
|
+
#
|
|
23
|
+
# @return [ Response ] The new response.
|
|
24
|
+
def initialize(options = {})
|
|
25
|
+
@options = options
|
|
102
26
|
end
|
|
103
|
-
|
|
104
|
-
private
|
|
105
|
-
|
|
106
|
-
def first_header_line
|
|
107
|
-
@first_header_line ||= @headers.to_s.split("\n").first
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def construct_header_string
|
|
111
|
-
lines = ["HTTP/#{http_version} #{code} #{status_message}"]
|
|
112
|
-
|
|
113
|
-
@headers_hash.each do |key, values|
|
|
114
|
-
[values].flatten.each do |value|
|
|
115
|
-
lines << "#{key}: #{value}"
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
lines << '' << ''
|
|
120
|
-
lines.join("\r\n")
|
|
121
|
-
end
|
|
122
27
|
end
|
|
123
28
|
end
|