typhoeus 1.1.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 905784a1cba9775195bba5751eac56a93e29c313
4
- data.tar.gz: 7802bff9112dfe764bee3ef0a5620988e1f5c23e
3
+ metadata.gz: 79bd3451f6ec67ea973d9dc62dc4645c21e2eba1
4
+ data.tar.gz: 762e3c44e97fc0f2241d5cbf9d2a9ff2caa8a53a
5
5
  SHA512:
6
- metadata.gz: a135cd5834f863538735ee0c971b26fb83141a9da7e74be98678c331b1cfba97c2cb22ec163b1eb85b95fae18055288c4e0c21e34d45780b264922db2f5415dd
7
- data.tar.gz: 1218163c756609a25e0635d6e390d38c474035fcb7a1077ef748248d218fbb97b3373234d5006a018bb9a45fd458b40202029db9790ed887952e2ecef3072f77
6
+ metadata.gz: e0a7c0b640b05b4527a4a9a7b3ee7db526fc25e31e001b7287f2423fecebbf6d673adb5c17b7cda32c1206872a3a27d82825b9ee74974607f691e9ee573fb39a
7
+ data.tar.gz: 444398bc7499402359de7a5534c265bf91c39346903c1b82c4767b1b7f9eb9c72741a979986b905e388301055e6816baa6ef999f9f35bed06a07a4bec37d7b99
data/.travis.yml CHANGED
@@ -1,14 +1,14 @@
1
1
  language: ruby
2
2
  script: "bundle exec rake"
3
- sudo: false
4
3
  rvm:
5
- - 1.8.7
6
- - 1.9.2
7
4
  - 1.9.3
8
5
  - 2.0.0
9
- - 2.1.8
10
- - 2.2.4
11
- - 2.3.0
6
+ - 2.1.10
7
+ - 2.2.10
8
+ - 2.3.8
9
+ - 2.4.7
10
+ - 2.5.6
11
+ - 2.6.4
12
12
  - ruby-head
13
13
  - jruby-head
14
14
  - jruby-18mode
@@ -19,3 +19,8 @@ matrix:
19
19
  - rvm: ruby-head
20
20
  - rvm: jruby-head
21
21
  - rvm: ree
22
+ include:
23
+ - rvm: 1.8.7
24
+ dist: precise
25
+ - rvm: 1.9.2
26
+ dist: trusty
data/CHANGELOG.md CHANGED
@@ -2,7 +2,19 @@
2
2
 
3
3
  ## Master
4
4
 
