ethon 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +14 -0
- data/README.md +36 -26
- data/lib/ethon.rb +2 -0
- data/lib/ethon/curl.rb +4 -0
- data/lib/ethon/curls/auth_types.rb +1 -1
- data/lib/ethon/curls/functions.rb +2 -0
- data/lib/ethon/easy.rb +12 -2
- data/lib/ethon/easy/callbacks.rb +2 -0
- data/lib/ethon/easy/form.rb +2 -0
- data/lib/ethon/easy/header.rb +2 -0
- data/lib/ethon/easy/http/actionable.rb +1 -0
- data/lib/ethon/easy/operations.rb +4 -0
- data/lib/ethon/easy/options.rb +8 -0
- data/lib/ethon/easy/params.rb +2 -0
- data/lib/ethon/easy/queryable.rb +1 -1
- data/lib/ethon/easy/response_callbacks.rb +2 -0
- data/lib/ethon/easy/util.rb +2 -0
- data/lib/ethon/errors/multi_fdset.rb +0 -1
- data/lib/ethon/multi.rb +4 -0
- data/lib/ethon/multi/operations.rb +26 -4
- data/lib/ethon/multi/stack.rb +2 -2
- data/lib/ethon/version.rb +3 -1
- metadata +3 -3
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## Master
|
4
4
|
|
5
|
+
## 0.5.1
|
6
|
+
|
7
|
+
[Full Changelog](http://github.com/typhoeus/ethon/compare/v0.5.0...0.5.1)
|
8
|
+
|
9
|
+
Bugfixes:
|
10
|
+
|
11
|
+
* Mark Curl.select and Curl.easy_perform as blocking so that the GIL is
|
12
|
+
released by ffi.
|
13
|
+
|
5
14
|
## 0.5.0
|
6
15
|
|
7
16
|
[Full Changelog](http://github.com/typhoeus/ethon/compare/v0.4.4...0.5.0)
|
@@ -11,6 +20,11 @@ Enhancements:
|
|
11
20
|
* New libcurl option proxyuserpwd
|
12
21
|
* Rename response_header to response_headers
|
13
22
|
|
23
|
+
Bugfixes:
|
24
|
+
|
25
|
+
* Mark Curl.select and Curl.easy_perform as blocking so that the GIL is
|
26
|
+
released by ffi.
|
27
|
+
|
14
28
|
## 0.4.4
|
15
29
|
|
16
30
|
[Full Changelog](http://github.com/typhoeus/ethon/compare/v0.4.3...v0.4.4)
|
data/README.md
CHANGED
@@ -21,43 +21,53 @@ With rubygems:
|
|
21
21
|
|
22
22
|
Making the first request is realy simple:
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
```ruby
|
25
|
+
easy = Ethon::Easy.new(url: "www.example.com")
|
26
|
+
easy.prepare
|
27
|
+
easy.perform
|
28
|
+
#=> :ok
|
29
|
+
```
|
28
30
|
|
29
31
|
You have access to various options like following redirects:
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
```ruby
|
34
|
+
easy = Ethon::Easy.new(url: "www.example.com", followlocation: true)
|
35
|
+
easy.prepare
|
36
|
+
easy.perform
|
37
|
+
#=> :ok
|
38
|
+
```
|
35
39
|
|
36
40
|
Once you're done you can look at the response code and body:
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
```ruby
|
43
|
+
easy = Ethon::Easy.new(url: "www.example.com", followlocation: true)
|
44
|
+
easy.prepare
|
45
|
+
easy.perform
|
46
|
+
easy.response_code
|
47
|
+
#=> 200
|
48
|
+
easy.response_body
|
49
|
+
#=> "<!doctype html><html ..."
|
50
|
+
```
|
45
51
|
|
46
52
|
## Http
|
47
53
|
|
48
54
|
In order to make life easier there are some helpers for doing http requests:
|
49
55
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
```ruby
|
57
|
+
easy = Ethon::Easy.new
|
58
|
+
easy.http_request("www.example.com", :get, { params: {a: 1} })
|
59
|
+
easy.prepare
|
60
|
+
easy.perform
|
61
|
+
#=> :ok
|
62
|
+
```
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
easy = Ethon::Easy.new
|
66
|
+
easy.http_request("www.example.com", :post, { params: { a: 1 }, body: { b: 2 } })
|
67
|
+
easy.prepare
|
68
|
+
easy.perform
|
69
|
+
#=> :ok
|
70
|
+
```
|
61
71
|
|
62
72
|
This really handy when doing requests since you don't have to care about setting
|
63
73
|
everything up correct.
|
data/lib/ethon.rb
CHANGED
data/lib/ethon/curl.rb
CHANGED
@@ -11,6 +11,8 @@ require 'ethon/curls/functions'
|
|
11
11
|
module Ethon
|
12
12
|
|
13
13
|
# FFI Wrapper module for Curl. Holds constants and required initializers.
|
14
|
+
#
|
15
|
+
# @api private
|
14
16
|
module Curl
|
15
17
|
extend ::FFI::Library
|
16
18
|
extend Ethon::Curls::Codes
|
@@ -58,6 +60,8 @@ module Ethon
|
|
58
60
|
# mean no other thread that is using libcurl. Because curl_global_init() calls
|
59
61
|
# functions of other libraries that are similarly thread unsafe, it could conflict with
|
60
62
|
# any other thread that uses these other libraries.
|
63
|
+
#
|
64
|
+
# @raise [ Ethon::Errors::GlobalInit ] If Curl.global_init fails.
|
61
65
|
def init
|
62
66
|
@@init_mutex.synchronize {
|
63
67
|
if not @@initialized
|
@@ -19,6 +19,7 @@ module Ethon
|
|
19
19
|
base.attach_function :easy_setopt_fixnum, :curl_easy_setopt, [:pointer, :easy_option, :long], :easy_code
|
20
20
|
base.attach_function :easy_setopt_callback, :curl_easy_setopt, [:pointer, :easy_option, :callback], :easy_code
|
21
21
|
base.attach_function :easy_setopt_proc, :curl_easy_setopt, [:pointer, :easy_option, :callback], :easy_code
|
22
|
+
base.instance_variable_set(:@blocking, true)
|
22
23
|
base.attach_function :easy_perform, :curl_easy_perform, [:pointer], :easy_code
|
23
24
|
base.attach_function :easy_strerror, :curl_easy_strerror, [:int], :string
|
24
25
|
base.attach_function :easy_escape, :curl_easy_escape, [:pointer, :pointer, :int], :string
|
@@ -46,6 +47,7 @@ module Ethon
|
|
46
47
|
base.attach_function :version, :curl_version, [], :string
|
47
48
|
base.attach_function :slist_append, :curl_slist_append, [:pointer, :string], :pointer
|
48
49
|
base.attach_function :slist_free_all, :curl_slist_free_all, [:pointer], :void
|
50
|
+
base.instance_variable_set(:@blocking, true)
|
49
51
|
base.attach_function :select, [:int, Curl::FDSet.ptr, Curl::FDSet.ptr, Curl::FDSet.ptr, Curl::Timeval.ptr], :int
|
50
52
|
end
|
51
53
|
end
|
data/lib/ethon/easy.rb
CHANGED
@@ -201,12 +201,16 @@ module Ethon
|
|
201
201
|
|
202
202
|
class << self
|
203
203
|
|
204
|
-
#
|
204
|
+
# Frees libcurls easy represantation including its headers if any.
|
205
205
|
#
|
206
206
|
# @example Free easy handle.
|
207
207
|
# Easy.finalizer(easy)
|
208
208
|
#
|
209
209
|
# @param [ Easy ] easy The easy to free.
|
210
|
+
#
|
211
|
+
# @see http://curl.haxx.se/libcurl/c/curl_easy_cleanup.html
|
212
|
+
#
|
213
|
+
# @api private
|
210
214
|
def finalizer(easy)
|
211
215
|
proc {
|
212
216
|
Curl.slist_free_all(easy.header_list) if easy.header_list
|
@@ -219,7 +223,7 @@ module Ethon
|
|
219
223
|
# It initializes curl, if not already done and applies the provided options.
|
220
224
|
#
|
221
225
|
# @example Create a new Easy.
|
222
|
-
# Easy.new(:
|
226
|
+
# Easy.new(url: "www.google.de")
|
223
227
|
#
|
224
228
|
# @param [ Hash ] options The options to set.
|
225
229
|
#
|
@@ -793,6 +797,8 @@ module Ethon
|
|
793
797
|
# @return [ Easy ] A new Easy.
|
794
798
|
#
|
795
799
|
# @see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
|
800
|
+
#
|
801
|
+
# @api public
|
796
802
|
def initialize(options = {})
|
797
803
|
Curl.init
|
798
804
|
ObjectSpace.define_finalizer(self, self.class.finalizer(self))
|
@@ -809,6 +815,8 @@ module Ethon
|
|
809
815
|
# @raise InvalidOption
|
810
816
|
#
|
811
817
|
# @see initialize
|
818
|
+
#
|
819
|
+
# @api private
|
812
820
|
def set_attributes(options)
|
813
821
|
options.each_pair do |key, value|
|
814
822
|
unless respond_to?("#{key}=")
|
@@ -838,6 +846,8 @@ module Ethon
|
|
838
846
|
# @param [ String ] value The value to escape.
|
839
847
|
#
|
840
848
|
# @return [ String ] The escaped value.
|
849
|
+
#
|
850
|
+
# @api private
|
841
851
|
def escape(value)
|
842
852
|
Curl.easy_escape(handle, value, 0)
|
843
853
|
end
|
data/lib/ethon/easy/callbacks.rb
CHANGED
data/lib/ethon/easy/form.rb
CHANGED
data/lib/ethon/easy/header.rb
CHANGED
@@ -20,6 +20,8 @@ module Ethon
|
|
20
20
|
# easy.perform
|
21
21
|
#
|
22
22
|
# @return [ Integer ] The return code.
|
23
|
+
#
|
24
|
+
# @api public
|
23
25
|
def perform
|
24
26
|
@return_code = Curl.easy_perform(handle)
|
25
27
|
complete
|
@@ -32,6 +34,8 @@ module Ethon
|
|
32
34
|
#
|
33
35
|
# @example Prepare easy.
|
34
36
|
# easy.prepare
|
37
|
+
#
|
38
|
+
# @api public
|
35
39
|
def prepare
|
36
40
|
set_options
|
37
41
|
set_headers
|
data/lib/ethon/easy/options.rb
CHANGED
@@ -3,6 +3,8 @@ module Ethon
|
|
3
3
|
|
4
4
|
# This module contains the logic and knowledge about the
|
5
5
|
# available options on easy.
|
6
|
+
#
|
7
|
+
# @api private
|
6
8
|
module Options
|
7
9
|
|
8
10
|
# :nodoc:
|
@@ -86,7 +88,13 @@ module Ethon
|
|
86
88
|
# @example Return casted the value.
|
87
89
|
# easy.value_for(:verbose)
|
88
90
|
#
|
91
|
+
# @param [ Symbol ] option The option to get the value from.
|
92
|
+
#
|
89
93
|
# @return [ Object ] The casted value.
|
94
|
+
#
|
95
|
+
# @raise [ Ethon::Errors::InvalidValue ] If specified option
|
96
|
+
# points to an enum and the value doen't correspond to
|
97
|
+
# the valid values.
|
90
98
|
def value_for(option)
|
91
99
|
value = method(option).call
|
92
100
|
return nil if value.nil?
|
data/lib/ethon/easy/params.rb
CHANGED
data/lib/ethon/easy/queryable.rb
CHANGED
@@ -49,7 +49,7 @@ module Ethon
|
|
49
49
|
# Return query pairs build from a hash.
|
50
50
|
#
|
51
51
|
# @example Build query pairs.
|
52
|
-
# action.build_query_pairs({:
|
52
|
+
# action.build_query_pairs({a: 1, b: 2})
|
53
53
|
# #=> [[:a, 1], [:b, 2]]
|
54
54
|
#
|
55
55
|
# @param [ Hash ] hash The hash to go through.
|
data/lib/ethon/easy/util.rb
CHANGED
data/lib/ethon/multi.rb
CHANGED
@@ -18,6 +18,8 @@ module Ethon
|
|
18
18
|
# Multi.finalizer(multi)
|
19
19
|
#
|
20
20
|
# @param [ Multi ] multi The multi to free.
|
21
|
+
#
|
22
|
+
# @api private
|
21
23
|
def finalizer(multi)
|
22
24
|
proc {
|
23
25
|
Curl.multi_cleanup(multi.handle)
|
@@ -92,6 +94,8 @@ module Ethon
|
|
92
94
|
# @raise InvalidOption
|
93
95
|
#
|
94
96
|
# @see initialize
|
97
|
+
#
|
98
|
+
# @api private
|
95
99
|
def set_attributes(options)
|
96
100
|
options.each_pair do |key, value|
|
97
101
|
unless respond_to?("#{key}=")
|
@@ -10,7 +10,7 @@ module Ethon
|
|
10
10
|
# @example Return multi handle.
|
11
11
|
# multi.handle
|
12
12
|
#
|
13
|
-
# @return [
|
13
|
+
# @return [ FFI::Pointer ] The multi handle.
|
14
14
|
def handle
|
15
15
|
@handle ||= Curl.multi_init
|
16
16
|
end
|
@@ -19,6 +19,8 @@ module Ethon
|
|
19
19
|
#
|
20
20
|
# @example Initialize variables.
|
21
21
|
# multi.init_vars
|
22
|
+
#
|
23
|
+
# @return [ void ]
|
22
24
|
def init_vars
|
23
25
|
@timeout = ::FFI::MemoryPointer.new(:long)
|
24
26
|
@timeval = Curl::Timeval.new
|
@@ -40,8 +42,12 @@ module Ethon
|
|
40
42
|
|
41
43
|
# Perform multi.
|
42
44
|
#
|
45
|
+
# @return [ nil ]
|
46
|
+
#
|
43
47
|
# @example Perform multi.
|
44
48
|
# multi.perform
|
49
|
+
#
|
50
|
+
# @api public
|
45
51
|
def perform
|
46
52
|
Ethon.logger.debug("ETHON: started MULTI")
|
47
53
|
while ongoing?
|
@@ -57,8 +63,12 @@ module Ethon
|
|
57
63
|
|
58
64
|
# Prepare multi.
|
59
65
|
#
|
66
|
+
# @return [ nil ]
|
67
|
+
#
|
60
68
|
# @example Prepare multi.
|
61
69
|
# multi.prepare
|
70
|
+
#
|
71
|
+
# @api public
|
62
72
|
def prepare
|
63
73
|
set_options
|
64
74
|
end
|
@@ -68,7 +78,9 @@ module Ethon
|
|
68
78
|
# @example Get timeout.
|
69
79
|
# multi.get_timeout
|
70
80
|
#
|
71
|
-
# @
|
81
|
+
# @return [ Integer ] The timeout.
|
82
|
+
#
|
83
|
+
# @raise [ Ethon::Errors::MultiTimeout ] If getting the timeout fails.
|
72
84
|
def get_timeout
|
73
85
|
code = Curl.multi_timeout(handle, @timeout)
|
74
86
|
raise Errors::MultiTimeout.new(code) unless code == :ok
|
@@ -81,6 +93,8 @@ module Ethon
|
|
81
93
|
#
|
82
94
|
# @example Reset fds.
|
83
95
|
# multi.reset_fds
|
96
|
+
#
|
97
|
+
# @return [ void ]
|
84
98
|
def reset_fds
|
85
99
|
@fd_read.clear
|
86
100
|
@fd_write.clear
|
@@ -92,8 +106,10 @@ module Ethon
|
|
92
106
|
# @example Set fds.
|
93
107
|
# multi.set_fds
|
94
108
|
#
|
95
|
-
# @
|
96
|
-
#
|
109
|
+
# @return [ void ]
|
110
|
+
#
|
111
|
+
# @raise [ Ethon::Errors::MultiFdset ] If setting the file descriptors fails.
|
112
|
+
# @raise [ Ethon::Errors::Select ] If select fails.
|
97
113
|
def set_fds(timeout)
|
98
114
|
code = Curl.multi_fdset(handle, @fd_read, @fd_write, @fd_excep, @max_fd)
|
99
115
|
raise Errors::MultiFdset.new(code) unless code == :ok
|
@@ -112,6 +128,8 @@ module Ethon
|
|
112
128
|
#
|
113
129
|
# @example Check.
|
114
130
|
# multi.check
|
131
|
+
#
|
132
|
+
# @return [ void ]
|
115
133
|
def check
|
116
134
|
msgs_left = ::FFI::MemoryPointer.new(:int)
|
117
135
|
while true
|
@@ -130,6 +148,8 @@ module Ethon
|
|
130
148
|
#
|
131
149
|
# @example Run
|
132
150
|
# multi.run
|
151
|
+
#
|
152
|
+
# @return [ void ]
|
133
153
|
def run
|
134
154
|
begin code = trigger end while code == :call_multi_perform
|
135
155
|
check
|
@@ -139,6 +159,8 @@ module Ethon
|
|
139
159
|
#
|
140
160
|
# @example Trigger.
|
141
161
|
# multi.trigger
|
162
|
+
#
|
163
|
+
# @return [ Symbol ] The Curl.multi_perform return code.
|
142
164
|
def trigger
|
143
165
|
running_count = FFI::MemoryPointer.new(:int)
|
144
166
|
code = Curl.multi_perform(handle, running_count)
|
data/lib/ethon/multi/stack.rb
CHANGED
@@ -21,7 +21,7 @@ module Ethon
|
|
21
21
|
#
|
22
22
|
# @param [ Easy ] easy The easy to add.
|
23
23
|
#
|
24
|
-
# @raise [Ethon::Errors::MultiAdd]
|
24
|
+
# @raise [ Ethon::Errors::MultiAdd ] If adding an easy failed.
|
25
25
|
def add(easy)
|
26
26
|
return nil if easy_handles.include?(easy)
|
27
27
|
|
@@ -36,7 +36,7 @@ module Ethon
|
|
36
36
|
#
|
37
37
|
# @param [ Easy ] easy The easy to delete.
|
38
38
|
#
|
39
|
-
# @raise [Ethon::Errors::MultiRemove]
|
39
|
+
# @raise [ Ethon::Errors::MultiRemove ] If removing an easy failed.
|
40
40
|
def delete(easy)
|
41
41
|
if easy_handles.delete(easy)
|
42
42
|
code = Curl.multi_remove_handle(handle, easy.handle)
|
data/lib/ethon/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ethon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
@@ -121,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
121
121
|
version: '0'
|
122
122
|
segments:
|
123
123
|
- 0
|
124
|
-
hash:
|
124
|
+
hash: 2761547586556677808
|
125
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
126
|
none: false
|
127
127
|
requirements:
|