typhoeus 1.3.0 → 1.4.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: df7045af2adbad5bf0b5bc883e8bc259a2f63544
4
- data.tar.gz: 16d738d8b00c774fe54a78c32becde597ad69569
2
+ SHA256:
3
+ metadata.gz: b1a6b0485477d252e7eb99852bec27994e9c23aa54e7d376cd24bc07d3639d5c
4
+ data.tar.gz: d2dbaf34e81e7a906dbf254d0d1aa1d6028c10a08605b6dc6261c282bfc39abd
5
5
  SHA512:
6
- metadata.gz: c5f8427b91d383cd94bc48c4f944b3bc7dbce619e0eccda0f84d428eb575ff9f7b65530f18789cb1aa99f02e4f03293af9987cffb12686542af13b9fb49bba51
7
- data.tar.gz: e01422dc678ff40ac31b695bc1dea8d0c3b843e0ecd2ad61fa386d9b290a0950db93e37289215aedaee3aad60a7cc2acd48efc4baf59ae4fc96f3198d5df460a
6
+ metadata.gz: 711db47d856f75d5eb730e11161e02a6a6f6c6d9e966aeec3ace577d250d57a790c2d0d5ade86fda425bff6b5f6d5c77079107a3f41a2379d4bff9cd802ca712
7
+ data.tar.gz: 52cfa55fe418b64ed16e094a497d6fc72092b8d5745d81860aead9e35a6dba403fb2375674ca652ba6bb8e5acac29ed5ce03161c2c68dc0f1de9d44ad65ac277
@@ -0,0 +1,30 @@
1
+ name: CI
2
+ on: [push, pull_request]
3
+ jobs:
4
+ build:
5
+ env:
6
+ BUNDLE_GEMFILE: Gemfile
7
+ runs-on: ${{ matrix.os }}-latest
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ os: [ubuntu, macos]
12
+ ruby-version: ['2.5', '2.6', '2.7', '3.0', '3.1', truffleruby]
13
+ steps:
14
+ - uses: actions/checkout@v3
15
+ - name: Install libcurl header
16
+ run: |
17
+ if ${{ matrix.os == 'macos' }}
18
+ then
19
+ brew install curl
20
+ else
21
+ sudo apt update && sudo apt install -y --no-install-recommends libcurl4-openssl-dev
22
+ fi
23
+ - name: Set up Ruby ${{ matrix.ruby-version }}
24
+ uses: ruby/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby-version }}
27
+ bundler-cache: true
28
+ - name: Run tests
29
+ run: |
30
+ bundle exec rake
@@ -0,0 +1,33 @@
1
+ name: Experimental
2
+ on: [push, pull_request]
3
+ jobs:
4
+ build:
5
+ env:
6
+ BUNDLE_GEMFILE: Gemfile
7
+ runs-on: ${{ matrix.os }}-latest
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ os: [ubuntu, macos]
12
+ ruby-version:
13
+ - ruby-head
14
+ - jruby-head
15
+ - truffleruby-head
16
+ steps:
17
+ - uses: actions/checkout@v3
18
+ - name: Install libcurl header
19
+ run: |
20
+ if ${{ matrix.os == 'macos' }}
21
+ then
22
+ brew install curl
23
+ else
24
+ sudo apt update && sudo apt install -y --no-install-recommends libcurl4-openssl-dev
25
+ fi
26
+ - name: Set up Ruby ${{ matrix.ruby-version }}
27
+ uses: ruby/setup-ruby@v1
28
+ with:
29
+ ruby-version: ${{ matrix.ruby-version }}
30
+ bundler-cache: true
31
+ - name: Run tests
32
+ run: |
33
+ bundle exec rake
data/CHANGELOG.md CHANGED
@@ -2,7 +2,23 @@
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.1...master)
6
+
7
+ ## 1.4.1
8
+
9
+ [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.4.0...v1.4.1)
10
+
11
+ ## 1.4.0
12
+
13
+ [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v1.1.2...v1.4.0)
14
+
15
+ #### 1 feature
16
+ - Faraday adapter exceptions namespace compatibility with Faraday v1 ([@iMacTia](https://github.com/iMacTia) in [#616](https://github.com/typhoeus/typhoeus/pull/616))
17
+
18
+ #### 3 Others
19
+ - Yard warning fixes ([@olleolleolle](https://github.com/olleolleolle) in [#622](https://github.com/typhoeus/typhoeus/pull/622))
20
+ - Add more Ruby versions in CI matrix ([@olleolleolle](https://github.com/olleolleolle) in [#623](https://github.com/typhoeus/typhoeus/pull/623))
21
+ - 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
22
 
7
23
  ## 1.1.2
8
24
 
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/Gemfile CHANGED
@@ -15,10 +15,14 @@ group :development, :test do
15
15
  gem "sinatra", "~> 1.3"
16
16
 
17
17
  if Gem.ruby_version >= Gem::Version.new("1.9.0")
18
- gem "faraday", ">= 0.9"
18
+ gem "faraday", ">= 0.9", "< 2.0"
19
19
  gem "dalli", "~> 2.0"
20
20
  end
21
21
 
22
+ if Gem.ruby_version >= Gem::Version.new("3.0.0")
23
+ gem 'webrick'
24
+ end
25
+
22
26
  gem "redis", "~> 3.0"
23
27
 
24
28
  if RUBY_PLATFORM == "java"
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 [![CI](https://github.com/typhoeus/typhoeus/actions/workflows/ci.yml/badge.svg)](https://github.com/typhoeus/typhoeus/actions/workflows/ci.yml) [![Experimental](https://github.com/typhoeus/typhoeus/actions/workflows/experimental.yml/badge.svg)](https://github.com/typhoeus/typhoeus/actions/workflows/experimental.yml) [![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,19 +19,20 @@ hydra.run
19
19
  ```
20
20
 
21
21
  ## Installation
22
-
22
+ Run:
23
23
  ```
24
- gem install typhoeus
24
+ bundle add typhoeus
25
25
  ```
26
26
 
27
+ Or install it yourself as:
28
+
27
29
  ```
28
- gem "typhoeus"
30
+ gem install typhoeus
29
31
  ```
30
32
 
31
33
  ## Project Tracking
32
34
 
33
- * [Documentation](http://rubydoc.info/github/typhoeus/typhoeus/frames/Typhoeus) (GitHub master)
34
- * [Mailing list](http://groups.google.com/group/typhoeus)
35
+ * [API Documentation](https://rubydoc.info/github/typhoeus/typhoeus/frames/Typhoeus) (GitHub master)
35
36
 
36
37
  ## Usage
37
38
 
@@ -191,6 +192,19 @@ end
191
192
  request.run
192
193
  ```
193
194
 
195
+ If you need to interrupt the stream halfway,
196
+ you can return the `:abort` symbol from the `on_body` block, example:
197
+
198
+ ```ruby
199
+ request.on_body do |chunk|
200
+ buffer << chunk
201
+ :abort if buffer.size > 1024 * 1024
202
+ end
203
+ ```
204
+
205
+ This will properly stop the stream internally and avoid any memory leak which
206
+ may happen if you interrupt with something like a `return`, `throw` or `raise`.
207
+
194
208
  ### Making Parallel Requests
195
209
 
196
210
  Generally, you should be running requests through hydra. Here is how that looks:
@@ -242,6 +256,33 @@ end
242
256
  hydra.run
243
257
  ```
244
258
 
259
+ ### Making Parallel Requests with Faraday + Typhoeus
260
+
261
+ ```ruby
262
+ require 'faraday'
263
+
264
+ conn = Faraday.new(:url => 'http://httppage.com') do |builder|
265
+ builder.request :url_encoded
266
+ builder.response :logger
267
+ builder.adapter :typhoeus
268
+ end
269
+
270
+ conn.in_parallel do
271
+ response1 = conn.get('/first')
272
+ response2 = conn.get('/second')
273
+
274
+ # these will return nil here since the
275
+ # requests have not been completed
276
+ response1.body
277
+ response2.body
278
+ end
279
+
280
+ # after it has been completed the response information is fully available
281
+ # response1.status, etc
282
+ response1.body
283
+ response2.body
284
+ ```
285
+
245
286
  ### Specifying Max Concurrency
246
287
 
247
288
  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.
@@ -307,6 +348,8 @@ Typhoeus.get("www.example.com").cached?
307
348
  For use with [Dalli](https://github.com/mperham/dalli):
308
349
 
309
350
  ```ruby
351
+ require "typhoeus/cache/dalli"
352
+
310
353
  dalli = Dalli::Client.new(...)
311
354
  Typhoeus::Config.cache = Typhoeus::Cache::Dalli.new(dalli)
312
355
  ```
@@ -314,12 +357,16 @@ Typhoeus::Config.cache = Typhoeus::Cache::Dalli.new(dalli)
314
357
  For use with Rails:
315
358
 
316
359
  ```ruby
360
+ require "typhoeus/cache/rails"
361
+
317
362
  Typhoeus::Config.cache = Typhoeus::Cache::Rails.new
318
363
  ```
319
364
 
320
365
  For use with [Redis](https://github.com/redis/redis-rb):
321
366
 
322
367
  ```ruby
368
+ require "typhoeus/cache/redis"
369
+
323
370
  redis = Redis.new(...)
324
371
  Typhoeus::Config.cache = Typhoeus::Cache::Redis.new(redis)
325
372
  ```
@@ -327,6 +374,14 @@ Typhoeus::Config.cache = Typhoeus::Cache::Redis.new(redis)
327
374
  All three of these adapters take an optional keyword argument `default_ttl`, which sets a default
328
375
  TTL on cached responses (in seconds), for requests which do not have a cache TTL set.
329
376
 
377
+ You may also selectively choose not to cache by setting `cache` to `false` on a request or to use
378
+ a different adapter.
379
+
380
+ ```ruby
381
+ cache = Cache.new
382
+ Typhoeus.get("www.example.com", cache: cache)
383
+ ```
384
+
330
385
  ### Direct Stubbing
331
386
 
332
387
  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
  #
@@ -44,6 +44,22 @@ module Typhoeus
44
44
  # @see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTVERBOSE
45
45
  attr_accessor :verbose
46
46
 
47
+ # Defines the default HTTP timeout for the entire request in seconds
48
+ # See README for more details about timeouts
49
+ #
50
+ # @return [ Integer, Float ]
51
+ #
52
+ # @see https://curl.haxx.se/libcurl/c/curl_easy_setopt#CURLOPTTIMEOUT
53
+ attr_accessor :timeout
54
+
55
+ # Defines the default HTTP timeout for the connection phase in seconds
56
+ # See README for more details about timeouts
57
+ #
58
+ # @return [ Integer, Float ]
59
+ #
60
+ # @see https://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTCONNECTTIMEOUT
61
+ attr_accessor :connecttimeout
62
+
47
63
  # Defines whether requests are cached.
48
64
  #
49
65
  # @return [ Object ]
@@ -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.
@@ -78,11 +78,17 @@ module Typhoeus
78
78
  # @return [ Ethon::Easy ] The easy.
79
79
  def get
80
80
  begin
81
+ read_callback_body = request.options.delete(:set_read_callback)
82
+
81
83
  easy.http_request(
82
84
  request.base_url.to_s,
83
85
  request.options.fetch(:method, :get),
84
86
  sanitize(request.options)
85
87
  )
88
+
89
+ # this needs to happen after http_request because
90
+ # ethon will set infilesize to zero if form.empty?
91
+ set_read_callback(read_callback_body) if !read_callback_body.nil?
86
92
  rescue Ethon::Errors::InvalidOption => e
87
93
  help = provide_help(e.message.match(/:\s(\w+)/)[1])
88
94
  raise $!, "#{$!}#{help}", $!.backtrace
@@ -97,7 +103,7 @@ module Typhoeus
97
103
  # set nosignal to true by default
98
104
  # this improves thread safety and timeout behavior
99
105
  sanitized = {:nosignal => true}
100
- request.options.each do |k,v|
106
+ options.each do |k,v|
101
107
  s = k.to_sym
102
108
  next if SANITIZE_IGNORE.include?(s)
103
109
  if new_option = RENAMED_OPTIONS[k.to_sym]
@@ -155,6 +161,11 @@ module Typhoeus
155
161
  request.execute_headers_callbacks(Response.new(Ethon::Easy::Mirror.from_easy(easy).options))
156
162
  end
157
163
  end
164
+ request.on_progress.each do |callback|
165
+ easy.on_progress do |dltotal, dlnow, ultotal, ulnow, easy|
166
+ callback.call(dltotal, dlnow, ultotal, ulnow, response)
167
+ end
168
+ end
158
169
  easy.on_complete do |easy|
159
170
  request.finish(Response.new(easy.mirror.options))
160
171
  Typhoeus::Pool.release(easy)
@@ -164,6 +175,26 @@ module Typhoeus
164
175
  end
165
176
  end
166
177
 
178
+ # Sets up an easy upload with CURLOPT_READFUNCTION
179
+ # along with CURLOPT_INFILESIZE_LARGE and CURLOPT_UPLOAD
180
+ #
181
+ # @param [ String/File ] body The body read by the readfunction.
182
+ #
183
+ # @return [ Ethon::Easy ] The easy.
184
+ def set_read_callback(body)
185
+ easy.infilesize_large =
186
+ if body.respond_to?(:bytesize)
187
+ body.bytesize
188
+ elsif body.respond_to?(:size)
189
+ body.size
190
+ end
191
+
192
+ easy.upload = true
193
+ easy.set_read_callback(body)
194
+
195
+ easy
196
+ end
197
+
167
198
  def provide_help(option)
168
199
  if new_option = CHANGED_OPTIONS[option.to_sym]
169
200
  "\nPlease try #{new_option} instead of #{option}." if new_option
@@ -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
  #
@@ -214,6 +214,8 @@ module Typhoeus
214
214
  options[:headers] = {'User-Agent' => default_user_agent}.merge(options[:headers] || {})
215
215
  options[:headers]['Expect'] ||= ''
216
216
  options[:verbose] = Typhoeus::Config.verbose if options[:verbose].nil? && !Typhoeus::Config.verbose.nil?
217
+ options[:timeout] = Typhoeus::Config.timeout if options[:timeout].nil? && !Typhoeus::Config.timeout.nil?
218
+ options[:connecttimeout] = Typhoeus::Config.connecttimeout if options[:connecttimeout].nil? && !Typhoeus::Config.connecttimeout.nil?
217
219
  options[:maxredirs] ||= 50
218
220
  options[:proxy] = Typhoeus::Config.proxy unless options.has_key?(:proxy) || Typhoeus::Config.proxy.nil?
219
221
  end
@@ -1,3 +1,5 @@
1
+ require 'delegate'
2
+
1
3
  module Typhoeus
2
4
  class Response
3
5
 
@@ -210,10 +210,67 @@ module Typhoeus
210
210
  options[:redirect_count]
211
211
  end
212
212
 
213
+ # Return the URL a redirect would take you to, had you enabled redirects.
214
+ #
215
+ # @example Get redirect_url.
216
+ # response.redirect_url
217
+ #
218
+ # @return [ String ] The redirect_url.
219
+ def redirect_url
220
+ options[:redirect_url]
221
+ end
222
+
213
223
  def request_size
214
224
  options[:request_size]
215
225
  end
216
226
 
227
+ # Return the bytes, the total amount of bytes that were uploaded
228
+ #
229
+ # @example Get size_upload.
230
+ # response.size_upload
231
+ #
232
+ # @return [ Float ] The size_upload.
233
+ def size_upload
234
+ options[:size_upload]
235
+ end
236
+
237
+
238
+ # Return the bytes, the total amount of bytes that were downloaded.
239
+ # The amount is only for the latest transfer and will be reset again
240
+ # for each new transfer. This counts actual payload data, what's
241
+ # also commonly called body. All meta and header data are excluded
242
+ # and will not be counted in this number.
243
+ #
244
+ # @example Get size_download
245
+ # response.size_download
246
+ #
247
+ # @return [ Float ] The size_download.
248
+ def size_download
249
+ options[:size_download]
250
+ end
251
+
252
+ # Return the bytes/second, the average upload speed that curl
253
+ # measured for the complete upload
254
+ #
255
+ # @example Get speed_upload.
256
+ # response.speed_upload
257
+ #
258
+ # @return [ Float ] The speed_upload.
259
+ def speed_upload
260
+ options[:speed_upload]
261
+ end
262
+
263
+ # Return the bytes/second, the average download speed that curl
264
+ # measured for the complete download
265
+ #
266
+ # @example Get speed_download.
267
+ # response.speed_download
268
+ #
269
+ # @return [ Float ] The speed_download.
270
+ def speed_download
271
+ options[:speed_download]
272
+ end
273
+
217
274
  def debug_info
218
275
  options[:debug_info]
219
276
  end
@@ -39,7 +39,7 @@ 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?
@@ -49,13 +49,12 @@ module Typhoeus
49
49
  (mock || return_code == :ok) && response_code && has_good_response_code?
50
50
  end
51
51
 
52
- # Return wether the response is a failure.
52
+ # Return whether the response is a failure.
53
53
  #
54
54
  # @example Return if the response was failed.
55
55
  # response.failure?
56
56
  #
57
57
  # @return [ Boolean ] Return true if failure, false else.
58
-
59
58
  def failure?
60
59
  (mock || return_code == :internal_server_error) && response_code && has_bad_response_code?
61
60
  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.3.0'
4
+ VERSION = '1.4.1'
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
 
@@ -2,7 +2,13 @@ require 'spec_helper'
2
2
 
3
3
  describe Typhoeus::Request do
4
4
  let(:base_url) { "localhost:3001" }
5
- let(:options) { {:verbose => true, :headers => { 'User-Agent' => "Fubar", 'Expect' => "" }, :maxredirs => 50} }
5
+ let(:options) do
6
+ {
7
+ verbose: true,
8
+ headers: { "User-Agent" => "Fubar", "Expect" => "" },
9
+ maxredirs: 50
10
+ }
11
+ end
6
12
  let(:request) { Typhoeus::Request.new(base_url, options) }
7
13
 
8
14
  describe ".url" do
@@ -95,6 +101,24 @@ describe Typhoeus::Request do
95
101
  end
96
102
  end
97
103
 
104
+ context "when Config.timeout set" do
105
+ before { Typhoeus.configure { |config| config.timeout = 10 } }
106
+ after { Typhoeus.configure { |config| config.timeout = nil } }
107
+
108
+ it "respects configuration" do
109
+ expect(request.options[:timeout]).to eq(10)
110
+ end
111
+ end
112
+
113
+ context "when Config.connecttimeout set" do
114
+ before { Typhoeus.configure { |config| config.connecttimeout = 10 } }
115
+ after { Typhoeus.configure { |config| config.connecttimeout = nil } }
116
+
117
+ it "respects configuration" do
118
+ expect(request.options[:connecttimeout]).to eq(10)
119
+ end
120
+ end
121
+
98
122
  context "when maxredirs" do
99
123
  context "when not set" do
100
124
  it "defaults to 50" do
@@ -195,6 +195,14 @@ describe Typhoeus::Response::Informations do
195
195
  end
196
196
  end
197
197
 
198
+ describe "#redirect_url" do
199
+ let(:options) { { :redirect_url => "http://www.example.com" } }
200
+
201
+ it "returns redirect_url from options" do
202
+ expect(response.redirect_url).to eq("http://www.example.com")
203
+ end
204
+ end
205
+
198
206
  describe "#request_size" do
199
207
  let(:options) { { :request_size => 2 } }
200
208
 
@@ -203,6 +211,38 @@ describe Typhoeus::Response::Informations do
203
211
  end
204
212
  end
205
213
 
214
+ describe "#size_upload" do
215
+ let(:options) { { :size_upload => 2.0 } }
216
+
217
+ it "returns size_upload from options" do
218
+ expect(response.size_upload).to eq(2.0)
219
+ end
220
+ end
221
+
222
+ describe "#size_download" do
223
+ let(:options) { { :size_download => 2.0 } }
224
+
225
+ it "returns size_download from options" do
226
+ expect(response.size_download).to eq(2.0)
227
+ end
228
+ end
229
+
230
+ describe "#speed_upload" do
231
+ let(:options) { { :speed_upload => 2.0 } }
232
+
233
+ it "returns speed_upload from options" do
234
+ expect(response.speed_upload).to eq(2.0)
235
+ end
236
+ end
237
+
238
+ describe "#speed_download" do
239
+ let(:options) { { :speed_download => 2.0 } }
240
+
241
+ it "returns speed_download from options" do
242
+ expect(response.speed_download).to eq(2.0)
243
+ end
244
+ end
245
+
206
246
  describe "#headers" do
207
247
  context "when no response_headers" do
208
248
  it "returns nil" do
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typhoeus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Balatero
8
8
  - Paul Dix
9
9
  - Hans Hasselberg
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-08-21 00:00:00.000000000 Z
13
+ date: 2023-11-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: ethon
@@ -34,9 +34,10 @@ executables: []
34
34
  extensions: []
35
35
  extra_rdoc_files: []
36
36
  files:
37
+ - ".github/workflows/ci.yml"
38
+ - ".github/workflows/experimental.yml"
37
39
  - ".gitignore"
38
40
  - ".rspec"
39
- - ".travis.yml"
40
41
  - CHANGELOG.md
41
42
  - CONTRIBUTING.md
42
43
  - Gemfile
@@ -134,7 +135,7 @@ homepage: https://github.com/typhoeus/typhoeus
134
135
  licenses:
135
136
  - MIT
136
137
  metadata: {}
137
- post_install_message:
138
+ post_install_message:
138
139
  rdoc_options: []
139
140
  require_paths:
140
141
  - lib
@@ -149,9 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
150
  - !ruby/object:Gem::Version
150
151
  version: 1.3.6
151
152
  requirements: []
152
- rubyforge_project:
153
- rubygems_version: 2.2.2
154
- signing_key:
153
+ rubygems_version: 3.3.7
154
+ signing_key:
155
155
  specification_version: 4
156
156
  summary: Parallel HTTP library on top of libcurl multi.
157
157
  test_files:
data/.travis.yml DELETED
@@ -1,22 +0,0 @@
1
- language: ruby
2
- script: "bundle exec rake"
3
- sudo: false
4
- rvm:
5
- - 1.8.7
6
- - 1.9.2
7
- - 1.9.3
8
- - 2.0.0
9
- - 2.1.8
10
- - 2.2.4
11
- - 2.3.0
12
- - 2.4.1
13
- - ruby-head
14
- - jruby-head
15
- - jruby-18mode
16
- - jruby-19mode
17
- matrix:
18
- fast_finish: true
19
- allow_failures:
20
- - rvm: ruby-head
21
- - rvm: jruby-head
22
- - rvm: ree