typhoeus 0.6.3 → 0.6.4

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.
Files changed (61) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +8 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +10 -0
  5. data/CHANGELOG.md +7 -1
  6. data/CONTRIBUTING.md +16 -0
  7. data/Guardfile +9 -0
  8. data/README.md +303 -1
  9. data/UPGRADE.md +55 -0
  10. data/lib/rack/typhoeus/middleware/params_decoder.rb +1 -1
  11. data/lib/rack/typhoeus/middleware/params_decoder/helper.rb +6 -2
  12. data/lib/typhoeus/adapters/faraday.rb +4 -1
  13. data/lib/typhoeus/easy_factory.rb +36 -15
  14. data/lib/typhoeus/hydra/before.rb +2 -1
  15. data/lib/typhoeus/hydra/cacheable.rb +1 -0
  16. data/lib/typhoeus/hydra/memoizable.rb +1 -0
  17. data/lib/typhoeus/hydra/queueable.rb +15 -3
  18. data/lib/typhoeus/request.rb +6 -2
  19. data/lib/typhoeus/request/marshal.rb +3 -2
  20. data/lib/typhoeus/response/informations.rb +4 -0
  21. data/lib/typhoeus/version.rb +1 -1
  22. data/perf/profile.rb +14 -0
  23. data/perf/vs_nethttp.rb +64 -0
  24. data/spec/rack/typhoeus/middleware/params_decoder/helper_spec.rb +132 -0
  25. data/spec/rack/typhoeus/middleware/params_decoder_spec.rb +31 -0
  26. data/spec/spec_helper.rb +35 -0
  27. data/spec/support/localhost_server.rb +94 -0
  28. data/spec/support/server.rb +108 -0
  29. data/spec/typhoeus/adapters/faraday_spec.rb +245 -0
  30. data/spec/typhoeus/config_spec.rb +15 -0
  31. data/spec/typhoeus/easy_factory_spec.rb +96 -0
  32. data/spec/typhoeus/errors/no_stub_spec.rb +13 -0
  33. data/spec/typhoeus/expectation_spec.rb +273 -0
  34. data/spec/typhoeus/hydra/addable_spec.rb +22 -0
  35. data/spec/typhoeus/hydra/before_spec.rb +97 -0
  36. data/spec/typhoeus/hydra/block_connection_spec.rb +18 -0
  37. data/spec/typhoeus/hydra/cacheable_spec.rb +68 -0
  38. data/spec/typhoeus/hydra/memoizable_spec.rb +53 -0
  39. data/spec/typhoeus/hydra/queueable_spec.rb +34 -0
  40. data/spec/typhoeus/hydra/runnable_spec.rb +155 -0
  41. data/spec/typhoeus/hydra/stubbable_spec.rb +28 -0
  42. data/spec/typhoeus/hydra_spec.rb +26 -0
  43. data/spec/typhoeus/pool_spec.rb +79 -0
  44. data/spec/typhoeus/request/actions_spec.rb +19 -0
  45. data/spec/typhoeus/request/before_spec.rb +92 -0
  46. data/spec/typhoeus/request/block_connection_spec.rb +75 -0
  47. data/spec/typhoeus/request/cacheable_spec.rb +80 -0
  48. data/spec/typhoeus/request/callbacks_spec.rb +91 -0
  49. data/spec/typhoeus/request/marshal_spec.rb +62 -0
  50. data/spec/typhoeus/request/memoizable_spec.rb +34 -0
  51. data/spec/typhoeus/request/operations_spec.rb +70 -0
  52. data/spec/typhoeus/request/responseable_spec.rb +13 -0
  53. data/spec/typhoeus/request/stubbable_spec.rb +27 -0
  54. data/spec/typhoeus/request_spec.rb +131 -0
  55. data/spec/typhoeus/response/header_spec.rb +97 -0
  56. data/spec/typhoeus/response/informations_spec.rb +218 -0
  57. data/spec/typhoeus/response/status_spec.rb +218 -0
  58. data/spec/typhoeus/response_spec.rb +81 -0
  59. data/spec/typhoeus_spec.rb +105 -0
  60. data/typhoeus.gemspec +25 -0
  61. metadata +101 -27
@@ -36,7 +36,7 @@ module Rack
36
36
  private
37
37
 
