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 +4 -4
- data/.travis.yml +11 -6
- data/CHANGELOG.md +13 -1
- data/CONTRIBUTING.md +4 -0
- data/README.md +55 -4
- data/lib/typhoeus/adapters/faraday.rb +3 -3
- data/lib/typhoeus/cache/dalli.rb +3 -1
- data/lib/typhoeus/cache/rails.rb +4 -2
- data/lib/typhoeus/cache/redis.rb +3 -1
- data/lib/typhoeus/config.rb +1 -1
- data/lib/typhoeus/easy_factory.rb +7 -2
- data/lib/typhoeus/hydra/cacheable.rb +1 -1
- 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/response/header.rb +11 -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 +4 -3
- data/spec/typhoeus/adapters/faraday_spec.rb +1 -1
- data/spec/typhoeus/easy_factory_spec.rb +6 -0
- data/spec/typhoeus/hydra/cacheable_spec.rb +31 -1
- data/spec/typhoeus/pool_spec.rb +4 -2
- 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/response/header_spec.rb +43 -6
- data/spec/typhoeus/response/informations_spec.rb +12 -1
- data/spec/typhoeus/response/status_spec.rb +54 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79bd3451f6ec67ea973d9dc62dc4645c21e2eba1
|
4
|
+
data.tar.gz: 762e3c44e97fc0f2241d5cbf9d2a9ff2caa8a53a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
10
|
-
- 2.2.
|
11
|
-
- 2.3.
|
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.
|
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/
|
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
|
24
|
+
gem "typhoeus"
|
25
25
|
```
|
26
|
+
Then run `bundle install`
|
27
|
+
|
28
|
+
Or install it yourself as:
|
26
29
|
|
27
30
|
```
|
28
|
-
gem
|
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::
|
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::
|
106
|
+
raise Faraday::ConnectionFailed, resp.return_message
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
data/lib/typhoeus/cache/dalli.rb
CHANGED
@@ -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 [
|
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
|
data/lib/typhoeus/cache/rails.rb
CHANGED
@@ -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 [
|
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
|
data/lib/typhoeus/cache/redis.rb
CHANGED
@@ -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 [
|
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
|
data/lib/typhoeus/config.rb
CHANGED
@@ -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
|
-
|
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)
|
@@ -15,7 +15,7 @@ module Typhoeus
|
|
15
15
|
#
|
16
16
|
# @option (see Typhoeus::Request#initialize)
|
17
17
|
#
|
18
|
-
# @return (see Typhoeus::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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
|
-
|
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
|
#
|
@@ -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
|
-
|
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.
|
41
|
+
raw.split(/\r?\n(?!\s)/).each do |header|
|
36
42
|
header.strip!
|
37
|
-
next if header.empty? || header.start_with?( 'HTTP/
|
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
|
-
|
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
@@ -127,11 +127,12 @@ module Typhoeus
|
|
127
127
|
# #=> :ok
|
128
128
|
# end
|
129
129
|
#
|
130
|
-
# @
|
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
|
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::
|
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
|
data/spec/typhoeus/pool_spec.rb
CHANGED
@@ -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
|
-
|
91
|
+
queue = Queue.new
|
92
92
|
(0..9).map do |n|
|
93
93
|
Thread.new do
|
94
|
-
|
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
|
97
|
-
|
98
|
-
|
99
|
-
|
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.
|
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:
|
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.
|
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.
|