typhoeus 0.4.2 → 0.5.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +86 -28
- data/Gemfile +17 -1
- data/README.md +20 -422
- data/Rakefile +21 -12
- data/lib/typhoeus.rb +58 -41
- data/lib/typhoeus/config.rb +14 -0
- data/lib/typhoeus/errors.rb +9 -0
- data/lib/typhoeus/errors/no_stub.rb +12 -0
- data/lib/typhoeus/errors/typhoeus_error.rb +8 -0
- data/lib/typhoeus/expectation.rb +126 -0
- data/lib/typhoeus/hydra.rb +31 -236
- data/lib/typhoeus/hydras/block_connection.rb +33 -0
- data/lib/typhoeus/hydras/easy_factory.rb +67 -0
- data/lib/typhoeus/hydras/easy_pool.rb +40 -0
- data/lib/typhoeus/hydras/memoizable.rb +53 -0
- data/lib/typhoeus/hydras/queueable.rb +46 -0
- data/lib/typhoeus/hydras/runnable.rb +18 -0
- data/lib/typhoeus/hydras/stubbable.rb +27 -0
- data/lib/typhoeus/request.rb +68 -243
- data/lib/typhoeus/requests/actions.rb +101 -0
- data/lib/typhoeus/requests/block_connection.rb +31 -0
- data/lib/typhoeus/requests/callbacks.rb +82 -0
- data/lib/typhoeus/requests/marshal.rb +21 -0
- data/lib/typhoeus/requests/memoizable.rb +36 -0
- data/lib/typhoeus/requests/operations.rb +52 -0
- data/lib/typhoeus/requests/responseable.rb +29 -0
- data/lib/typhoeus/requests/stubbable.rb +29 -0
- data/lib/typhoeus/response.rb +24 -118
- data/lib/typhoeus/responses/header.rb +50 -0
- data/lib/typhoeus/responses/informations.rb +43 -0
- data/lib/typhoeus/responses/legacy.rb +27 -0
- data/lib/typhoeus/responses/status.rb +78 -0
- data/lib/typhoeus/version.rb +3 -1
- metadata +34 -141
- data/lib/typhoeus/curl.rb +0 -453
- data/lib/typhoeus/easy.rb +0 -115
- data/lib/typhoeus/easy/auth.rb +0 -14
- data/lib/typhoeus/easy/callbacks.rb +0 -33
- data/lib/typhoeus/easy/ffi_helper.rb +0 -61
- data/lib/typhoeus/easy/infos.rb +0 -90
- data/lib/typhoeus/easy/options.rb +0 -115
- data/lib/typhoeus/easy/proxy.rb +0 -20
- data/lib/typhoeus/easy/ssl.rb +0 -82
- data/lib/typhoeus/filter.rb +0 -28
- data/lib/typhoeus/form.rb +0 -61
- data/lib/typhoeus/header.rb +0 -54
- data/lib/typhoeus/hydra/callbacks.rb +0 -24
- data/lib/typhoeus/hydra/connect_options.rb +0 -61
- data/lib/typhoeus/hydra/stubbing.rb +0 -68
- data/lib/typhoeus/hydra_mock.rb +0 -131
- data/lib/typhoeus/multi.rb +0 -146
- data/lib/typhoeus/param_processor.rb +0 -43
- data/lib/typhoeus/remote.rb +0 -306
- data/lib/typhoeus/remote_method.rb +0 -108
- data/lib/typhoeus/remote_proxy_object.rb +0 -50
- data/lib/typhoeus/utils.rb +0 -50
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,76 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 0.5.0.pre
|
4
|
+
|
5
|
+
[Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.4.2...master)
|
6
|
+
|
7
|
+
Major Changes:
|
8
|
+
|
9
|
+
* Ethon integration
|
10
|
+
* Params are url params and a body is always a body for every request type
|
11
|
+
* Request parameter and body are properly encoded (only POST multiform body is not)
|
12
|
+
* No more header sanitizing
|
13
|
+
|
14
|
+
Before: `:headers => { 'user_agent' => 'Custom' }` was modified to
|
15
|
+
`:headers => { 'User-Agent' => 'Custom' }`
|
16
|
+
|
17
|
+
* The options you can set might have a slightly other names, as Ethon sticks to
|
18
|
+
libcurl names. See
|
19
|
+
[Easy.new](http://rubydoc.info/github/typhoeus/ethon/Ethon/Easy#initialize-instance_method)
|
20
|
+
for a description.
|
21
|
+
* The following classes were deleted because they do not seemed to be uesed at all. If that
|
22
|
+
turns out to be wrong, they will be restored: `Typhoeus::Filter`, `Typhoeus::Remote`, `Typhoeus::RemoteMethod`, `Typhoeus::RemoteProxyObject`
|
23
|
+
* `Typhoeus::Easy` and `Typhoeus::Multi` are now `Ethon::Easy` and `Ethon::Multi`
|
24
|
+
|
25
|
+
* Request shortcuts: `Typhoeus.get("www.google.de")`
|
26
|
+
* Global configuration:
|
27
|
+
```ruby
|
28
|
+
Typhoeus.configure do |config|
|
29
|
+
config.verbose = true
|
30
|
+
config.memoize = true
|
31
|
+
end
|
32
|
+
```
|
33
|
+
* No more Response#headers_hash, instead response#header returning the last
|
34
|
+
header and response#redirections returning the responses with headers
|
35
|
+
generated through redirections
|
36
|
+
* Instead of defining the same callbacks on every request, you can define global callbacks:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
Typhoeus.on_complete { p "yay" }
|
40
|
+
```
|
41
|
+
|
42
|
+
* The stubbing interface changed slightly. You now have the same syntax as for requests:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
Typhoeus.stub(url, options).and_return(response)
|
46
|
+
```
|
47
|
+
|
48
|
+
Enhancements:
|
49
|
+
|
50
|
+
* Documentation
|
51
|
+
( [Alex P](https://github.com/ifesdjeen), [\#188](https://github.com/typhoeus/typhoeus/issues/188) )
|
52
|
+
* Request#on\_complete can hold multiple blocks.
|
53
|
+
* Request#eql? recognizes when header/params/body has a different order, but still same keys and values
|
54
|
+
( [Alex P](https://github.com/ifesdjeen), [\#194](https://github.com/typhoeus/typhoeus/issues/194) )
|
55
|
+
|
56
|
+
Bug Fixes:
|
57
|
+
|
58
|
+
* Zero bytes in strings are escaped for libcurl
|
59
|
+
* Add support for socks5 hostname proxy type
|
60
|
+
( [eweathers](https://github.com/eweathers), [\#183](https://github.com/typhoeus/typhoeus/issues/183) )
|
61
|
+
* Post body is encoded
|
62
|
+
( [Rohan Deshpande](https://github.com/rdeshpande), [\#143](https://github.com/typhoeus/typhoeus/issues/143) )
|
63
|
+
* Set default user agent
|
64
|
+
( [Steven Shingler](https://github.com/sshingler), [\#176](https://github.com/typhoeus/typhoeus/issues/176) )
|
65
|
+
|
66
|
+
## 0.4.2
|
67
|
+
* A header hotfix
|
68
|
+
|
69
|
+
## 0.4.1
|
70
|
+
* Fix verifypeer and verifyhost options
|
71
|
+
* Fix header sending
|
72
|
+
|
73
|
+
## 0.4.0
|
3
74
|
* Make a GET even when a body is given
|
4
75
|
* Deprecated User Agent setter removed
|
5
76
|
* Allow cache key basis overwrite (John Crepezzi, #147)
|
@@ -7,14 +78,12 @@
|
|
7
78
|
* Refactor upload code (Marnen Laibow-Koser, #152)
|
8
79
|
* Fix travis-ci build (Ezekiel Templin, #160)
|
9
80
|
|
10
|
-
0.3.3
|
11
|
-
-----
|
81
|
+
## 0.3.3
|
12
82
|
* Make sure to call the Easy::failure callback on all non-success http response codes, even invalid ones. [balexis]
|
13
83
|
* Use bytesize instead of length to determine Content-Length [dlamacchia]
|
14
84
|
* Added SSL version option to Easy/Request [michelbarbosa/dbalatero]
|
15
85
|
|
16
|
-
0.3.2
|
17
|
-
-----
|
86
|
+
## 0.3.2
|
18
87
|
* Fix array params to be consistent with HTTP spec [gridaphobe]
|
19
88
|
* traversal\_to\_params\_hash should use the escape option [itsmeduncan]
|
20
89
|
* Fix > 1024 open file descriptors [mschulkind]
|
@@ -35,20 +104,16 @@
|
|
35
104
|
* Fix HTTP status edge-case [balexis]
|
36
105
|
* Expose primary\_ip to easy object [balexis]
|
37
106
|
|
38
|
-
0.2.4
|
39
|
-
-----
|
107
|
+
## 0.2.4
|
40
108
|
* Fix form POSTs to only use multipart for file uploads, otherwise use application/x-www-form-urlencoded [dbalatero]
|
41
109
|
|
42
|
-
0.2.3
|
43
|
-
-----
|
110
|
+
## 0.2.3
|
44
111
|
* Code duplication in Typhoeus::Form led to nested URL param errors on POST only. Fixed [dbalatero]
|
45
112
|
|
46
|
-
0.2.2
|
47
|
-
-----
|
113
|
+
## 0.2.2
|
48
114
|
* Fixed a problem with nested URL params encoding incorrectly [dbalatero]
|
49
115
|
|
50
|
-
0.2.1
|
51
|
-
-----
|
116
|
+
## 0.2.1
|
52
117
|
* Added extended proxy support [Zapotek, GH-46]
|
53
118
|
* eliminated compile time warnings by using proper type declarations [skaes, GH-54]
|
54
119
|
* fixed broken calls to rb\_raise [skaes, GH-54]
|
@@ -60,34 +125,27 @@
|
|
60
125
|
* added abort to Hydra to prematurely stop a hydra.run [Zapotek]
|
61
126
|
* added file upload support for POST requests [jtarchie, GH-59]
|
62
127
|
|
63
|
-
0.2.0
|
64
|
-
------
|
128
|
+
## 0.2.0
|
65
129
|
* Fix warning in Request#headers from attr\_accessor
|
66
|
-
* Params with array values were not parsing into the format that rack expects
|
67
|
-
[GH-39, smartocci]
|
130
|
+
* Params with array values were not parsing into the format that rack expects [GH-39, smartocci]
|
68
131
|
* Removed Rack as a dependency [GH-45]
|
69
132
|
* Added integration hooks for VCR!
|
70
133
|
|
71
|
-
0.1.31
|
72
|
-
------
|
134
|
+
## 0.1.31
|
73
135
|
* Fixed bug in setting compression encoding [morhekil]
|
74
136
|
* Exposed authentication control methods through Request interface [morhekil]
|
75
137
|
|
76
|
-
0.1.30
|
77
|
-
-----------
|
138
|
+
## 0.1.30
|
78
139
|
* Exposed CURLOPT\_CONNECTTIMEOUT\_MS to Requests [balexis]
|
79
140
|
|
80
|
-
0.1.29
|
81
|
-
------
|
141
|
+
## 0.1.29
|
82
142
|
* Fixed a memory corruption with using CURLOPT\_POSTFIELDS [gravis,
|
83
143
|
32531d0821aecc4]
|
84
144
|
|
85
|
-
0.1.28
|
86
|
-
----------------
|
145
|
+
## 0.1.28
|
87
146
|
* Added SSL cert options for Typhoeus::Easy [GH-25, gravis]
|
88
147
|
* Ported SSL cert options to Typhoeus::Request interface [gravis]
|
89
148
|
* Added support for any HTTP method (purge for Varnish) [ryana]
|
90
149
|
|
91
|
-
0.1.27
|
92
|
-
------
|
150
|
+
## 0.1.27
|
93
151
|
* Added rack as dependency, added dev dependencies to Rakefile [GH-21]
|
data/Gemfile
CHANGED
@@ -1,3 +1,19 @@
|
|
1
1
|
source :rubygems
|
2
|
-
|
3
2
|
gemspec
|
3
|
+
|
4
|
+
gem "rake"
|
5
|
+
|
6
|
+
group :development, :test do
|
7
|
+
gem "rspec", "~> 2.11"
|
8
|
+
|
9
|
+
gem "sinatra", "~> 1.3"
|
10
|
+
gem "json"
|
11
|
+
|
12
|
+
if RUBY_PLATFORM == "java"
|
13
|
+
gem "spoon"
|
14
|
+
end
|
15
|
+
|
16
|
+
unless ENV["CI"]
|
17
|
+
gem "guard-rspec", "~> 0.7"
|
18
|
+
end
|
19
|
+
end
|
data/README.md
CHANGED
@@ -1,438 +1,36 @@
|
|
1
|
-
#
|
1
|
+
# Typhoeus [![Build Status](https://secure.travis-ci.org/typhoeus/typhoeus.png)](http://travis-ci.org/typhoeus/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
|
|
5
|
-
##
|
5
|
+
## Example
|
6
6
|
|
7
|
-
|
8
|
-
Typhoeus runs HTTP requests in parallel while cleanly encapsulating handling
|
9
|
-
logic. To be a little more specific, it’s a library for accessing web services
|
10
|
-
in Ruby. It’s specifically designed for building RESTful service oriented
|
11
|
-
architectures in Ruby that need to be fast enough to process calls to multiple
|
12
|
-
services within the client’s HTTP request/response life cycle.
|
7
|
+
Single request:
|
13
8
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
whatever), and mocking capability baked in. It uses libcurl and libcurl-multi
|
18
|
-
to work this speedy magic. I wrote the bindings myself so it’s yet another
|
19
|
-
Ruby libcurl library, but with some extra awesomeness added in. FFI is used to
|
20
|
-
interface with the library so it works with any Ruby implementation.
|
9
|
+
```ruby
|
10
|
+
Typhoeus.get("www.example.com")
|
11
|
+
```
|
21
12
|
|
22
|
-
|
13
|
+
Parallel requests:
|
23
14
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
(earlier versions might work but no guarantees are provided).
|
15
|
+
```ruby
|
16
|
+
hydra = Typhoeus::Hydra.new
|
17
|
+
10.times.map{ hydra.queue(Typhoeus::Request.new("www.example.com")) }
|
18
|
+
hydra.run
|
19
|
+
```
|
30
20
|
|
31
|
-
|
21
|
+
## Project Tracking
|
32
22
|
|
33
|
-
|
23
|
+
* [Documentation](http://rubydoc.info/github/typhoeus/typhoeus)
|
24
|
+
* [Website](http://typhoeus.github.com/)
|
25
|
+
* [Mailinglist](http://groups.google.com/group/typhoeus)
|
34
26
|
|
35
|
-
|
36
|
-
could be because you don’t have the latest version of libcurl installed. Do
|
37
|
-
this to fix:
|
38
|
-
|
39
|
-
sudo apt-get install libcurl4-gnutls-dev
|
40
|
-
|
41
|
-
If you’re still having issues, please let me know on [the mailing
|
42
|
-
list](http://groups.google.com/group/typhoeus).
|
43
|
-
|
44
|
-
There’s one other thing you should know. The Easy object (which is just a
|
45
|
-
libcurl thing) allows you to set timeout values in milliseconds. However, for
|
46
|
-
this to work you need to build libcurl with c-ares support built in.
|
47
|
-
|
48
|
-
## Windows Support
|
49
|
-
|
50
|
-
Typhoeus runs perfectly on Windows. The tricky part is knowing how to install
|
51
|
-
libcurl in the absence of a package manager.
|
52
|
-
|
53
|
-
To install libcurl, simply grab [the latest libcurl
|
54
|
-
package](http://curl.haxx.se/download.html#Win32) off of the curl website,
|
55
|
-
extract the bin directory, and then add the path to the bin directory into the
|
56
|
-
PATH environment variable. Ruby with then be able to find libcurl properly and
|
57
|
-
everything will just work.
|
58
|
-
|
59
|
-
## Usage
|
60
|
-
|
61
|
-
The primary interface for Typhoeus is comprised of three classes: Request,
|
62
|
-
Response, and Hydra. Request represents an HTTP request object, response
|
63
|
-
represents an HTTP response, and Hydra manages making parallel HTTP
|
64
|
-
connections.
|
65
|
-
|
66
|
-
require 'rubygems'
|
67
|
-
require 'typhoeus'
|
68
|
-
require 'json'
|
69
|
-
|
70
|
-
# the request object
|
71
|
-
request = Typhoeus::Request.new("http://www.pauldix.net",
|
72
|
-
:body => "this is a request body",
|
73
|
-
:method => :post,
|
74
|
-
:headers => {:Accept => "text/html"},
|
75
|
-
:timeout => 100, # milliseconds
|
76
|
-
:cache_timeout => 60, # seconds
|
77
|
-
:params => {:field1 => "a field"})
|
78
|
-
# we can see from this that the first argument is the url. the second is a set of options.
|
79
|
-
# the options are all optional. The default for :method is :get. Timeout is measured in milliseconds.
|
80
|
-
# cache_timeout is measured in seconds.
|
81
|
-
|
82
|
-
# Run the request via Hydra.
|
83
|
-
hydra = Typhoeus::Hydra.new
|
84
|
-
hydra.queue(request)
|
85
|
-
hydra.run
|
86
|
-
|
87
|
-
# the response object will be set after the request is run
|
88
|
-
response = request.response
|
89
|
-
response.code # http status code
|
90
|
-
response.time # time in seconds the request took
|
91
|
-
response.headers # the http headers
|
92
|
-
response.headers_hash # http headers put into a hash
|
93
|
-
response.body # the response body
|
94
|
-
|
95
|
-
**Making Quick Requests**
|
96
|
-
|
97
|
-
The request object has some convenience methods for performing single HTTP
|
98
|
-
requests. The arguments are the same as those you pass into the request
|
99
|
-
constructor.
|
100
|
-
|
101
|
-
response = Typhoeus::Request.get("http://www.pauldix.net")
|
102
|
-
response = Typhoeus::Request.head("http://www.pauldix.net")
|
103
|
-
response = Typhoeus::Request.put("http://localhost:3000/posts/1", :body => "whoo, a body")
|
104
|
-
response = Typhoeus::Request.post("http://localhost:3000/posts", :params => {:title => "test post", :content => "this is my test"})
|
105
|
-
response = Typhoeus::Request.delete("http://localhost:3000/posts/1")
|
106
|
-
|
107
|
-
**Handling HTTP errors**
|
108
|
-
|
109
|
-
You can query the response object to figure out if you had a successful
|
110
|
-
request or not. Here’s some example code that you might use to handle errors.
|
111
|
-
|
112
|
-
request.on_complete do |response|
|
113
|
-
if response.success?
|
114
|
-
# hell yeah
|
115
|
-
elsif response.timed_out?
|
116
|
-
# aw hell no
|
117
|
-
log("got a time out")
|
118
|
-
elsif response.code == 0
|
119
|
-
# Could not get an http response, something's wrong.
|
120
|
-
log(response.curl_error_message)
|
121
|
-
else
|
122
|
-
# Received a non-successful http response.
|
123
|
-
log("HTTP request failed: " + response.code.to_s)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
This also works with serial (blocking) requests in the same fashion. Both
|
128
|
-
serial and parallel requests return a Response object.
|
129
|
-
|
130
|
-
**Handling file uploads**
|
131
|
-
|
132
|
-
A File object can be passed as a param for a POST request to handle uploading
|
133
|
-
files to the server. Typhoeus will upload the file as the original file name
|
134
|
-
and use Mime::Types to set the content type.
|
135
|
-
|
136
|
-
response = Typhoeus::Request.post("http://localhost:3000/posts",
|
137
|
-
:params => {
|
138
|
-
:title => "test post", :content => "this is my test",
|
139
|
-
:file => File.open("thesis.txt","r")
|
140
|
-
}
|
141
|
-
)
|
142
|
-
|
143
|
-
**Making Parallel Requests**
|
144
|
-
|
145
|
-
# Generally, you should be running requests through hydra. Here is how that looks
|
146
|
-
hydra = Typhoeus::Hydra.new
|
147
|
-
|
148
|
-
first_request = Typhoeus::Request.new("http://localhost:3000/posts/1.json")
|
149
|
-
first_request.on_complete do |response|
|
150
|
-
post = JSON.parse(response.body)
|
151
|
-
third_request = Typhoeus::Request.new(post.links.first) # get the first url in the post
|
152
|
-
third_request.on_complete do |response|
|
153
|
-
# do something with that
|
154
|
-
end
|
155
|
-
hydra.queue third_request
|
156
|
-
return post
|
157
|
-
end
|
158
|
-
second_request = Typhoeus::Request.new("http://localhost:3000/users/1.json")
|
159
|
-
second_request.on_complete do |response|
|
160
|
-
JSON.parse(response.body)
|
161
|
-
end
|
162
|
-
hydra.queue first_request
|
163
|
-
hydra.queue second_request
|
164
|
-
hydra.run # this is a blocking call that returns once all requests are complete
|
165
|
-
|
166
|
-
first_request.handled_response # the value returned from the on_complete block
|
167
|
-
second_request.handled_response # the value returned from the on_complete block (parsed JSON)
|
168
|
-
|
169
|
-
The execution of that code goes something like this. The first and second
|
170
|
-
requests are built and queued. When hydra is run the first and second requests
|
171
|
-
run in parallel. When the first request completes, the third request is then
|
172
|
-
built and queued up. The moment it is queued Hydra starts executing it.
|
173
|
-
Meanwhile the second request would continue to run (or it could have completed
|
174
|
-
before the first). Once the third request is done, hydra.run returns.
|
175
|
-
|
176
|
-
**Specifying Max Concurrency**
|
177
|
-
|
178
|
-
Hydra will also handle how many requests you can make in parallel. Things will
|
179
|
-
get flakey if you try to make too many requests at the same time. The built in
|
180
|
-
limit is 200. When more requests than that are queued up, hydra will save them
|
181
|
-
for later and start the requests as others are finished. You can raise or
|
182
|
-
lower the concurrency limit through the Hydra constructor.
|
183
|
-
|
184
|
-
hydra = Typhoeus::Hydra.new(:max_concurrency => 20) # keep from killing some servers
|
185
|
-
|
186
|
-
**Memoization**
|
187
|
-
|
188
|
-
Hydra memoizes requests within a single run call. You can also disable
|
189
|
-
memoization.
|
190
|
-
|
191
|
-
hydra = Typhoeus::Hydra.new
|
192
|
-
2.times do
|
193
|
-
r = Typhoeus::Request.new("http://localhost/3000/users/1")
|
194
|
-
hydra.queue r
|
195
|
-
end
|
196
|
-
hydra.run # this will result in a single request being issued. However, the on_complete handlers of both will be called.
|
197
|
-
hydra.disable_memoization
|
198
|
-
2.times do
|
199
|
-
r = Typhoeus::Request.new("http://localhost/3000/users/1")
|
200
|
-
hydra.queue r
|
201
|
-
end
|
202
|
-
hydra.run # this will result in a two requests.
|
203
|
-
|
204
|
-
**Caching**
|
205
|
-
|
206
|
-
Hydra includes built in support for creating cache getters and setters. In the
|
207
|
-
following example, if there is a cache hit, the cached object is passed to the
|
208
|
-
on\_complete handler of the request object.
|
209
|
-
|
210
|
-
hydra = Typhoeus::Hydra.new
|
211
|
-
hydra.cache_setter do |request|
|
212
|
-
@cache.set(request.cache_key, request.response, request.cache_timeout)
|
213
|
-
end
|
214
|
-
|
215
|
-
hydra.cache_getter do |request|
|
216
|
-
@cache.get(request.cache_key) rescue nil
|
217
|
-
end
|
218
|
-
|
219
|
-
**Direct Stubbing**
|
220
|
-
|
221
|
-
Hydra allows you to stub out specific urls and patterns to avoid hitting
|
222
|
-
remote servers while testing.
|
223
|
-
|
224
|
-
hydra = Typhoeus::Hydra.new
|
225
|
-
response = Response.new(:code => 200, :headers => "", :body => "{'name' : 'paul'}", :time => 0.3)
|
226
|
-
hydra.stub(:get, "http://localhost:3000/users/1").and_return(response)
|
227
|
-
|
228
|
-
request = Typhoeus::Request.new("http://localhost:3000/users/1")
|
229
|
-
request.on_complete do |response|
|
230
|
-
JSON.parse(response.body)
|
231
|
-
end
|
232
|
-
hydra.queue request
|
233
|
-
hydra.run
|
234
|
-
|
235
|
-
The queued request will hit the stub. The on\_complete handler will be called
|
236
|
-
and will be passed the response object. You can also specify a regex to match
|
237
|
-
urls.
|
238
|
-
|
239
|
-
hydra.stub(:get, /http\:\/\/localhost\:3000\/users\/.*/).and_return(response)
|
240
|
-
# any requests for a user will be stubbed out with the pre built response.
|
241
|
-
|
242
|
-
**The Singleton**
|
243
|
-
|
244
|
-
All of the quick requests are done using the singleton hydra object. If you
|
245
|
-
want to enable caching or stubbing on the quick requests, set those options on
|
246
|
-
the singleton.
|
247
|
-
|
248
|
-
hydra = Typhoeus::Hydra.hydra
|
249
|
-
hydra.stub(:get, "http://localhost:3000/users")
|
250
|
-
|
251
|
-
**Timeouts**
|
252
|
-
|
253
|
-
No exceptions are raised on HTTP timeouts. You can check whether a request
|
254
|
-
timed out with the following methods:
|
255
|
-
|
256
|
-
easy.timed_out? # for a raw Easy handle
|
257
|
-
response.timed_out? # for a Response handle
|
258
|
-
|
259
|
-
**Following Redirections**
|
260
|
-
|
261
|
-
Use `:follow_location => true`, eg:
|
262
|
-
|
263
|
-
Typhoeus::Request.new(“www.example.com”, :follow_location => true)
|
264
|
-
|
265
|
-
**Basic Authentication**
|
266
|
-
|
267
|
-
response = Typhoeus::Request.get("http://twitter.com/statuses/followers.json",
|
268
|
-
:username => username, :password => password)
|
269
|
-
|
270
|
-
**SSL**
|
271
|
-
|
272
|
-
SSL comes built in to libcurl so it’s in Typhoeus as well. If you pass in a
|
273
|
-
url with “https” it should just work assuming that you have your [cert
|
274
|
-
bundle](http://curl.haxx.se/docs/caextract.html) in order and the server is
|
275
|
-
verifiable. You must also have libcurl built with SSL support enabled. You can
|
276
|
-
check that by doing this:
|
277
|
-
|
278
|
-
Typhoeus::Easy.new.curl_version # output should include OpenSSL/...
|
279
|
-
|
280
|
-
Now, even if you have libcurl built with OpenSSL you may still have a messed
|
281
|
-
up cert bundle or if you’re hitting a non-verifiable SSL server then you’ll
|
282
|
-
have to disable peer verification to make SSL work. Like this:
|
283
|
-
|
284
|
-
Typhoeus::Request.get("https://mail.google.com/mail", :disable_ssl_peer_verification => true)
|
285
|
-
|
286
|
-
If you are getting “SSL: certificate subject name does not match target host
|
287
|
-
name” from curl (ex:- you are trying to access to b.c.host.com when the
|
288
|
-
certificate subject is \*.host.com). You can disable host verification. Like
|
289
|
-
this:
|
290
|
-
|
291
|
-
Typhoeus::Request.get("https://mail.google.com/mail", :disable_ssl_host_verification => true)
|
292
|
-
|
293
|
-
**LibCurl**
|
294
|
-
|
295
|
-
Typhoeus also has a more raw libcurl interface. These are the Easy and Multi
|
296
|
-
objects. If you’re into accessing just the raw libcurl style, those are your
|
297
|
-
best bet.
|
298
|
-
|
299
|
-
However, by using this raw interface, you do not get access to Hydra-specific
|
300
|
-
features, such as stubbing/mocking.
|
301
|
-
|
302
|
-
SSL Certs can be provided to the Easy interface:
|
303
|
-
|
304
|
-
e = Typhoeus::Easy.new
|
305
|
-
e.url = "https://example.com/action"
|
306
|
-
s.ssl_cacert = "ca_file.cer"
|
307
|
-
e.ssl_cert = "acert.crt"
|
308
|
-
e.ssl_key = "akey.key"
|
309
|
-
[...]
|
310
|
-
e.perform
|
311
|
-
|
312
|
-
or directly to a Typhoeus::Request :
|
313
|
-
|
314
|
-
e = Typhoeus::Request.get("https://example.com/action",
|
315
|
-
:ssl_cacert => "ca_file.cer",
|
316
|
-
:ssl_cert => "acert.crt",
|
317
|
-
:ssl_key => "akey.key",
|
318
|
-
[...]
|
319
|
-
end
|
320
|
-
|
321
|
-
## Advanced authentication
|
322
|
-
|
323
|
-
Thanks for the authentication piece and this description go to Oleg Ivanov
|
324
|
-
(morhekil). The major reason to start this fork was the need to perform NTLM
|
325
|
-
authentication in Ruby, and other libcurl’s authentications method were made
|
326
|
-
possible as a result. Now you can do it via Typhoeus::Easy interface using the
|
327
|
-
following API.
|
328
|
-
|
329
|
-
e = Typhoeus::Easy.new
|
330
|
-
e.auth = {
|
331
|
-
:username => 'username',
|
332
|
-
:password => 'password',
|
333
|
-
:method => Typhoeus::Easy::AUTH_TYPES[:CURLAUTH_NTLM]
|
334
|
-
}
|
335
|
-
e.url = "http://example.com/auth_ntlm"
|
336
|
-
e.method = :get
|
337
|
-
e.perform
|
338
|
-
|
339
|
-
**Other authentication types**
|
340
|
-
|
341
|
-
The following authentication types are available:
|
342
|
-
|
343
|
-
* CURLAUTH\_BASIC
|
344
|
-
* CURLAUTH\_DIGEST
|
345
|
-
* CURLAUTH\_GSSNEGOTIATE
|
346
|
-
* CURLAUTH\_NTLM
|
347
|
-
* CURLAUTH\_DIGEST\_IE
|
348
|
-
* CURLAUTH\_AUTO
|
349
|
-
|
350
|
-
The last one (CURLAUTH\_AUTO) is really a combination of all previous methods
|
351
|
-
and is provided by Typhoeus for convenience. When you set authentication to
|
352
|
-
auto, Typhoeus will retrieve the given URL first and examine it’s headers to
|
353
|
-
confirm what auth types are supported by the server. The it will select the
|
354
|
-
strongest of available auth methods and will send the second request using the
|
355
|
-
selected authentication method.
|
356
|
-
|
357
|
-
**Authentication via the quick request interface**
|
358
|
-
|
359
|
-
There’s also an easy way to perform any kind of authentication via the quick
|
360
|
-
request interface:
|
361
|
-
|
362
|
-
e = Typhoeus::Request.get("http://example.com",
|
363
|
-
:username => 'username',
|
364
|
-
:password => 'password',
|
365
|
-
:auth_method => :ntlm)
|
366
|
-
|
367
|
-
All methods listed above is available in a shorter form – :basic, :digest,
|
368
|
-
:gssnegotiate, :ntlm, :digest\_ie, :auto.
|
369
|
-
|
370
|
-
**Query of available auth types**
|
371
|
-
|
372
|
-
After the initial request you can get the authentication types available on
|
373
|
-
the server via Typhoues::Easy#auth\_methods call. It will return a number
|
374
|
-
|
375
|
-
that you’ll need to decode yourself, please refer to easy.rb source code to
|
376
|
-
see the numeric values of different auth types.
|
377
|
-
|
378
|
-
## Verbose debug output
|
379
|
-
|
380
|
-
Sometime it’s useful to see verbose output from curl. You may now enable it:
|
381
|
-
|
382
|
-
e = Typhoeus::Easy.new
|
383
|
-
e.verbose = 1
|
384
|
-
|
385
|
-
or using the quick request:
|
386
|
-
|
387
|
-
e = Typhoeus::Request.get("http://example.com", :verbose => true)
|
388
|
-
|
389
|
-
Just remember that libcurl prints it’s debug output to the console (to
|
390
|
-
STDERR), so you’ll need to run your scripts from the console to see it.
|
391
|
-
|
392
|
-
## Benchmarks
|
393
|
-
|
394
|
-
I set up a benchmark to test how the parallel performance works vs Ruby’s
|
395
|
-
built in NET::HTTP. The setup was a local evented HTTP server that would take
|
396
|
-
a request, sleep for 500 milliseconds and then issued a blank response. I set
|
397
|
-
up the client to call this 20 times. Here are the results:
|
398
|
-
|
399
|
-
net::http 0.030000 0.010000 0.040000 ( 10.054327)
|
400
|
-
typhoeus 0.020000 0.070000 0.090000 ( 0.508817)
|
401
|
-
|
402
|
-
We can see from this that NET::HTTP performs as expected, taking 10 seconds to
|
403
|
-
run 20 500ms requests. Typhoeus only takes 500ms (the time of the response
|
404
|
-
that took the longest.) One other thing to note is that Typhoeus keeps a pool
|
405
|
-
of libcurl Easy handles to use. For this benchmark I warmed the pool first. So
|
406
|
-
if you test this out it may be a bit slower until the Easy handle pool has
|
407
|
-
enough in it to run all the simultaneous requests. For some reason the easy
|
408
|
-
handles can take quite some time to allocate.
|
409
|
-
|
410
|
-
## Running the specs
|
411
|
-
|
412
|
-
Running the specs requires a couple of Sinatra servers to be booted. rake spec
|
413
|
-
will do this for you, but if you’re needing to run the specs a lot, spinning
|
414
|
-
up the servers manually and leaving them running should speed things up a bit.
|
415
|
-
Do this:
|
416
|
-
|
417
|
-
# Start up the test servers (in another terminal)
|
418
|
-
rake start_test_servers
|
419
|
-
|
420
|
-
# Run the specs
|
421
|
-
rake spec
|
422
|
-
|
423
|
-
|
424
|
-
## Next Steps
|
425
|
-
|
426
|
-
* Add in ability to keep-alive requests and reuse them within hydra.
|
427
|
-
* Add support for automatic retry, exponential back-off, and queuing for later.
|
428
|
-
|
429
|
-
## LICENSE
|
27
|
+
## LICENSE
|
430
28
|
|
431
29
|
(The MIT License)
|
432
30
|
|
433
|
-
Copyright © 2009-2010 Paul Dix
|
31
|
+
Copyright © 2009-2010 [Paul Dix](http://www.pauldix.net/)
|
434
32
|
|
435
|
-
Copyright © 2011 David Balatero
|
33
|
+
Copyright © 2011 [David Balatero](https://github.com/dbalatero/)
|
436
34
|
|
437
35
|
Copyright © 2012 [Hans Hasselberg](http://www.hans.io)
|
438
36
|
|