tech-angels-typhoeus 0.1.36

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 (44) hide show
  1. data/.gitignore +2 -0
  2. data/README.textile +312 -0
  3. data/Rakefile +39 -0
  4. data/VERSION +1 -0
  5. data/benchmarks/profile.rb +25 -0
  6. data/benchmarks/vs_nethttp.rb +35 -0
  7. data/examples/twitter.rb +21 -0
  8. data/ext/typhoeus/.gitignore +5 -0
  9. data/ext/typhoeus/Makefile +157 -0
  10. data/ext/typhoeus/extconf.rb +65 -0
  11. data/ext/typhoeus/native.c +11 -0
  12. data/ext/typhoeus/native.h +21 -0
  13. data/ext/typhoeus/typhoeus_easy.c +207 -0
  14. data/ext/typhoeus/typhoeus_easy.h +19 -0
  15. data/ext/typhoeus/typhoeus_multi.c +225 -0
  16. data/ext/typhoeus/typhoeus_multi.h +16 -0
  17. data/lib/typhoeus.rb +55 -0
  18. data/lib/typhoeus/.gitignore +1 -0
  19. data/lib/typhoeus/easy.rb +329 -0
  20. data/lib/typhoeus/filter.rb +28 -0
  21. data/lib/typhoeus/hydra.rb +235 -0
  22. data/lib/typhoeus/multi.rb +35 -0
  23. data/lib/typhoeus/remote.rb +306 -0
  24. data/lib/typhoeus/remote_method.rb +108 -0
  25. data/lib/typhoeus/remote_proxy_object.rb +48 -0
  26. data/lib/typhoeus/request.rb +159 -0
  27. data/lib/typhoeus/response.rb +49 -0
  28. data/lib/typhoeus/service.rb +20 -0
  29. data/profilers/valgrind.rb +24 -0
  30. data/spec/fixtures/result_set.xml +60 -0
  31. data/spec/servers/app.rb +73 -0
  32. data/spec/spec.opts +2 -0
  33. data/spec/spec_helper.rb +11 -0
  34. data/spec/typhoeus/easy_spec.rb +236 -0
  35. data/spec/typhoeus/filter_spec.rb +35 -0
  36. data/spec/typhoeus/hydra_spec.rb +311 -0
  37. data/spec/typhoeus/multi_spec.rb +74 -0
  38. data/spec/typhoeus/remote_method_spec.rb +141 -0
  39. data/spec/typhoeus/remote_proxy_object_spec.rb +65 -0
  40. data/spec/typhoeus/remote_spec.rb +695 -0
  41. data/spec/typhoeus/request_spec.rb +169 -0
  42. data/spec/typhoeus/response_spec.rb +63 -0
  43. data/typhoeus.gemspec +112 -0
  44. metadata +203 -0
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'sinatra'
4
+ require 'json'
5
+
6
+ @@fail_count = 0
7
+ get '/fail/:number' do
8
+ if @@fail_count >= params[:number].to_i
9
+ "ok"
10
+ else
11
+ @@fail_count += 1
12
+ error 500, "oh noes!"
13
+ end
14
+ end
15
+
16
+ get '/fail_forever' do
17
+ error 500, "oh noes!"
18
+ end
19
+
20
+ get '/redirect' do
21
+ redirect '/'
22
+ end
23
+
24
+ get '/bad_redirect' do
25
+ redirect '/bad_redirect'
26
+ end
27
+
28
+ get '/auth_basic/:username/:password' do
29
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
30
+ # Check that we've got a basic auth, and that it's credentials match the ones
31
+ # provided in the request
32
+ if @auth.provided? && @auth.basic? && @auth.credentials == [ params[:username], params[:password] ]
33
+ # auth is valid - confirm it
34
+ true
35
+ else
36
+ # invalid auth - request the authentication
37
+ response['WWW-Authenticate'] = %(Basic realm="Testing HTTP Auth")
38
+ throw(:halt, [401, "Not authorized\n"])
39
+ end
40
+ end
41
+
42
+ get '/auth_ntlm' do
43
+ # we're just checking for the existence if NTLM auth header here. It's validation
44
+ # is too troublesome and really doesn't bother is much, it's up to libcurl to make
45
+ # it valid
46
+ is_ntlm_auth = /^NTLM/ =~ request.env['HTTP_AUTHORIZATION']
47
+ true if is_ntlm_auth
48
+ throw(:halt, [401, "Not authorized\n"]) if !is_ntlm_auth
49
+ end
50
+
51
+ get '/**' do
52
+ sleep params["delay"].to_i if params.has_key?("delay")
53
+ request.env.merge!(:body => request.body.read).to_json
54
+ end
55
+
56
+ head '/**' do
57
+ sleep params["delay"].to_i if params.has_key?("delay")
58
+ end
59
+
60
+ put '/**' do
61
+ puts request.inspect
62
+ request.env.merge!(:body => request.body.read).to_json
63
+ end
64
+
65
+ post '/**' do
66
+ puts request.inspect
67
+ request.env.merge!(:body => request.body.read).to_json
68
+ end
69
+
70
+ delete '/**' do
71
+ puts request.inspect
72
+ request.env.merge!(:body => request.body.read).to_json
73
+ end
@@ -0,0 +1,2 @@
1
+ --diff
2
+ --color
@@ -0,0 +1,11 @@
1
+ require "rubygems"
2
+ require 'json'
3
+ require "spec"
4
+
5
+ # gem install redgreen for colored test output
6
+ begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end
7
+
8
+ path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
9
+ $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
10
+
11
+ require "lib/typhoeus"
@@ -0,0 +1,236 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Typhoeus::Easy do
4
+ describe "#supports_zlib" do
5
+ before(:each) do
6
+ @easy = Typhoeus::Easy.new
7
+ end
8
+
9
+ it "should return true if the version string has zlib" do
10
+ @easy.stub!(:curl_version).and_return("libcurl/7.20.0 OpenSSL/0.9.8l zlib/1.2.3 libidn/1.16")
11
+ @easy.supports_zlib?.should be_true
12
+ end
13
+
14
+ it "should return false if the version string doesn't have zlib" do
15
+ @easy.stub!(:curl_version).and_return("libcurl/7.20.0 OpenSSL/0.9.8l libidn/1.16")
16
+ @easy.supports_zlib?.should be_false
17
+ end
18
+ end
19
+
20
+ describe "options" do
21
+ it "should not follow redirects if not instructed to" do
22
+ e = Typhoeus::Easy.new
23
+ e.url = "http://localhost:3001/redirect"
24
+ e.method = :get
25
+ e.perform
26
+ e.response_code.should == 302
27
+ end
28
+
29
+ it "should allow for following redirects" do
30
+ e = Typhoeus::Easy.new
31
+ e.url = "http://localhost:3001/redirect"
32
+ e.method = :get
33
+ e.follow_location = true
34
+ e.perform
35
+ e.response_code.should == 200
36
+ JSON.parse(e.response_body)["REQUEST_METHOD"].should == "GET"
37
+ end
38
+
39
+ it "should allow you to set the user agent" do
40
+ easy = Typhoeus::Easy.new
41
+ easy.url = "http://localhost:3002"
42
+ easy.method = :get
43
+ easy.user_agent = "myapp"
44
+ easy.perform
45
+ easy.response_code.should == 200
46
+ JSON.parse(easy.response_body)["HTTP_USER_AGENT"].should == "myapp"
47
+ end
48
+
49
+ it "should provide a timeout in milliseconds" do
50
+ e = Typhoeus::Easy.new
51
+ e.url = "http://localhost:3001"
52
+ e.method = :get
53
+ e.timeout = 50
54
+ e.perform
55
+ # this doesn't work on a mac for some reason
56
+ # e.timed_out?.should == true
57
+ end
58
+
59
+ it "should allow the setting of the max redirects to follow" do
60
+ e = Typhoeus::Easy.new
61
+ e.url = "http://localhost:3001/redirect"
62
+ e.method = :get
63
+ e.follow_location = true
64
+ e.max_redirects = 5
65
+ e.perform
66
+ e.response_code.should == 200
67
+ end
68
+
69
+ it "should handle our bad redirect action, provided we've set max_redirects properly" do
70
+ e = Typhoeus::Easy.new
71
+ e.url = "http://localhost:3001/bad_redirect"
72
+ e.method = :get
73
+ e.follow_location = true
74
+ e.max_redirects = 5
75
+ e.perform
76
+ e.response_code.should == 302
77
+ end
78
+ end
79
+
80
+ describe "authentication" do
81
+ it "should allow to set username and password" do
82
+ e = Typhoeus::Easy.new
83
+ username, password = 'foo', 'bar'
84
+ e.auth = { :username => username, :password => password }
85
+ e.url = "http://localhost:3001/auth_basic/#{username}/#{password}"
86
+ e.method = :get
87
+ e.perform
88
+ e.response_code.should == 200
89
+ end
90
+
91
+ it "should allow to query auth methods support by the server" do
92
+ e = Typhoeus::Easy.new
93
+ e.url = "http://localhost:3001/auth_basic/foo/bar"
94
+ e.method = :get
95
+ e.perform
96
+ e.auth_methods.should == Typhoeus::Easy::AUTH_TYPES[:CURLAUTH_BASIC]
97
+ end
98
+
99
+ it "should allow to set authentication method" do
100
+ e = Typhoeus::Easy.new
101
+ e.auth = { :username => 'username', :password => 'password', :method => Typhoeus::Easy::AUTH_TYPES[:CURLAUTH_NTLM] }
102
+ e.url = "http://localhost:3001/auth_ntlm"
103
+ e.method = :get
104
+ e.perform
105
+ e.response_code.should == 200
106
+ end
107
+ end
108
+
109
+ describe "get" do
110
+ it "should perform a get" do
111
+ easy = Typhoeus::Easy.new
112
+ easy.url = "http://localhost:3002"
113
+ easy.method = :get
114
+ easy.perform
115
+ easy.response_code.should == 200
116
+ JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "GET"
117
+ end
118
+ end
119
+
120
+ describe "purge" do
121
+ it "should set custom request to purge" do
122
+ easy = Typhoeus::Easy.new
123
+ easy.should_receive(:set_option).with(Typhoeus::Easy::OPTION_VALUES[:CURLOPT_CUSTOMREQUEST], "PURGE").once
124
+ easy.method = :purge
125
+ end
126
+ end
127
+
128
+ describe "head" do
129
+ it "should perform a head" do
130
+ easy = Typhoeus::Easy.new
131
+ easy.url = "http://localhost:3002"
132
+ easy.method = :head
133
+ easy.perform
134
+ easy.response_code.should == 200
135
+ end
136
+ end
137
+
138
+ describe "start_time" do
139
+ it "should be get/settable" do
140
+ time = Time.now
141
+ easy = Typhoeus::Easy.new
142
+ easy.start_time.should be_nil
143
+ easy.start_time = time
144
+ easy.start_time.should == time
145
+ end
146
+ end
147
+
148
+ describe "params=" do
149
+ it "should handle arrays of params" do
150
+ easy = Typhoeus::Easy.new
151
+ easy.url = "http://localhost:3002/index.html"
152
+ easy.method = :get
153
+ easy.request_body = "this is a body!"
154
+ easy.params = {
155
+ :foo => 'bar',
156
+ :username => ['dbalatero', 'dbalatero2']
157
+ }
158
+
159
+ easy.url.should =~ /\?.*username=dbalatero&username=dbalatero2/
160
+ end
161
+ end
162
+
163
+
164
+ describe "put" do
165
+ it "should perform a put" do
166
+ easy = Typhoeus::Easy.new
167
+ easy.url = "http://localhost:3002"
168
+ easy.method = :put
169
+ easy.perform
170
+ easy.response_code.should == 200
171
+ JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "PUT"
172
+ end
173
+
174
+ it "should send a request body" do
175
+ easy = Typhoeus::Easy.new
176
+ easy.url = "http://localhost:3002"
177
+ easy.method = :put
178
+ easy.request_body = "this is a body!"
179
+ easy.perform
180
+ easy.response_code.should == 200
181
+ easy.response_body.should include("this is a body!")
182
+ end
183
+ end
184
+
185
+ describe "post" do
186
+ it "should perform a post" do
187
+ easy = Typhoeus::Easy.new
188
+ easy.url = "http://localhost:3002"
189
+ easy.method = :post
190
+ easy.perform
191
+ easy.response_code.should == 200
192
+ JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "POST"
193
+ end
194
+
195
+ it "should send a request body" do
196
+ easy = Typhoeus::Easy.new
197
+ easy.url = "http://localhost:3002"
198
+ easy.method = :post
199
+ easy.request_body = "this is a body!"
200
+ easy.perform
201
+ easy.response_code.should == 200
202
+ easy.response_body.should include("this is a body!")
203
+ end
204
+
205
+ it "should handle params" do
206
+ easy = Typhoeus::Easy.new
207
+ easy.url = "http://localhost:3002"
208
+ easy.method = :post
209
+ easy.params = {:foo => "bar"}
210
+ easy.perform
211
+ easy.response_code.should == 200
212
+ easy.response_body.should include("foo=bar")
213
+ end
214
+ end
215
+
216
+ describe "delete" do
217
+ it "should perform a delete" do
218
+ easy = Typhoeus::Easy.new
219
+ easy.url = "http://localhost:3002"
220
+ easy.method = :delete
221
+ easy.perform
222
+ easy.response_code.should == 200
223
+ JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "DELETE"
224
+ end
225
+
226
+ it "should send a request body" do
227
+ easy = Typhoeus::Easy.new
228
+ easy.url = "http://localhost:3002"
229
+ easy.method = :delete
230
+ easy.request_body = "this is a body!"
231
+ easy.perform
232
+ easy.response_code.should == 200
233
+ easy.response_body.should include("this is a body!")
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,35 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Typhoeus::Filter do
4
+ it "should take a method name and optionally take options" do
5
+ filter = Typhoeus::Filter.new(:bar, :only => :foo)
6
+ filter = Typhoeus::Filter.new(:bar)
7
+ end
8
+
9
+ describe "#apply_filter?" do
10
+ it "should return true for any method when :only and :except aren't specified" do
11
+ filter = Typhoeus::Filter.new(:bar)
12
+ filter.apply_filter?(:asdf).should be_true
13
+ end
14
+
15
+ it "should return true if a method is in only" do
16
+ filter = Typhoeus::Filter.new(:bar, :only => :foo)
17
+ filter.apply_filter?(:foo).should be_true
18
+ end
19
+
20
+ it "should return false if a method isn't in only" do
21
+ filter = Typhoeus::Filter.new(:bar, :only => :foo)
22
+ filter.apply_filter?(:bar).should be_false
23
+ end
24
+
25
+ it "should return true if a method isn't in except" do
26
+ filter = Typhoeus::Filter.new(:bar, :except => :foo)
27
+ filter.apply_filter?(:bar).should be_true
28
+ end
29
+
30
+ it "should return false if a method is in except" do
31
+ filter = Typhoeus::Filter.new(:bar, :except => :foo)
32
+ filter.apply_filter?(:foo).should be_false
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,311 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ # some of these tests assume that you have some local services running.
4
+ # ruby spec/servers/app.rb -p 3000
5
+ # ruby spec/servers/app.rb -p 3001
6
+ # ruby spec/servers/app.rb -p 3002
7
+ describe Typhoeus::Hydra do
8
+ before(:all) do
9
+ cache_class = Class.new do
10
+ def initialize
11
+ @cache = {}
12
+ end
13
+ def get(key)
14
+ @cache[key]
15
+ end
16
+ def set(key, object, timeout = 0)
17
+ @cache[key] = object
18
+ end
19
+ end
20
+ @cache = cache_class.new
21
+ end
22
+
23
+ it "has a singleton" do
24
+ Typhoeus::Hydra.hydra.should be_a Typhoeus::Hydra
25
+ end
26
+
27
+ it "has a setter for the singleton" do
28
+ Typhoeus::Hydra.hydra = :foo
29
+ Typhoeus::Hydra.hydra.should == :foo
30
+ Typhoeus::Hydra.hydra = Typhoeus::Hydra.new
31
+ end
32
+
33
+ context "#stub" do
34
+ before do
35
+ @hydra = Typhoeus::Hydra.new
36
+ @on_complete_handler_called = nil
37
+ @request = Typhoeus::Request.new("http://localhost:3000/foo")
38
+ @request.on_complete do |response|
39
+ @on_complete_handler_called = true
40
+ response.code.should == 404
41
+ response.headers.should == "whatever"
42
+ end
43
+ @response = Typhoeus::Response.new(:code => 404, :headers => "whatever", :body => "not found", :time => 0.1)
44
+ end
45
+
46
+ it "stubs requests to a specific URI" do
47
+ @hydra.stub(:get, "http://localhost:3000/foo").and_return(@response)
48
+ @hydra.queue(@request)
49
+ @hydra.run
50
+ @on_complete_handler_called.should be_true
51
+ @response.request.should == @request
52
+ end
53
+
54
+ it "stubs requests to URIs matching a pattern" do
55
+ @hydra.stub(:get, /foo/).and_return(@response)
56
+ @hydra.queue(@request)
57
+ @hydra.run
58
+ @on_complete_handler_called.should be_true
59
+ @response.request.should == @request
60
+ end
61
+
62
+ it "can clear stubs" do
63
+ @hydra.clear_stubs
64
+ end
65
+
66
+ it "clears out previously queued requests once they are called" do
67
+ @hydra.stub(:get, "asdf").and_return(@response)
68
+
69
+ call_count = 0
70
+ request = Typhoeus::Request.new("asdf")
71
+ request.on_complete do |response|
72
+ call_count += 1
73
+ end
74
+ @hydra.queue(request)
75
+ @hydra.run
76
+ call_count.should == 1
77
+ @hydra.run
78
+ call_count.should == 1
79
+ end
80
+
81
+ it "calls stubs for requests that are queued up in the on_complete of a first stub" do
82
+ @hydra.stub(:get, "asdf").and_return(@response)
83
+ @hydra.stub(:get, "bar").and_return(@response)
84
+
85
+ second_handler_called = false
86
+ request = Typhoeus::Request.new("asdf")
87
+ request.on_complete do |response|
88
+ r = Typhoeus::Request.new("bar")
89
+ r.on_complete do |res|
90
+ second_handler_called = true
91
+ end
92
+ @hydra.queue(r)
93
+ end
94
+ @hydra.queue(request)
95
+ @hydra.run
96
+
97
+ second_handler_called.should be_true
98
+ end
99
+
100
+ it "matches a stub only when the HTTP method also matches"
101
+ end
102
+
103
+ it "queues a request" do
104
+ hydra = Typhoeus::Hydra.new
105
+ hydra.queue Typhoeus::Request.new("http://localhost:3000")
106
+ end
107
+
108
+ it "runs a batch of requests" do
109
+ hydra = Typhoeus::Hydra.new
110
+ first = Typhoeus::Request.new("http://localhost:3000/first")
111
+ second = Typhoeus::Request.new("http://localhost:3001/second")
112
+ hydra.queue first
113
+ hydra.queue second
114
+ hydra.run
115
+ first.response.body.should include("first")
116
+ second.response.body.should include("second")
117
+ end
118
+
119
+ it "has a cache_setter proc" do
120
+ hydra = Typhoeus::Hydra.new
121
+ hydra.cache_setter do |request|
122
+ # @cache.set(request.cache_key, request.response, request.cache_timeout)
123
+ end
124
+ end
125
+
126
+ it "has a cache_getter" do
127
+ hydra = Typhoeus::Hydra.new
128
+ hydra.cache_getter do |request|
129
+ # @cache.get(request.cache_key) rescue nil
130
+ end
131
+ end
132
+
133
+ it "memoizes GET reqeusts" do
134
+ hydra = Typhoeus::Hydra.new
135
+ first = Typhoeus::Request.new("http://localhost:3000/foo", :params => {:delay => 1})
136
+ second = Typhoeus::Request.new("http://localhost:3000/foo", :params => {:delay => 1})
137
+ hydra.queue first
138
+ hydra.queue second
139
+ start_time = Time.now
140
+ hydra.run
141
+ first.response.body.should include("foo")
142
+ first.handled_response.body.should include("foo")
143
+ first.response.should == second.response
144
+ first.handled_response.should == second.handled_response
145
+ (Time.now - start_time).should < 1.2 # if it had run twice it would be ~ 2 seconds
146
+ end
147
+
148
+ it "can turn off memoization for GET requests" do
149
+ hydra = Typhoeus::Hydra.new
150
+ hydra.disable_memoization
151
+ first = Typhoeus::Request.new("http://localhost:3000/foo")
152
+ second = Typhoeus::Request.new("http://localhost:3000/foo")
153
+ hydra.queue first
154
+ hydra.queue second
155
+ hydra.run
156
+ first.response.body.should include("foo")
157
+ first.response.object_id.should_not == second.response.object_id
158
+ end
159
+
160
+ it "pulls GETs from cache" do
161
+ hydra = Typhoeus::Hydra.new
162
+ start_time = Time.now
163
+ hydra.cache_getter do |request|
164
+ @cache.get(request.cache_key) rescue nil
165
+ end
166
+ hydra.cache_setter do |request|
167
+ @cache.set(request.cache_key, request.response, request.cache_timeout)
168
+ end
169
+
170
+ first = Typhoeus::Request.new("http://localhost:3000/foo", :params => {:delay => 1})
171
+ @cache.set(first.cache_key, :foo, 60)
172
+ hydra.queue first
173
+ hydra.run
174
+ (Time.now - start_time).should < 0.1
175
+ first.response.should == :foo
176
+ end
177
+
178
+ it "sets GET responses to cache when the request has a cache_timeout value" do
179
+ hydra = Typhoeus::Hydra.new
180
+ hydra.cache_getter do |request|
181
+ @cache.get(request.cache_key) rescue nil
182
+ end
183
+ hydra.cache_setter do |request|
184
+ @cache.set(request.cache_key, request.response, request.cache_timeout)
185
+ end
186
+
187
+ first = Typhoeus::Request.new("http://localhost:3000/first", :cache_timeout => 0)
188
+ second = Typhoeus::Request.new("http://localhost:3000/second")
189
+ hydra.queue first
190
+ hydra.queue second
191
+ hydra.run
192
+ first.response.body.should include("first")
193
+ @cache.get(first.cache_key).should == first.response
194
+ @cache.get(second.cache_key).should be_nil
195
+ end
196
+
197
+ it "has a global on_complete" do
198
+ foo = nil
199
+ hydra = Typhoeus::Hydra.new
200
+ hydra.on_complete do |response|
201
+ foo = :called
202
+ end
203
+
204
+ first = Typhoeus::Request.new("http://localhost:3000/first")
205
+ hydra.queue first
206
+ hydra.run
207
+ first.response.body.should include("first")
208
+ foo.should == :called
209
+ end
210
+
211
+ it "has a global on_complete setter" do
212
+ foo = nil
213
+ hydra = Typhoeus::Hydra.new
214
+ proc = Proc.new {|response| foo = :called}
215
+ hydra.on_complete = proc
216
+
217
+ first = Typhoeus::Request.new("http://localhost:3000/first")
218
+ hydra.queue first
219
+ hydra.run
220
+ first.response.body.should include("first")
221
+ foo.should == :called
222
+ end
223
+
224
+ it "should reuse connections from the pool for a host"
225
+
226
+ it "should queue up requests while others are running" do
227
+ hydra = Typhoeus::Hydra.new
228
+
229
+ start_time = Time.now
230
+ @responses = []
231
+
232
+ request = Typhoeus::Request.new("http://localhost:3000/first", :params => {:delay => 1})
233
+ request.on_complete do |response|
234
+ @responses << response
235
+ response.body.should include("first")
236
+ end
237
+
238
+ request.after_complete do |object|
239
+ second_request = Typhoeus::Request.new("http://localhost:3001/second", :params => {:delay => 2})
240
+ second_request.on_complete do |response|
241
+ @responses << response
242
+ response.body.should include("second")
243
+ end
244
+ hydra.queue second_request
245
+ end
246
+ hydra.queue request
247
+
248
+ third_request = Typhoeus::Request.new("http://localhost:3002/third", :params => {:delay => 3})
249
+ third_request.on_complete do |response|
250
+ @responses << response
251
+ response.body.should include("third")
252
+ end
253
+ hydra.queue third_request
254
+
255
+ hydra.run
256
+ @responses.size.should == 3
257
+ (Time.now - start_time).should < 3.3
258
+ end
259
+
260
+ it "should fire and forget" do
261
+ # this test is totally hacky. I have no clue how to make it verify. I just look at the test servers
262
+ # to verify that stuff is running
263
+ hydra = Typhoeus::Hydra.new
264
+ first = Typhoeus::Request.new("http://localhost:3000/first?delay=1")
265
+ second = Typhoeus::Request.new("http://localhost:3001/second?delay=2")
266
+ hydra.queue first
267
+ hydra.queue second
268
+ hydra.fire_and_forget
269
+ third = Typhoeus::Request.new("http://localhost:3002/third?delay=3")
270
+ hydra.queue third
271
+ hydra.fire_and_forget
272
+ sleep 3 # have to do this or future tests may break.
273
+ end
274
+
275
+ it "should take the maximum number of concurrent requests as an argument" do
276
+ hydra = Typhoeus::Hydra.new(:max_concurrency => 2)
277
+ first = Typhoeus::Request.new("http://localhost:3000/first?delay=1")
278
+ second = Typhoeus::Request.new("http://localhost:3001/second?delay=1")
279
+ third = Typhoeus::Request.new("http://localhost:3002/third?delay=1")
280
+ hydra.queue first
281
+ hydra.queue second
282
+ hydra.queue third
283
+
284
+ start_time = Time.now
285
+ hydra.run
286
+ finish_time = Time.now
287
+
288
+ first.response.code.should == 200
289
+ second.response.code.should == 200
290
+ third.response.code.should == 200
291
+ (finish_time - start_time).should > 2.0
292
+ end
293
+
294
+ it "should respect the follow_location option when set on a request" do
295
+ hydra = Typhoeus::Hydra.new
296
+ request = Typhoeus::Request.new("http://localhost:3000/redirect", :follow_location => true)
297
+ hydra.queue request
298
+ hydra.run
299
+
300
+ request.response.code.should == 200
301
+ end
302
+
303
+ it "should pass through the max_redirects option when set on a request" do
304
+ hydra = Typhoeus::Hydra.new
305
+ request = Typhoeus::Request.new("http://localhost:3000/bad_redirect", :max_redirects => 5)
306
+ hydra.queue request
307
+ hydra.run
308
+
309
+ request.response.code.should == 302
310
+ end
311
+ end