typhoeus 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
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