38
38
  # Persist params change in environment. Extracted from:
39
- # https://github.com/rack/rack/blob/master/lib/rack/request.rb#L233
39
+ # https://github.com/rack/rack/blob/master/lib/rack/request.rb#L243
40
40
  def update_params(req, k, v)
41
41
  found = false
42
42
  if req.GET.has_key?(k)
@@ -48,8 +48,12 @@ module Rack
48
48
  # @return [Boolean] True if its a encoded Array, else false.
49
49
  def encoded?(hash)
50
50
  return false if hash.empty?
51
- keys = hash.keys.map{|i| i.to_i if i.respond_to?(:to_i)}.sort
52
- keys == hash.keys.size.times.to_a
51
+ if hash.keys.size > 1
52
+ keys = hash.keys.map{|i| i.to_i if i.respond_to?(:to_i)}.sort
53
+ keys == hash.keys.size.times.to_a
54
+ else
55
+ hash.keys.first =~ /0/
56
+ end
53
57
  end
54
58
 
55
59
  # If the Hash is an array encoded by typhoeus an array is returned
@@ -110,8 +110,11 @@ module Faraday # :nodoc:
110
110
  def configure_ssl(req, env)
111
111
  ssl = env[:ssl]
112
112
 
113
- ssl_verifyhost = (ssl && ssl.fetch(:verify, true)) ? 2 : 0
113
+ verify_p = (ssl && ssl.fetch(:verify, true))
114
+
115
+ ssl_verifyhost = verify_p ? 2 : 0
114
116
  req.options[:ssl_verifyhost] = ssl_verifyhost
117
+ req.options[:ssl_verifypeer] = verify_p
115
118
  req.options[:sslversion] = ssl[:version] if ssl[:version]
116
119
  req.options[:sslcert] = ssl[:client_cert] if ssl[:client_cert]
117
120
  req.options[:sslkey] = ssl[:client_key] if ssl[:client_key]
@@ -51,7 +51,7 @@ module Typhoeus
51
51
  easy.http_request(
52
52
  request.base_url,
53
53
  request.options.fetch(:method, :get),
54
- request.options.reject{ |k,_| [:method, :cache_ttl].include?(k) }
54
+ sanitize(request.options)
55
55
  )
56
56
  rescue Ethon::Errors::InvalidOption => e
57
57
  help = provide_help(e.message.match(/:\s(\w+)/)[1])
@@ -63,6 +63,20 @@ module Typhoeus
63
63
 
64
64
  private
65
65
 
66
+ def sanitize(options)
67
+ sanitized = {}
68
+ request.options.each do |k,v|
69
+ next if [:method, :cache_ttl].include?(k.to_sym)
70
+ if new_option = renamed_options[k.to_sym]
71
+ warn("Deprecated option #{k}. Please use #{new_option} instead.")
72
+ sanitized[new_option] = v
73
+ else
74
+ sanitized[k] = v
75
+ end
76
+ end
77
+ sanitized
78
+ end
79
+
66
80
  # Sets on_complete callback on easy in order to be able to
67
81
  # track progress.
68
82
  #
@@ -72,28 +86,22 @@ module Typhoeus
72
86
  # @return [ Ethon::Easy ] The easy.
73
87
  def set_callback
74
88
  easy.on_complete do |easy|
75
- request.finish(Response.new(easy.to_hash))
89
+ request.finish(Response.new(easy.mirror.options))
76
90
  Typhoeus::Pool.release(easy)
77
91
  if hydra && !hydra.queued_requests.empty?
78
- hydra.add(hydra.queued_requests.shift)
92
+ hydra.dequeue
79
93
  end
80
94
  end
81
95
  end
82
96
 