5
- [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.1.2...master)
5
+ [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.4.0...master)
6
+
7
+ ## 1.4.0
8
+
9
+ [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.1.2...v1.4.0)
10
+
11
+ #### 1 feature
12
+ - Faraday adapter exceptions namespace compatibility with Faraday v1 ([@iMacTia](https://github.com/iMacTia) in [#616](https://github.com/typhoeus/typhoeus/pull/616))
13
+
14
+ #### 3 Others
15
+ - Yard warning fixes ([@olleolleolle](https://github.com/olleolleolle) in [#622](https://github.com/typhoeus/typhoeus/pull/622))
16
+ - Add more Ruby versions in CI matrix ([@olleolleolle](https://github.com/olleolleolle) in [#623](https://github.com/typhoeus/typhoeus/pull/623))
17
+ - Use of argument passed in function instead of `attr_reader` ([@v-kolesnikov](https://github.com/v-kolesnikov) in [#625](https://github.com/typhoeus/typhoeus/pull/625))
6
18
 
7
19
  ## 1.1.2
8
20
 
data/CONTRIBUTING.md CHANGED
@@ -14,3 +14,7 @@ a test!
14
14
  5. Push to your fork and submit a pull request.
15
15
 
16
16
  And in case we didn't emphasize it enough: we love tests!
17
+
18
+ ## Issue triage [![Open Source Helpers](https://www.codetriage.com/typhoeus/typhoeus/badges/users.svg)](https://www.codetriage.com/typhoeus/typhoeus)
19
+
20
+ You can contribute by triaging issues which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to typhoeus on CodeTriage](https://www.codetriage.com/typhoeus/typhoeus).
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Typhoeus [![Build Status](https://img.shields.io/travis/typhoeus/typhoeus/master.svg)](https://travis-ci.org/typhoeus/typhoeus) [![Code Climate](https://img.shields.io/codeclimate/github/typhoeus/typhoeus.svg)](https://codeclimate.com/github/typhoeus/typhoeus) [![Gem Version](https://img.shields.io/gem/v/typhoeus.svg)](https://rubygems.org/gems/typhoeus)
1
+ # Typhoeus [![Build Status](https://img.shields.io/travis/typhoeus/typhoeus/master.svg)](https://travis-ci.org/typhoeus/typhoeus) [![Code Climate](https://img.shields.io/codeclimate/maintainability/typhoeus/typhoeus.svg)](https://codeclimate.com/github/typhoeus/typhoeus) [![Gem Version](https://img.shields.io/gem/v/typhoeus.svg)](https://rubygems.org/gems/typhoeus)
2
2
 
3
3
  Like a modern code version of the mythical beast with 100 serpent heads, Typhoeus runs HTTP requests in parallel while cleanly encapsulating handling logic.
4
4
 
@@ -19,13 +19,16 @@ hydra.run
19
19
  ```
20
20
 
21
21
  ## Installation
22
-
22
+ Add the following line to your Gemfile:
23
23
  ```
24
- gem install typhoeus
24
+ gem "typhoeus"
25
25
  ```
26
+ Then run `bundle install`
27
+
28
+ Or install it yourself as:
26
29
 
27
30
  ```
28
- gem "typhoeus"
31
+ gem install typhoeus
29
32
  ```
30
33
 
31
34
  ## Project Tracking
@@ -191,6 +194,19 @@ end
191
194
  request.run
192
195
  ```
193
196
 
197
+ If you need to interrupt the stream halfway,
198
+ you can return the `:abort` symbol from the `on_body` block, example:
199
+
200
+ ```ruby
201
+ request.on_body do |chunk|
202
+ buffer << chunk
203
+ :abort if buffer.size > 1024 * 1024
204
+ end
205
+ ```
206
+
207
+ This will properly stop the stream internally and avoid any memory leak which
208
+ may happen if you interrupt with something like a `return`, `throw` or `raise`.
209
+
194
210
  ### Making Parallel Requests
195
211
 
196
212
  Generally, you should be running requests through hydra. Here is how that looks:
@@ -242,6 +258,33 @@ end
242
258
  hydra.run
243
259
  ```
244
260
 
261
+ ### Making Parallel Requests with Faraday + Typhoeus
262
+
263
+ ```ruby
264
+ require 'faraday'
265
+
266
+ conn = Faraday.new(:url => 'http://httppage.com') do |builder|
267
+ builder.request :url_encoded
268
+ builder.response :logger
269
+ builder.adapter :typhoeus
270
+ end
271
+
272
+ conn.in_parallel do
273
+ response1 = conn.get('/first')
274
+ response2 = conn.get('/second')
275
+
276
+ # these will return nil here since the
277
+ # requests have not been completed
278
+ response1.body
279
+ response2.body
280
+ end
281
+
282
+ # after it has been completed the response information is fully available
283
+ # response1.status, etc
284
+ response1.body
285
+ response2.body
286
+ ```
287
+
245
288
  ### Specifying Max Concurrency
246
289
 
247
290
  Hydra will also handle how many requests you can make in parallel. Things will get flakey if you try to make too many requests at the same time. The built in limit is 200. When more requests than that are queued up, hydra will save them for later and start the requests as others are finished. You can raise or lower the concurrency limit through the Hydra constructor.
@@ -327,6 +370,14 @@ Typhoeus::Config.cache = Typhoeus::Cache::Redis.new(redis)
327
370
  All three of these adapters take an optional keyword argument `default_ttl`, which sets a default
328
371
  TTL on cached responses (in seconds), for requests which do not have a cache TTL set.
329
372
 
373
+ You may also selectively choose not to cache by setting `cache` to `false` on a request or to use
374
+ a different adapter.
375
+
376
+ ```ruby
377
+ cache = Cache.new
378
+ Typhoeus.get("www.example.com", cache: cache)
379
+ ```
380
+
330
381
  ### Direct Stubbing
331
382
 
332
383
  Hydra allows you to stub out specific urls and patterns to avoid hitting
@@ -97,13 +97,13 @@ module Faraday # :nodoc:
97
97
  if resp.timed_out?
98
98
  env[:typhoeus_timed_out] = true
99
99
  unless parallel?(env)
100
- raise Faraday::Error::TimeoutError, "request timed out"
100
+ raise Faraday::TimeoutError, "request timed out"
101
101
  end
102
- elsif resp.response_code == 0
102
+ elsif (resp.response_code == 0) || ((resp.return_code != :ok) && !resp.mock?)
103
103
  env[:typhoeus_connection_failed] = true
104
104
  env[:typhoeus_return_message] = resp.return_message
105
105
  unless parallel?(env)
106
- raise Faraday::Error::ConnectionFailed, resp.return_message
106
+ raise Faraday::ConnectionFailed, resp.return_message
107
107
  end
108
108
  end
109
109
 
@@ -7,7 +7,9 @@ module Typhoeus
7
7
  #
8
8
  # @param [ Dalli::Client ] client
9
9
  # A connection to the cache server. Defaults to `Dalli::Client.new`
10
- # @param [ Integer ] default_ttl
10
+ # @param [ Hash ] options
11
+ # Options
12
+ # @option options [ Integer ] :default_ttl
11
13
  # The default TTL of cached responses in seconds, for requests which do not set a cache_ttl.
12
14
  def initialize(client = ::Dalli::Client.new, options = {})
13
15
  @client = client
@@ -7,7 +7,9 @@ module Typhoeus
7
7
  #
8
8
  # @param [ ActiveSupport::Cache::Store ] cache
9
9
  # A Rails cache backend. Defaults to Rails.cache.
10
- # @param [ Integer ] default_ttl
10
+ # @param [ Hash ] options
11
+ # Options
12
+ # @option options [ Integer ] :default_ttl
11
13
  # The default TTL of cached responses in seconds, for requests which do not set a cache_ttl.
12
14
  def initialize(cache = ::Rails.cache, options = {})
13
15
  @cache = cache
@@ -19,7 +21,7 @@ module Typhoeus
19
21
  end
20
22
 
21
23
  def set(request, response)
22
- @cache.write(request, response, :expires_in => request.cache_ttl || @default_ttl)
24
+ @cache.write(request.cache_key, response, :expires_in => request.cache_ttl || @default_ttl)
23
25
  end
24
26
  end
25
27
  end
@@ -8,7 +8,9 @@ module Typhoeus
8
8
  # @param [ Redis ] redis
9
9
  # A connection to Redis. Defaults to `Redis.new`, which uses the
10
10
  # `REDIS_URL` environment variable to connect
11
- # @param [ Integer ] default_ttl
11
+ # @param [ Hash ] options
12
+ # Options
13
+ # @option options [ Integer ] :default_ttl
12
14
  # The default TTL of cached responses in seconds, for requests which do not set a cache_ttl.
13
15
  def initialize(redis = ::Redis.new, options = {})
14
16
  @redis = redis
@@ -18,7 +18,7 @@ module Typhoeus
18
18
  # {Typhoeus::Errors::NoStub} error is raised,
19
19
  # when trying to do a real request. It's possible
20
20
  # to work around inside
21
- # {Typhoeus#with_connection}.
21
+ # {Typhoeus.with_connection}.
22
22
  #
23
23
  # @return [ Boolean ]
24
24
  #
@@ -35,7 +35,7 @@ module Typhoeus
35
35
 
36
36
  REMOVED_OPTIONS = Set.new([:cache_key_basis, :cache_timeout, :user_agent])
37
37
 
38
- SANITIZE_IGNORE = Set.new([:method, :cache_ttl])
38
+ SANITIZE_IGNORE = Set.new([:method, :cache_ttl, :cache])
39
39
  SANITIZE_TIMEOUT = Set.new([:timeout_ms, :connecttimeout_ms])
40
40
 
41
41
  # Returns the request provided.
@@ -97,7 +97,7 @@ module Typhoeus
97
97
  # set nosignal to true by default
98
98
  # this improves thread safety and timeout behavior
99
99
  sanitized = {:nosignal => true}
100
- request.options.each do |k,v|
100
+ options.each do |k,v|
101
101
  s = k.to_sym
102
102
  next if SANITIZE_IGNORE.include?(s)
103
103
  if new_option = RENAMED_OPTIONS[k.to_sym]
@@ -155,6 +155,11 @@ module Typhoeus
155
155
  request.execute_headers_callbacks(Response.new(Ethon::Easy::Mirror.from_easy(easy).options))
156
156
  end
157
157
  end
158
+ request.on_progress.each do |callback|
159
+ easy.on_progress do |dltotal, dlnow, ultotal, ulnow, easy|
160
+ callback.call(dltotal, dlnow, ultotal, ulnow, response)
161
+ end
162
+ end
158
163
  easy.on_complete do |easy|
159
164
  request.finish(Response.new(easy.mirror.options))
160
165
  Typhoeus::Pool.release(easy)
@@ -2,7 +2,7 @@ module Typhoeus
2
2
  class Hydra
3
3
  module Cacheable
4
4
  def add(request)
5
- if request.cacheable? && response = Typhoeus::Config.cache.get(request)
5
+ if request.cacheable? && response = request.cached_response
6
6
  response.cached = true
7
7
  request.finish(response)
8
8
  dequeue
@@ -15,7 +15,7 @@ module Typhoeus
15
15
  #
16
16
  # @option (see Typhoeus::Request#initialize)
17
17
  #
18
- # @return (see Typhoeus::Request#initialize)
18
+ # @return (see Typhoeus::Response#initialize)
19
19
  #
20
20
  # @note (see Typhoeus::Request#initialize)
21
21
  def get(base_url, options = {})
@@ -31,7 +31,7 @@ module Typhoeus
31
31
  #
32
32
  # @option (see Typhoeus::Request#initialize)
33
33
  #
34
- # @return (see Typhoeus::Request#initialize)
34
+ # @return (see Typhoeus::Response#initialize)
35
35
  #
36
36
  # @note (see Typhoeus::Request#initialize)
37
37
  def post(base_url, options = {})
@@ -50,7 +50,7 @@ module Typhoeus
50
50
  # @option options :body [ Hash ] Body hash which
51
51
  # becomes a PUT request body.
52
52
  #
53
- # @return (see Typhoeus::Request#initialize)
53
+ # @return (see Typhoeus::Response#initialize)
54
54
  #
55
55
  # @note (see Typhoeus::Request#initialize)
56
56
  def put(base_url, options = {})
@@ -66,7 +66,7 @@ module Typhoeus
66
66
  #
67
67
  # @option (see Typhoeus::Request#initialize)
68
68
  #
69
- # @return (see Typhoeus::Request#initialize)
69
+ # @return (see Typhoeus::Response#initialize)
70
70
  #
71
71
  # @note (see Typhoeus::Request#initialize)
72
72
  def delete(base_url, options = {})
@@ -82,7 +82,7 @@ module Typhoeus
82
82
  #
83
83
  # @option (see Typhoeus::Request#initialize)
84
84
  #
85
- # @return (see Typhoeus::Request#initialize)
85
+ # @return (see Typhoeus::Response#initialize)
86
86
  #
87
87
  # @note (see Typhoeus::Request#initialize)
88
88
  def head(base_url, options = {})
@@ -98,7 +98,7 @@ module Typhoeus
98
98
  #
99
99
  # @option (see Typhoeus::Request#initialize)
100
100
  #
101
- # @return (see Typhoeus::Request#initialize)
101
+ # @return (see Typhoeus::Response#initialize)
102
102
  #
103
103
  # @note (see Typhoeus::Request#initialize)
104
104
  def patch(base_url, options = {})
@@ -114,7 +114,7 @@ module Typhoeus
114
114
  #
115
115
  # @option (see Typhoeus::Request#initialize)
116
116
  #
117
- # @return (see Typhoeus::Request#initialize)
117
+ # @return (see Typhoeus::Response#initialize)
118
118
  #
119
119
  # @note (see Typhoeus::Request#initialize)
120
120
  def options(base_url, options = {})
@@ -2,16 +2,16 @@ module Typhoeus
2
2
  class Request
3
3
  module Cacheable
4
4
  def response=(response)
5
- Typhoeus::Config.cache.set(self, response) if cacheable? && !response.cached?
5
+ cache.set(self, response) if cacheable? && !response.cached?
6
6
  super
7
7
  end
8
8
 
9
9
  def cacheable?
10
- Typhoeus::Config.cache
10
+ cache
11
11
  end
12
12
 
13
13
  def run
14
- if cacheable? && response = Typhoeus::Config.cache.get(self)
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 if
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
- # `on_complete`, `on_success`, `on_failure`, and `hydra`, since they cannot be marshalled.
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 { |response, body_chunk| puts "Got #{body_chunk.bytesize} bytes" }
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
  #
@@ -1,3 +1,5 @@
1
+ require 'delegate'
2
+
1
3
  module Typhoeus
2
4
  class Response
3
5
 
@@ -6,7 +8,7 @@ module Typhoeus
6
8
  # Values can be strings (normal case) or arrays of strings (for duplicates headers)
7
9
  #
8
10
  # @api private
9
- class Header < Hash
11
+ class Header < DelegateClass(Hash)
10
12
 
11
13
  # Create a new header.
12
14
  #
@@ -15,10 +17,14 @@ module Typhoeus
15
17
  #
16
18
  # @param [ String ] raw The raw header.
17
19
  def initialize(raw)
20
+ super({})
18
21
  @raw = raw
19
22
  @sanitized = {}
20
23
  parse
21
- set_default_proc_on(self, lambda { |h, k| @sanitized[k.to_s.downcase] })
24
+ end
25
+
26
+ def [](key)
27
+ fetch(key) { @sanitized[key.to_s.downcase] }
22
28
  end
23
29
 
24
30
  # Parses the raw header.
@@ -32,9 +38,9 @@ module Typhoeus
32
38
  process_pair(k, v)
33
39
  end
34
40
  when String
35
- raw.lines.each do |header|
41
+ raw.split(/\r?\n(?!\s)/).each do |header|
36
42
  header.strip!
37
- next if header.empty? || header.start_with?( 'HTTP/1.' )
43
+ next if header.empty? || header.start_with?( 'HTTP/' )
38
44
  process_line(header)
39
45
  end
40
46
  end
@@ -47,7 +53,7 @@ module Typhoeus
47
53
  # @return [ void ]
48
54
  def process_line(header)
49
55
  key, value = header.split(':', 2)
50
- process_pair(key.strip, value.strip)
56
+ process_pair(key.strip, (value ? value.strip.gsub(/\r?\n\s*/, ' ') : ''))
51
57
  end
52
58
 
53
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
- h.map{ |k,v| [k, v.respond_to?(:join) ? v.join : v] }.
51
- map{ |e| "#{e.first}: #{e.last}" }.
52
- join("\r\n")
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 wether the response is a success.
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 && response_code >= 200 && response_code < 300
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
@@ -14,7 +14,7 @@ module Typhoeus
14
14
  # Remembers the corresponding request.
15
15
  #
16
16
  # @example Get request.
17
- # request = Typhoeus::Request.get("www.example.com")
17
+ # request = Typhoeus::Request.new("www.example.com")
18
18
  # response = request.run
19
19
  # request == response.request
20
20
  # #=> true
@@ -1,5 +1,5 @@
1
1
  module Typhoeus
2
2
 
3
3
  # The current Typhoeus version.
4
- VERSION = '1.1.2'
4
+ VERSION = '1.4.0'
5
5
  end
data/lib/typhoeus.rb CHANGED
@@ -127,11 +127,12 @@ module Typhoeus
127
127
  # #=> :ok
128
128
  # end
129
129
  #
130
- # @param [ Block ] block The block to execute.
131
- #
130
+ # @yield Yields control to the block after disabling block_connection.
131
+ # Afterwards, the block_connection is set to its original
132
+ # value.
132
133
  # @return [ Object ] Returns the return value of the block.
133
134
  #
134
- # @see Typhoeus::Config#block_connection
135
+ # @see Typhoeus::Config.block_connection
135
136
  def self.with_connection
136
137
  old = Config.block_connection
137
138
  Config.block_connection = false
@@ -163,7 +163,7 @@ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("1.9.0")
163
163
 
164
164
  context "when not parallel" do
165
165
  it "raises an error" do
166
- expect { conn.get("/") }.to raise_error(Faraday::Error::ConnectionFailed, "No error")
166
+ expect { conn.get("/") }.to raise_error(Faraday::ConnectionFailed, "No error")
167
167
  end
168
168
  end
169
169
  end
@@ -104,6 +104,12 @@ describe Typhoeus::EasyFactory do
104
104
  end
105
105
 
106
106
  describe "#set_callback" do
107
+ it "sets easy.on_progress callback when an on_progress callback is provided" do
108
+ request.on_progress { 1 }
109
+ expect(easy_factory.easy).to receive(:on_progress)
110
+ easy_factory.send(:set_callback)
111
+ end
112
+
107
113
  it "sets easy.on_complete callback" do
108
114
  expect(easy_factory.easy).to receive(:on_complete)
109
115
  easy_factory.send(:set_callback)
@@ -4,6 +4,7 @@ describe Typhoeus::Hydra::Cacheable do
4
4
  let(:base_url) { "localhost:3001" }
5
5
  let(:hydra) { Typhoeus::Hydra.new() }
6
6
  let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) }
7
+ let(:response) { Typhoeus::Response.new }
7
8
  let(:cache) { MemoryCache.new }
8
9
 
9
10
  describe "add" do
@@ -24,7 +25,6 @@ describe Typhoeus::Hydra::Cacheable do
24
25
  end
25
26
 
26
27
  context "when request in memory" do
27
- let(:response) { Typhoeus::Response.new }
28
28
  before { cache.memory[request] = response }
29
29
 
30
30
  it "returns response with cached status" do
@@ -53,6 +53,36 @@ describe Typhoeus::Hydra::Cacheable do
53
53
  end
54
54
  end
55
55
  end
56
+
57
+ context "when cache is specified on a request" do
58
+ before { Typhoeus::Config.cache = false }
59
+
60
+ context "when cache is false" do
61
+ let(:non_cached_request) { Typhoeus::Request.new(base_url, {:method => :get, :cache => false}) }
62
+
63
+ it "initiates an HTTP call" do
64
+ expect(Typhoeus::EasyFactory).to receive(:new).with(non_cached_request, hydra).and_call_original
65
+
66
+ hydra.add(non_cached_request)
67
+ end
68
+ end
69
+
70
+ context "when cache is defined" do
71
+ let(:cached_request) { Typhoeus::Request.new(base_url, {:method => :get, :cache => cache}) }
72
+
73
+ before { cache.memory[cached_request] = response }
74
+
75
+ it "uses the cache instead of making a new request" do
76
+ expect(Typhoeus::EasyFactory).not_to receive(:new)
77
+
78
+ hydra.add(cached_request)
79
+
80
+ expect(cached_request.response).to be_cached
81
+ expect(cached_request.response).to eq(response)
82
+ end
83
+ end
84
+ end
85
+
56
86
  end
57
87
  end
58
88
  end
@@ -88,12 +88,14 @@ describe Typhoeus::Pool do
88
88
 
89
89
  context "when threaded access" do
90
90
  it "creates correct number of easies" do
91
- array = []
91
+ queue = Queue.new
92
92
  (0..9).map do |n|
93
93
  Thread.new do
94
- array << Typhoeus::Pool.get
94
+ queue.enq(Typhoeus::Pool.get)
95
95
  end
96
96
  end.map(&:join)
97
+
98
+ array = Array.new(queue.size) { queue.pop }
97
99
  expect(array.uniq.size).to eq(10)
98
100
  end
99
101
  end
@@ -55,6 +55,30 @@ describe Typhoeus::Request::Cacheable do
55
55
  request.run
56
56
  end
57
57
  end
58
+
59
+ context "when cache is specified on a request" do
60
+ before { Typhoeus::Config.cache = false }
61
+
62
+ context "when cache is false" do
63
+ let(:options) { { :cache => false } }
64
+
65
+ it "finishes request" do
66
+ expect(request.response).to_not be(response)
67
+ request.run
68
+ end
69
+ end
70
+
71
+ context "when cache is defined" do
72
+ let(:options) { { :cache => cache } }
73
+
74
+ before { cache.memory[request] = response }
75
+
76
+ it "finishes request" do
77
+ expect(request).to receive(:finish).with(response)
78
+ request.run
79
+ end
80
+ end
81
+ end
58
82
  end
59
83
  end
60
84
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Typhoeus::Request::Callbacks do
4
4
  let(:request) { Typhoeus::Request.new("fubar") }
5
5
 
6
- [:on_complete, :on_success, :on_failure].each do |callback|
6
+ [:on_complete, :on_success, :on_failure, :on_progress].each do |callback|
7
7
  describe "##{callback}" do
8
8
  it "responds" do
9
9
  expect(request).to respond_to(callback)
@@ -33,7 +33,7 @@ describe Typhoeus::Request::Callbacks do
33
33
  end
34
34
 
35
35
  describe "#execute_callbacks" do
36
- [:on_complete, :on_success, :on_failure].each do |callback|
36
+ [:on_complete, :on_success, :on_failure, :on_progress].each do |callback|
37
37
  context "when #{callback}" do
38
38
  context "when local callback" do
39
39
  before do
@@ -5,7 +5,7 @@ describe Typhoeus::Request::Marshal do
5
5
  let(:request) { Typhoeus::Request.new(base_url) }
6
6
 
7
7
  describe "#marshal_dump" do
8
- %w(on_complete on_success on_failure).each do |name|
8
+ %w(on_complete on_success on_failure on_progress).each do |name|
9
9
  context "when #{name} handler" do
10
10
  before { request.instance_variable_set("@#{name}", Proc.new{}) }
11
11
 
@@ -55,7 +55,7 @@ describe Typhoeus::Response::Header do
55
55
  Server: gws
56
56
  X-XSS-Protection: 1; mode=block
57
57
  X-Frame-Options: SAMEORIGIN
58
- Transfer-Encoding: chunked'
58
+ Transfer-Encoding: chunked'.gsub(/^\s{8}/, '')
59
59
  end
60
60
 
61
61
  it "sets raw" do
@@ -93,18 +93,55 @@ describe Typhoeus::Response::Header do
93
93
  end
94
94
  end
95
95
 
96
- context 'includes line with only whitespace' do
97
- let(:raw) do
98
- 'HTTP/1.1 200 OK
99
- Date: Fri, 29 Jun 2012 10:09:23 GMT
96
+ context 'includes a multi-line header' do
97
+ let(:raw) do
98
+ 'HTTP/1.1 200 OK
99
+ Date: Fri, 29 Jun 2012 10:09:23 GMT
100
+ Content-Security-Policy: default-src "self";
101
+ img-src * data: "self";
102
+ upgrade-insecure-requests;'.gsub(/^\s{10}/, '')
103
+ end
100
104
 
101
- '
105
+ it "joins header parts" do
106
+ expect(header).to eq({
107
+ 'Date' => 'Fri, 29 Jun 2012 10:09:23 GMT',
108
+ 'Content-Security-Policy' => 'default-src "self"; img-src * data: "self"; upgrade-insecure-requests;'
109
+ })
110
+ end
111
+ end
112
+
113
+ context 'includes line with only whitespace' do
114
+ let(:raw) do
115
+ 'HTTP/1.1 200 OK
116
+ Date: Fri, 29 Jun 2012 10:09:23 GMT
117
+
118
+ '.gsub(/^\s{10}/, '')
102
119
  end
103
120
 
104
121
  it 'ignores it' do
105
122
  expect(header).to eq({ 'Date' => 'Fri, 29 Jun 2012 10:09:23 GMT' })
106
123
  end
107
124
  end
125
+
126
+ context 'with broken headers' do
127
+ let(:raw) do
128
+ 'HTTP/1.1 200 OK
129
+ Date:
130
+ Content-Type
131
+ '.gsub(/^\s{10}/, '')
132
+ end
133
+
134
+ it 'returns empty string for invalid headers' do
135
+ expect(header.to_hash).to include({ 'Date' => '', 'Content-Type' => '' })
136
+ end
137
+ end
108
138
  end
109
139
  end
140
+
141
+ it "can be Marshal'd" do
142
+ header = Typhoeus::Response::Header.new("Foo: Bar")
143
+ expect {
144
+ Marshal.dump(header)
145
+ }.not_to raise_error
146
+ end
110
147
  end
@@ -74,6 +74,17 @@ describe Typhoeus::Response::Informations do
74
74
  expect(response.response_headers).to include("\r\n")
75
75
  end
76
76
  end
77
+
78
+ context "when multiple values for a header" do
79
+ let(:options) { { :mock => true, :headers => {"Length" => 1, "Content-Type" => "text/plain", "set-cookie" => ["cookieone=one","cookietwo=two"] } } }
80
+
81
+ it "constructs response_headers" do
82
+ expect(response.response_headers).to include("Length: 1")
83
+ expect(response.response_headers).to include("Content-Type: text/plain")
84
+ expect(response.response_headers).to include("set-cookie: cookieone=one,cookietwo=two")
85
+ expect(response.response_headers).to include("\r\n")
86
+ end
87
+ end
77
88
  end
78
89
  end
79
90
  end
@@ -232,7 +243,7 @@ describe Typhoeus::Response::Informations do
232
243
  end
233
244
 
234
245
  it "returns headers" do
235
- expect(response.headers).to include("Length" => "1")
246
+ expect(response.headers.to_hash).to include("Length" => "1")
236
247
  end
237
248
  end
238
249
  end
@@ -128,6 +128,60 @@ describe Typhoeus::Response::Status do
128
128
  end
129
129
  end
130
130
 
131
+ describe "#failure?" do
132
+ context "when response code between 300-526 and 100-300" do
133
+ let(:options) { {:return_code => return_code, :response_code => 300} }
134
+
135
+ context "when mock" do
136
+ before { response.mock = true }
137
+
138
+ context "when return_code :internal_server_error" do
139
+ let(:return_code) { :internal_server_error }
140
+
141
+ it "returns true" do
142
+ expect(response.failure?).to be_truthy
143
+ end
144
+ end
145
+
146
+ context "when return_code nil" do
147
+ let(:return_code) { nil }
148
+
149
+ it "returns true" do
150
+ expect(response.failure?).to be_truthy
151
+ end
152
+ end
153
+ end
154
+
155
+ context "when no mock" do
156
+ before { response.mock = nil }
157
+
158
+ context "when return_code :internal_server_error" do
159
+ let(:return_code) { :internal_server_error }
160
+
161
+ it "returns true" do
162
+ expect(response.failure?).to be_truthy
163
+ end
164
+ end
165
+
166
+ context "when return_code nil" do
167
+ let(:return_code) { nil }
168
+
169
+ it "returns false" do
170
+ expect(response.failure?).to be_falsey
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ context "when response code is not 300-526" do
177
+ let(:options) { {:return_code => :ok, :response_code => 200} }
178
+
179
+ it "returns false" do
180
+ expect(response.failure?).to be_falsey
181
+ end
182
+ end
183
+ end
184
+
131
185
  describe "#modified?" do
132
186
  context "when response code 304" do
133
187
  let(:options) { {:return_code => :ok, :response_code => 304} }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typhoeus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Balatero
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-12-02 00:00:00.000000000 Z
13
+ date: 2020-05-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: ethon
@@ -150,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
150
  version: 1.3.6
151
151
  requirements: []
152
152
  rubyforge_project:
153
- rubygems_version: 2.2.2
153
+ rubygems_version: 2.5.2.3
154
154
  signing_key:
155
155
  specification_version: 4
156
156
  summary: Parallel HTTP library on top of libcurl multi.