typhoeus 1.0.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +12 -7
- data/CHANGELOG.md +38 -2
- data/CONTRIBUTING.md +4 -0
- data/Gemfile +14 -3
- data/LICENSE +1 -1
- data/README.md +67 -42
- data/lib/typhoeus/adapters/faraday.rb +30 -9
- data/lib/typhoeus/cache/dalli.rb +28 -0
- data/lib/typhoeus/cache/rails.rb +28 -0
- data/lib/typhoeus/cache/redis.rb +35 -0
- data/lib/typhoeus/config.rb +8 -1
- data/lib/typhoeus/easy_factory.rb +10 -3
- data/lib/typhoeus/hydra/cacheable.rb +1 -1
- data/lib/typhoeus/pool.rb +2 -0
- data/lib/typhoeus/request/actions.rb +7 -7
- data/lib/typhoeus/request/cacheable.rb +14 -3
- data/lib/typhoeus/request/callbacks.rb +21 -3
- data/lib/typhoeus/request/marshal.rb +2 -2
- data/lib/typhoeus/request/streamable.rb +1 -1
- data/lib/typhoeus/request.rb +2 -0
- data/lib/typhoeus/response/header.rb +13 -5
- data/lib/typhoeus/response/informations.rb +7 -3
- data/lib/typhoeus/response/status.rb +22 -2
- data/lib/typhoeus/response.rb +1 -1
- data/lib/typhoeus/version.rb +1 -1
- data/lib/typhoeus.rb +19 -3
- data/spec/support/server.rb +8 -0
- data/spec/typhoeus/adapters/faraday_spec.rb +237 -191
- data/spec/typhoeus/cache/dalli_spec.rb +41 -0
- data/spec/typhoeus/cache/redis_spec.rb +41 -0
- data/spec/typhoeus/config_spec.rb +1 -1
- data/spec/typhoeus/easy_factory_spec.rb +6 -0
- data/spec/typhoeus/hydra/before_spec.rb +9 -8
- data/spec/typhoeus/hydra/cacheable_spec.rb +31 -1
- data/spec/typhoeus/hydra/runnable_spec.rb +4 -3
- data/spec/typhoeus/pool_spec.rb +43 -2
- data/spec/typhoeus/request/before_spec.rb +9 -8
- data/spec/typhoeus/request/cacheable_spec.rb +24 -0
- data/spec/typhoeus/request/callbacks_spec.rb +2 -2
- data/spec/typhoeus/request/marshal_spec.rb +1 -1
- data/spec/typhoeus/request_spec.rb +21 -3
- data/spec/typhoeus/response/header_spec.rb +51 -1
- data/spec/typhoeus/response/informations_spec.rb +12 -1
- data/spec/typhoeus/response/status_spec.rb +54 -0
- data/typhoeus.gemspec +1 -1
- metadata +12 -5
@@ -2,16 +2,16 @@ module Typhoeus
|
|
2
2
|
class Request
|
3
3
|
module Cacheable
|
4
4
|
def response=(response)
|
5
|
-
|
5
|
+
cache.set(self, response) if cacheable? && !response.cached?
|
6
6
|
super
|
7
7
|
end
|
8
8
|
|
9
9
|
def cacheable?
|
10
|
-
|
10
|
+
cache
|
11
11
|
end
|
12
12
|
|
13
13
|
def run
|
14
|
-
if
|
14
|
+
if response = cached_response
|
15
15
|
response.cached = true
|
16
16
|
finish(response)
|
17
17
|
else
|
@@ -19,9 +19,20 @@ module Typhoeus
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
def cached_response
|
23
|
+
cacheable? && cache.get(self)
|
24
|
+
end
|
25
|
+
|
22
26
|
def cache_ttl
|
23
27
|
options[:cache_ttl]
|
24
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def cache
|
33
|
+
return nil if options[:cache] === false
|
34
|
+
options[:cache] || Typhoeus::Config.cache
|
35
|
+
end
|
25
36
|
end
|
26
37
|
end
|
27
38
|
end
|
@@ -89,6 +89,24 @@ module Typhoeus
|
|
89
89
|
@on_headers << block if block_given?
|
90
90
|
@on_headers
|
91
91
|
end
|
92
|
+
|
93
|
+
# Set on_progress callback.
|
94
|
+
#
|
95
|
+
# @example Set on_progress.
|
96
|
+
# request.on_progress do |dltotal, dlnow, ultotal, ulnow|
|
97
|
+
# puts "dltotal (#{dltotal}), dlnow (#{dlnow}), ultotal (#{ultotal}), ulnow (#{ulnow})"
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# @param [ Block ] block The block to execute.
|
101
|
+
#
|
102
|
+
# @yield [ Typhoeus::Response ]
|
103
|
+
#
|
104
|
+
# @return [ Array<Block> ] All on_progress blocks.
|
105
|
+
def on_progress(&block)
|
106
|
+
@on_progress ||= []
|
107
|
+
@on_progress << block if block_given?
|
108
|
+
@on_progress
|
109
|
+
end
|
92
110
|
end
|
93
111
|
|
94
112
|
# Execute the headers callbacks and yields response.
|
@@ -106,8 +124,8 @@ module Typhoeus
|
|
106
124
|
end
|
107
125
|
|
108
126
|
# Execute necessary callback and yields response. This
|
109
|
-
# include in every case on_complete, on_success
|
110
|
-
# successful and on_failure if not.
|
127
|
+
# include in every case on_complete and on_progress, on_success
|
128
|
+
# if successful and on_failure if not.
|
111
129
|
#
|
112
130
|
# @example Execute callbacks.
|
113
131
|
# request.execute_callbacks
|
@@ -116,7 +134,7 @@ module Typhoeus
|
|
116
134
|
#
|
117
135
|
# @api private
|
118
136
|
def execute_callbacks
|
119
|
-
callbacks = Typhoeus.on_complete + on_complete
|
137
|
+
callbacks = Typhoeus.on_complete + Typhoeus.on_progress + on_complete + on_progress
|
120
138
|
|
121
139
|
if response && response.success?
|
122
140
|
callbacks += Typhoeus.on_success + on_success
|
@@ -5,9 +5,9 @@ module Typhoeus
|
|
5
5
|
module Marshal
|
6
6
|
|
7
7
|
# Return the important data needed to serialize this Request, except the
|
8
|
-
#
|
8
|
+
# request callbacks and `hydra`, since they cannot be marshalled.
|
9
9
|
def marshal_dump
|
10
|
-
unmarshallable = %w(@on_complete @on_success @on_failure @on_headers @on_body @hydra)
|
10
|
+
unmarshallable = %w(@on_complete @on_success @on_failure @on_progress @on_headers @on_body @hydra)
|
11
11
|
(instance_variables - unmarshallable - unmarshallable.map(&:to_sym)).map do |name|
|
12
12
|
[name, instance_variable_get(name)]
|
13
13
|
end
|
@@ -10,7 +10,7 @@ module Typhoeus
|
|
10
10
|
# Setting an on_body callback will cause the response body to be empty.
|
11
11
|
#
|
12
12
|
# @example Set on_body.
|
13
|
-
# request.on_body { |
|
13
|
+
# request.on_body { |body_chunk, response| puts "Got #{body_chunk.bytesize} bytes" }
|
14
14
|
#
|
15
15
|
# @param [ Block ] block The block to execute.
|
16
16
|
#
|
data/lib/typhoeus/request.rb
CHANGED
@@ -212,8 +212,10 @@ module Typhoeus
|
|
212
212
|
default_user_agent = Config.user_agent || Typhoeus::USER_AGENT
|
213
213
|
|
214
214
|
options[:headers] = {'User-Agent' => default_user_agent}.merge(options[:headers] || {})
|
215
|
+
options[:headers]['Expect'] ||= ''
|
215
216
|
options[:verbose] = Typhoeus::Config.verbose if options[:verbose].nil? && !Typhoeus::Config.verbose.nil?
|
216
217
|
options[:maxredirs] ||= 50
|
218
|
+
options[:proxy] = Typhoeus::Config.proxy unless options.has_key?(:proxy) || Typhoeus::Config.proxy.nil?
|
217
219
|
end
|
218
220
|
end
|
219
221
|
end
|
@@ -1,11 +1,14 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
1
3
|
module Typhoeus
|
2
4
|
class Response
|
3
5
|
|
4
6
|
# This class represents the response header.
|
5
7
|
# It can be accessed like a hash.
|
8
|
+
# Values can be strings (normal case) or arrays of strings (for duplicates headers)
|
6
9
|
#
|
7
10
|
# @api private
|
8
|
-
class Header < Hash
|
11
|
+
class Header < DelegateClass(Hash)
|
9
12
|
|
10
13
|
# Create a new header.
|
11
14
|
#
|
@@ -14,10 +17,14 @@ module Typhoeus
|
|
14
17
|
#
|
15
18
|
# @param [ String ] raw The raw header.
|
16
19
|
def initialize(raw)
|
20
|
+
super({})
|
17
21
|
@raw = raw
|
18
22
|
@sanitized = {}
|
19
23
|
parse
|
20
|
-
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](key)
|
27
|
+
fetch(key) { @sanitized[key.to_s.downcase] }
|
21
28
|
end
|
22
29
|
|
23
30
|
# Parses the raw header.
|
@@ -31,8 +38,9 @@ module Typhoeus
|
|
31
38
|
process_pair(k, v)
|
32
39
|
end
|
33
40
|
when String
|
34
|
-
raw.
|
35
|
-
|
41
|
+
raw.split(/\r?\n(?!\s)/).each do |header|
|
42
|
+
header.strip!
|
43
|
+
next if header.empty? || header.start_with?( 'HTTP/' )
|
36
44
|
process_line(header)
|
37
45
|
end
|
38
46
|
end
|
@@ -45,7 +53,7 @@ module Typhoeus
|
|
45
53
|
# @return [ void ]
|
46
54
|
def process_line(header)
|
47
55
|
key, value = header.split(':', 2)
|
48
|
-
process_pair(key.strip, value.strip)
|
56
|
+
process_pair(key.strip, (value ? value.strip.gsub(/\r?\n\s*/, ' ') : ''))
|
49
57
|
end
|
50
58
|
|
51
59
|
# Sets key value pair for self and @sanitized.
|
@@ -47,9 +47,13 @@ module Typhoeus
|
|
47
47
|
def response_headers
|
48
48
|
return options[:response_headers] if options[:response_headers]
|
49
49
|
if mock? && h = options[:headers]
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
status_code = return_code || "200"
|
51
|
+
reason_phrase = status_code == "200" ? "OK" : "Mock Reason Phrase"
|
52
|
+
status_line = "HTTP/1.1 #{status_code} #{reason_phrase}"
|
53
|
+
actual_headers = h.map{ |k,v| [k, v.respond_to?(:join) ? v.join(',') : v] }.
|
54
|
+
map{ |e| "#{e.first}: #{e.last}" }
|
55
|
+
|
56
|
+
[status_line, *actual_headers].join("\r\n")
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
@@ -39,14 +39,24 @@ module Typhoeus
|
|
39
39
|
@http_version ||= first_header_line ? first_header_line[/HTTP\/(\S+)/, 1] : nil
|
40
40
|
end
|
41
41
|
|
42
|
-
# Return
|
42
|
+
# Return whether the response is a success.
|
43
43
|
#
|
44
44
|
# @example Return if the response was successful.
|
45
45
|
# response.success?
|
46
46
|
#
|
47
47
|
# @return [ Boolean ] Return true if successful, false else.
|
48
48
|
def success?
|
49
|
-
(mock || return_code == :ok) && response_code &&
|
49
|
+
(mock || return_code == :ok) && response_code && has_good_response_code?
|
50
|
+
end
|
51
|
+
|
52
|
+
# Return whether the response is a failure.
|
53
|
+
#
|
54
|
+
# @example Return if the response was failed.
|
55
|
+
# response.failure?
|
56
|
+
#
|
57
|
+
# @return [ Boolean ] Return true if failure, false else.
|
58
|
+
def failure?
|
59
|
+
(mock || return_code == :internal_server_error) && response_code && has_bad_response_code?
|
50
60
|
end
|
51
61
|
|
52
62
|
# Return wether the response is modified.
|
@@ -81,6 +91,16 @@ module Typhoeus
|
|
81
91
|
end
|
82
92
|
end
|
83
93
|
end
|
94
|
+
|
95
|
+
# :nodoc:
|
96
|
+
def has_good_response_code?
|
97
|
+
response_code >= 200 && response_code < 300
|
98
|
+
end
|
99
|
+
|
100
|
+
# :nodoc:
|
101
|
+
def has_bad_response_code?
|
102
|
+
!has_good_response_code?
|
103
|
+
end
|
84
104
|
end
|
85
105
|
end
|
86
106
|
end
|
data/lib/typhoeus/response.rb
CHANGED
@@ -14,7 +14,7 @@ module Typhoeus
|
|
14
14
|
# Remembers the corresponding request.
|
15
15
|
#
|
16
16
|
# @example Get request.
|
17
|
-
# request = Typhoeus::Request.
|
17
|
+
# request = Typhoeus::Request.new("www.example.com")
|
18
18
|
# response = request.run
|
19
19
|
# request == response.request
|
20
20
|
# #=> true
|
data/lib/typhoeus/version.rb
CHANGED
data/lib/typhoeus.rb
CHANGED
@@ -17,6 +17,21 @@ if defined?(Rack)
|
|
17
17
|
require "rack/typhoeus"
|
18
18
|
end
|
19
19
|
|
20
|
+
# If the Redis gem is available, load the redis cache adapter
|
21
|
+
if defined?(Redis)
|
22
|
+
require "typhoeus/cache/redis"
|
23
|
+
end
|
24
|
+
|
25
|
+
# If the Dalli gem is available, load the Dalli cache adapter
|
26
|
+
if defined?(Dalli)
|
27
|
+
require "typhoeus/cache/dalli"
|
28
|
+
end
|
29
|
+
|
30
|
+
# If we are using Rails, load the Rails cache adapter
|
31
|
+
if defined?(Rails)
|
32
|
+
require "typhoeus/cache/rails"
|
33
|
+
end
|
34
|
+
|
20
35
|
# If we are using Rails, then we will include the Typhoeus railtie.
|
21
36
|
# if defined?(Rails)
|
22
37
|
# require "typhoeus/railtie"
|
@@ -112,11 +127,12 @@ module Typhoeus
|
|
112
127
|
# #=> :ok
|
113
128
|
# end
|
114
129
|
#
|
115
|
-
# @
|
116
|
-
#
|
130
|
+
# @yield Yields control to the block after disabling block_connection.
|
131
|
+
# Afterwards, the block_connection is set to its original
|
132
|
+
# value.
|
117
133
|
# @return [ Object ] Returns the return value of the block.
|
118
134
|
#
|
119
|
-
# @see Typhoeus::Config
|
135
|
+
# @see Typhoeus::Config.block_connection
|
120
136
|
def self.with_connection
|
121
137
|
old = Config.block_connection
|
122
138
|
Config.block_connection = false
|
data/spec/support/server.rb
CHANGED
@@ -23,6 +23,14 @@ TESTSERVER = Sinatra.new do
|
|
23
23
|
[200, { 'Set-Cookie' => %w[ foo bar ], 'Content-Type' => 'text/plain' }, ['']]
|
24
24
|
end
|
25
25
|
|
26
|
+
get '/cookies-test' do
|
27
|
+
[200, { 'Set-Cookie' => %w(foo=bar bar=foo), 'Content-Type' => 'text/plain' }, ['']]
|
28
|
+
end
|
29
|
+
|
30
|
+
get '/cookies-test2' do
|
31
|
+
[200, { 'Set-Cookie' => %w(foo2=bar bar2=foo), 'Content-Type' => 'text/plain' }, ['']]
|
32
|
+
end
|
33
|
+
|
26
34
|
get '/fail/:number' do
|
27
35
|
if fail_count >= params[:number].to_i
|
28
36
|
"ok"
|