83
- def provide_help(option)
84
- renamed = {
97
+ def renamed_options
98
+ {
85
99
  :auth_method => :httpauth,
86
100
  :connect_timeout => :connecttimeout,
87
- :disable_ssl_host_verification => :ssl_verifyhost,
88
- :disable_ssl_peer_verification => :ssl_verifypeer,
89
101
  :encoding => :accept_encoding,
90
102
  :follow_location => :followlocation,
91
103
  :max_redirects => :maxredirs,
92
- :password => :userpwd,
93
- :proxy_auth_method => :proxyauth,
94
- :proxy_password => :proxyuserpwd,
95
104
  :proxy_type => :proxytype,
96
- :proxy_username => :proxyuserpwd,
97
105
  :ssl_cacert => :cainfo,
98
106
  :ssl_capath => :capath,
99
107
  :ssl_cert => :sslcert,
@@ -102,12 +110,25 @@ module Typhoeus
102
110
  :ssl_key_password => :keypasswd,
103
111
  :ssl_key_type => :sslkeytype,
104
112
  :ssl_version => :sslversion,
105
- :username => :userpwd
106
113
  }
107
- removed = [:cache_key_basis, :cache_timout, :user_agent]
108
- if new_option = renamed[option.to_sym]
114
+ end
115
+
116
+ def changed_options
117
+ {
118
+ :disable_ssl_host_verification => :ssl_verifyhost,
119
+ :disable_ssl_peer_verification => :ssl_verifypeer,
120
+ :proxy_auth_method => :proxyauth,
121
+ }
122
+ end
123
+
124
+ def removed_options
125
+ [:cache_key_basis, :cache_timeout, :user_agent]
126
+ end
127
+
128
+ def provide_help(option)
129
+ if new_option = changed_options[option.to_sym]
109
130
  "\nPlease try #{new_option} instead of #{option}." if new_option
110
- elsif removed.include?(option.to_sym)
131
+ elsif removed_options.include?(option.to_sym)
111
132
  "\nThe option #{option} was removed."
112
133
  end
113
134
  end
@@ -11,7 +11,7 @@ module Typhoeus
11
11
 
12
12
  # Overrride add in order to execute callbacks in
13
13
  # Typhoeus.before. Will break and return when a
14
- # callback returns nil or false. Calls super
14
+ # callback returns nil, false or a response. Calls super
15
15
  # otherwise.
16
16
  #
17
17
  # @example Add the request.
@@ -20,6 +20,7 @@ module Typhoeus
20
20
  Typhoeus.before.each do |callback|
21
21
  value = callback.call(request)
22
22
  if value.nil? || value == false || value.is_a?(Response)
23
+ dequeue
23
24
  return value
24
25
  end
25
26
  end
@@ -4,6 +4,7 @@ module Typhoeus
4
4
  def add(request)
5
5
  if request.cacheable? && response = Typhoeus::Config.cache.get(request)
6
6
  request.finish(response)
7
+ dequeue
7
8
  else
8
9
  super
9
10
  end
@@ -36,6 +36,7 @@ module Typhoeus
36
36
  if request.memoizable? && memory.has_key?(request)
37
37
  response = memory[request]
38
38
  request.finish(response, true)
39
+ dequeue
39
40
  else
40
41
  super
41
42
  end
@@ -10,7 +10,7 @@ module Typhoeus
10
10
  # Return the queued requests.
11
11
  #
12
12
  # @example Return queued requests.
13
- # hydra.queued_requests
13
+ # hydra.queued_requests
14
14
  #
15
15
  # @return [ Array<Typhoeus::Request> ] The queued requests.
16
16
  def queued_requests
@@ -23,7 +23,7 @@ module Typhoeus
23
23
  # anything about already running requests.
24
24
  #
25
25
  # @example Abort hydra.
26
- # hydra.abort
26
+ # hydra.abort
27
27
  def abort
28
28
  queued_requests.clear
29
29
  end
@@ -34,11 +34,23 @@ module Typhoeus
34
34
  # request.
35
35
  #
36
36
  # @example Queue request.
37
- # hydra.queue(request)
37
+ # hydra.queue(request)
38
38
  def queue(request)
39
39
  request.hydra = self
40
40
  queued_requests << request
41
41
  end
42
+
43
+ # Removes a request from queued_requests and
44
+ # adds it to the hydra in order to be
45
+ # performed next.
46
+ #
47
+ # @example Dequeue request.
48
+ # hydra.dequeue
49
+ #
50
+ # @since 0.6.4
51
+ def dequeue
52
+ add(queued_requests.shift) unless queued_requests.empty?
53
+ end
42
54
  end
43
55
  end
44
56
  end
@@ -1,3 +1,4 @@
1
+ require 'zlib'
1
2
  require 'typhoeus/request/actions'
2
3
  require 'typhoeus/request/before'
3
4
  require 'typhoeus/request/block_connection'
@@ -123,7 +124,10 @@ module Typhoeus
123
124
  #
124
125
  # @since 0.5.5
125
126
  def url
126
- EasyFactory.new(self).get.url
127
+ easy = EasyFactory.new(self).get
128
+ url = easy.url
129
+ Typhoeus::Pool.release(easy)
130
+ url
127
131
  end
128
132
 
129
133
  # Returns whether other is equal to self.
@@ -148,7 +152,7 @@ module Typhoeus
148
152
  #
149
153
  # @api private
150
154
  def hash
151
- Digest::MD5.hexdigest("#{self.class.name}#{base_url}#{options}").to_i(16)
155
+ Zlib.crc32 "#{self.class.name}#{base_url}#{options}"
152
156
  end
153
157
 
154
158
  private
@@ -5,9 +5,10 @@ module Typhoeus
5
5
  module Marshal
6
6
 
7
7
  # Return the important data needed to serialize this Request, except the
8
- # `on_complete` handler, since they cannot be marshalled.
8
+ # `on_complete`, `on_success`, `on_failure`, and `hydra`, since they cannot be marshalled.
9
9
  def marshal_dump
10
- (instance_variables - ['@on_complete', :@on_complete]).map do |name|
10
+ unmarshallable = %w(@on_complete @on_success @on_failure @hydra)
11
+ (instance_variables - unmarshallable - unmarshallable.map(&:to_sym)).map do |name|
11
12
  [name, instance_variable_get(name)]
12
13
  end
13
14
  end
@@ -188,6 +188,10 @@ module Typhoeus
188
188
  options[:redirect_count]
189
189
  end
190
190
 
191
+ def debug_info
192
+ options[:debug_info]
193
+ end
194
+
191
195
  # Returns the response header.
192
196
  #
193
197
  # @example Return headers.
@@ -1,5 +1,5 @@
1
1
  module Typhoeus
2
2
 
3
3
  # The current Typhoeus version.
4
- VERSION = '0.6.3'
4
+ VERSION = '0.6.4'
5
5
  end
data/perf/profile.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'typhoeus'
2
+ require 'ruby-prof'
3
+
4
+ calls = 50
5
+ base_url = "http://127.0.0.1:3000/"
6
+
7
+ RubyProf.start
8
+ calls.times do |i|
9
+ Typhoeus::Request.get(base_url+i.to_s)
10
+ end
11
+ result = RubyProf.stop
12
+
13
+ printer = RubyProf::FlatPrinter.new(result)
14
+ printer.print(STDOUT)
@@ -0,0 +1,64 @@
1
+ require 'typhoeus'
2
+ require 'net/http'
3
+ require 'open-uri'
4
+ require 'benchmark'
5
+
6
+ URL = "http://localhost:300"
7
+ hydra = Typhoeus::Hydra.new(max_concurrency: 3)
8
+
9
+ if defined? require_relative
10
+ require_relative '../spec/support/localhost_server.rb'
11
+ require_relative '../spec/support/server.rb'
12
+ else
13
+ require '../spec/support/localhost_server.rb'
14
+ require '../spec/support/server.rb'
15
+ end
16
+ LocalhostServer.new(TESTSERVER.new, 3000)
17
+ LocalhostServer.new(TESTSERVER.new, 3001)
18
+ LocalhostServer.new(TESTSERVER.new, 3002)
19
+
20
+ def url_for(i)
21
+ "#{URL}#{i%3}/"
22
+ end
23
+
24
+ Benchmark.bm do |bm|
25
+
26
+ [1000].each do |calls|
27
+ puts "[ #{calls} requests ]"
28
+
29
+ bm.report("net/http ") do
30
+ calls.times do |i|
31
+ uri = URI.parse(url_for(i))
32
+ Net::HTTP.get_response(uri)
33
+ end
34
+ end
35
+
36
+ bm.report("open ") do
37
+ calls.times do |i|
38
+ open(url_for(i))
39
+ end
40
+ end
41
+
42
+ bm.report("request ") do
43
+ calls.times do |i|
44
+ Typhoeus::Request.get(url_for(i))
45
+ end
46
+ end
47
+
48
+ bm.report("hydra ") do
49
+ calls.times do |i|
50
+ hydra.queue(Typhoeus::Request.new(url_for(i)))
51
+ end
52
+ hydra.run
53
+ end
54
+
55
+ bm.report("hydra memoize ") do
56
+ Typhoeus::Config.memoize = true
57
+ calls.times do |i|
58
+ hydra.queue(Typhoeus::Request.new(url_for(i)))
59
+ end
60
+ hydra.run
61
+ Typhoeus::Config.memoize = false
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,132 @@
1
+ require 'spec_helper'
2
+ require "rack/typhoeus"
3
+
4
+ describe "Rack::Typhoeus::Middleware::ParamsDecoder::Helper" do
5
+
6
+ let(:klass) do
7
+ Class.new do
8
+ include Rack::Typhoeus::Middleware::ParamsDecoder::Helper
9
+ end.new
10
+ end
11
+
12
+ describe "#decode" do
13
+ let(:decoded) { klass.decode(params) }
14
+ let(:params) { { :array => {'0' => :a, '1' => :b } } }
15
+
16
+ it "decodes" do
17
+ expect(decoded[:array]).to match_array([:a, :b])
18
+ end
19
+
20
+ it "doesn't modify" do
21
+ expect(decoded).to_not be(params)
22
+ end
23
+ end
24
+
25
+ describe "#decode!" do
26
+ let(:decoded) { klass.decode!(params) }
27
+
28
+ context "when hash" do
29
+ context "when encoded" do
30
+ context "when simple" do
31
+ let(:params) { { :array => {'0' => :a, '1' => :b } } }
32
+
33
+ it "decodes" do
34
+ expect(decoded[:array]).to match_array([:a, :b])
35
+ end
36
+
37
+ it "modifies" do
38
+ expect(decoded).to eq(params)
39
+ end
40
+ end
41
+
42
+ context "when nested" do
43
+ let(:params) do
44
+ { :array => { '0' => 0, '1' => { '0' => 'sub0', '1' => 'sub1' } } }
45
+ end
46
+
47
+ it "decodes" do
48
+ expect(decoded[:array]).to include(0)
49
+ expect(decoded[:array].find{|e| e.is_a?(Array)}).to(
50
+ match_array(['sub0', 'sub1'])
51
+ )
52
+ end
53
+
54
+ it "modifies" do
55
+ expect(decoded).to eq(params)
56
+ end
57
+ end
58
+ end
59
+
60
+ context "when not encoded" do
61
+ let(:params) { {:a => :a} }
62
+
63
+ it "doesn't modify" do
64
+ expect(decoded).to be(params)
65
+ end
66
+ end
67
+ end
68
+
69
+ context "when no hash" do
70
+ let(:params) { "a" }
71
+
72
+ it "returns self" do
73
+ expect(decoded).to be(params)
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "#encoded?" do
79
+ let(:encoded) { klass.send(:encoded?, params) }
80
+
81
+ context "when there is only one key" do
82
+ context "and its 0" do
83
+ let(:params){ {'0' => 1} }
84
+ it 'returns true' do
85
+ expect(encoded).to be_true
86
+ end
87
+ end
88
+ context "and its not 0" do
89
+ let(:params){ {'some-key' => 1}}
90
+ it 'returns false' do
91
+ expect(encoded).to be_false
92
+ end
93
+ end
94
+ end
95
+
96
+ context "when keys are ascending numbers starting with zero" do
97
+ let(:params) { Hash[12.times.map {|i| [i, (i+65).chr]}] }
98
+
99
+ it "returns true" do
100
+ expect(encoded).to be_true
101
+ end
102
+ end
103
+
104
+ context "when keys are not ascending numbers starting with zero" do
105
+ let(:params) { {:a => 1} }
106
+
107
+ it "returns false" do
108
+ expect(encoded).to be_false
109
+ end
110
+ end
111
+ end
112
+
113
+ describe "#convert" do
114
+ let(:converted) { klass.send(:convert, params) }
115
+
116
+ context "when encoded" do
117
+ let(:params) { {'0' => :a, '1' => :b} }
118
+
119
+ it "returns values" do
120
+ expect(converted).to match_array([:a, :b])
121
+ end
122
+ end
123
+
124
+ context "when not encoded" do
125
+ let(:params) { {:a => :a} }
126
+
127
+ it "returns unmodified" do
128
+ expect(converted).to be(params)
129
+ end
130
+ end
131
+ end
132
+ end