ethon 0.10.1 → 0.11.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/Gemfile +9 -4
- data/README.md +4 -1
- data/lib/ethon/curls/functions.rb +1 -0
- data/lib/ethon/curls/options.rb +8 -2
- data/lib/ethon/curls/settings.rb +1 -0
- data/lib/ethon/easy.rb +2 -0
- data/lib/ethon/easy/callbacks.rb +21 -0
- data/lib/ethon/easy/form.rb +4 -2
- data/lib/ethon/easy/http/actionable.rb +1 -1
- data/lib/ethon/easy/options.rb +10 -2
- data/lib/ethon/easy/response_callbacks.rb +26 -0
- data/lib/ethon/version.rb +1 -1
- data/spec/ethon/easy/callbacks_spec.rb +7 -1
- data/spec/ethon/easy/debug_info_spec.rb +1 -0
- data/spec/ethon/easy/form_spec.rb +9 -0
- data/spec/ethon/easy/options_spec.rb +29 -0
- data/spec/ethon/easy/queryable_spec.rb +5 -3
- data/spec/ethon/easy/response_callbacks_spec.rb +57 -1
- data/spec/ethon/easy_spec.rb +5 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac54c9df1c6dfd22a65124a64c7bb93b2792dc55
|
4
|
+
data.tar.gz: 5fedd427db76181d6bde8c7c4af4116bdf1cc272
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 538f6d8f6af52a294d72ecc3f63f8a2a7ed97f90154382979edfbdc6085f38e16ea4e336f1cdff3d107551402ba2408b87f8632added41b2915744b97da47c3c
|
7
|
+
data.tar.gz: 54695f47f42ea0838c8da9531d136b52d6d77a8e5cd10374929c878b6ff55f572727d1e8afa3b854672ba6bbbcb5eff1d0d25091bc6d5f1ad6df0d757eeecb6e
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -18,11 +18,16 @@ group :development, :test do
|
|
18
18
|
gem "json"
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
if Gem.ruby_version >= Gem::Version.new("2.0.0")
|
22
|
+
gem "mime-types", "~> 1.18"
|
23
|
+
end
|
22
24
|
|
23
|
-
|
24
|
-
gem "
|
25
|
-
|
25
|
+
if Gem.ruby_version >= Gem::Version.new("2.2.0")
|
26
|
+
gem "mustermann"
|
27
|
+
elsif Gem.ruby_version >= Gem::Version.new("2.1.0")
|
28
|
+
gem "mustermann", "0.4.0"
|
29
|
+
elsif Gem.ruby_version >= Gem::Version.new("2.0.0")
|
30
|
+
gem "mustermann", "0.3.1"
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
[](https://badge.fury.io/rb/ethon)
|
2
|
+
[](https://travis-ci.org/typhoeus/ethon)
|
3
|
+
|
4
|
+
# Ethon
|
2
5
|
|
3
6
|
In Greek mythology, Ethon, the son of Typhoeus and Echidna, is a gigantic eagle. So much for the history.
|
4
7
|
In the modern world, Ethon is a very basic libcurl wrapper using ffi.
|
@@ -19,6 +19,7 @@ module Ethon
|
|
19
19
|
base.attach_function :easy_setopt_long, :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_debug_callback, :curl_easy_setopt, [:pointer, :easy_option, :debug_callback], :easy_code
|
22
|
+
base.attach_function :easy_setopt_progress_callback, :curl_easy_setopt, [:pointer, :easy_option, :progress_callback], :easy_code
|
22
23
|
base.attach_function :easy_setopt_off_t, :curl_easy_setopt, [:pointer, :easy_option, :int64], :easy_code
|
23
24
|
base.instance_variable_set(:@blocking, true)
|
24
25
|
base.attach_function :easy_perform, :curl_easy_perform, [:pointer], :easy_code
|
data/lib/ethon/curls/options.rb
CHANGED
@@ -7,7 +7,7 @@ module Ethon
|
|
7
7
|
|
8
8
|
OPTION_STRINGS = { :easy => 'easy_options', :multi => 'multi_options' }.freeze
|
9
9
|
FOPTION_STRINGS = { :easy => 'EASY_OPTIONS', :multi => 'MULTI_OPTIONS' }.freeze
|
10
|
-
FTYPES = [:long, :string, :ffipointer, :callback, :debug_callback, :off_t]
|
10
|
+
FTYPES = [:long, :string, :ffipointer, :callback, :debug_callback, :progress_callback, :off_t]
|
11
11
|
FUNCS = Hash[*[:easy, :multi].zip([:easy, :multi].map { |t| Hash[*FTYPES.zip(FTYPES.map { |ft| "#{t}_setopt_#{ft}" }).flatten] }).flatten]
|
12
12
|
# Sets appropriate option for easy, depending on value type.
|
13
13
|
def set_option(option, value, handle, type = :easy)
|
@@ -85,6 +85,9 @@ module Ethon
|
|
85
85
|
when :debug_callback
|
86
86
|
func=:debug_callback
|
87
87
|
raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
|
88
|
+
when :progress_callback
|
89
|
+
func=:progress_callback
|
90
|
+
raise Errors::InvalidValue.new(option,value) unless value.nil? or value.is_a? Proc
|
88
91
|
when :off_t
|
89
92
|
return if value.nil?
|
90
93
|
func=:off_t
|
@@ -136,6 +139,7 @@ module Ethon
|
|
136
139
|
:cbdata => :objectpoint,
|
137
140
|
:callback => :functionpoint,
|
138
141
|
:debug_callback => :functionpoint,
|
142
|
+
:progress_callback => :functionpoint,
|
139
143
|
:off_t => :off_t,
|
140
144
|
}
|
141
145
|
|
@@ -247,7 +251,7 @@ module Ethon
|
|
247
251
|
option :easy, :opensocketdata, :cbdata, 164
|
248
252
|
option :easy, :closesocketfunction, :callback, 208
|
249
253
|
option :easy, :closesocketdata, :cbdata, 209
|
250
|
-
option :easy, :progressfunction, :
|
254
|
+
option :easy, :progressfunction, :progress_callback, 56
|
251
255
|
option :easy, :progressdata, :cbdata, 57
|
252
256
|
option :easy, :headerfunction, :callback, 79
|
253
257
|
option :easy, :writeheader, :cbdata, 29
|
@@ -266,6 +270,8 @@ module Ethon
|
|
266
270
|
option :easy, :chunk_data, :cbdata, 201
|
267
271
|
option :easy, :fnmatch_function, :callback, 200
|
268
272
|
option :easy, :fnmatch_data, :cbdata, 202
|
273
|
+
option :easy, :xferinfofunction, :progress_callback, 219
|
274
|
+
option :easy, :xferinfodata, :cbdata, 57
|
269
275
|
## ERROR OPTIONS
|
270
276
|
option :easy, :errorbuffer, :buffer, 10, 256
|
271
277
|
option :easy, :stderr, :dontuse_object, 37
|
data/lib/ethon/curls/settings.rb
CHANGED
@@ -2,6 +2,7 @@ module Ethon
|
|
2
2
|
module Curl
|
3
3
|
callback :callback, [:pointer, :size_t, :size_t, :pointer], :size_t
|
4
4
|
callback :debug_callback, [:pointer, :debug_info_type, :pointer, :size_t, :pointer], :int
|
5
|
+
callback :progress_callback, [:pointer, :long_long, :long_long, :long_long, :long_long], :int
|
5
6
|
ffi_lib_flags :now, :global
|
6
7
|
ffi_lib ['libcurl', 'libcurl.so.4']
|
7
8
|
end
|
data/lib/ethon/easy.rb
CHANGED
@@ -253,6 +253,7 @@ module Ethon
|
|
253
253
|
@on_complete = nil
|
254
254
|
@on_headers = nil
|
255
255
|
@on_body = nil
|
256
|
+
@on_progress = nil
|
256
257
|
@procs = nil
|
257
258
|
@mirror = nil
|
258
259
|
Curl.easy_reset(handle)
|
@@ -267,6 +268,7 @@ module Ethon
|
|
267
268
|
e.instance_variable_set(:@body_write_callback, nil)
|
268
269
|
e.instance_variable_set(:@header_write_callback, nil)
|
269
270
|
e.instance_variable_set(:@debug_callback, nil)
|
271
|
+
e.instance_variable_set(:@progress_callback, nil)
|
270
272
|
e.set_callbacks
|
271
273
|
e
|
272
274
|
end
|
data/lib/ethon/easy/callbacks.rb
CHANGED
@@ -72,6 +72,27 @@ module Ethon
|
|
72
72
|
}
|
73
73
|
end
|
74
74
|
|
75
|
+
def set_progress_callback
|
76
|
+
if Curl.version_info[:version] >= "7.32.0"
|
77
|
+
Curl.set_option(:xferinfofunction, progress_callback, handle)
|
78
|
+
else
|
79
|
+
Curl.set_option(:progressfunction, progress_callback, handle)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the progress callback.
|
84
|
+
#
|
85
|
+
# @example Return the callback.
|
86
|
+
# easy.progress_callback
|
87
|
+
#
|
88
|
+
# @return [ Proc ] The callback.
|
89
|
+
def progress_callback
|
90
|
+
@progress_callback ||= proc { |_, dltotal, dlnow, ultotal, ulnow|
|
91
|
+
progress(dltotal, dlnow, ultotal, ulnow)
|
92
|
+
0
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
75
96
|
# Set the read callback. This callback is used by libcurl to
|
76
97
|
# read data when performing a PUT request.
|
77
98
|
#
|
data/lib/ethon/easy/form.rb
CHANGED
@@ -21,9 +21,10 @@ module Ethon
|
|
21
21
|
# @param [ Hash ] params The parameter with which to initialize the form.
|
22
22
|
#
|
23
23
|
# @return [ Form ] A new Form.
|
24
|
-
def initialize(easy, params)
|
24
|
+
def initialize(easy, params, multipart = nil)
|
25
25
|
@easy = easy
|
26
26
|
@params = params || {}
|
27
|
+
@multipart = multipart
|
27
28
|
end
|
28
29
|
|
29
30
|
# Return a pointer to the first form element in libcurl.
|
@@ -47,13 +48,14 @@ module Ethon
|
|
47
48
|
end
|
48
49
|
|
49
50
|
# Return if form is multipart. The form is multipart
|
50
|
-
# when it contains a file.
|
51
|
+
# when it contains a file or multipart option is set on the form during creation.
|
51
52
|
#
|
52
53
|
# @example Return if form is multipart.
|
53
54
|
# form.multipart?
|
54
55
|
#
|
55
56
|
# @return [ Boolean ] True if form is multipart, else false.
|
56
57
|
def multipart?
|
58
|
+
return true if @multipart
|
57
59
|
query_pairs.any?{|pair| pair.respond_to?(:last) && pair.last.is_a?(Array)}
|
58
60
|
end
|
59
61
|
|
@@ -71,7 +71,7 @@ module Ethon
|
|
71
71
|
#
|
72
72
|
# @return [ Form ] The form.
|
73
73
|
def form
|
74
|
-
@form ||= Form.new(@easy, query_options.fetch(:body, nil))
|
74
|
+
@form ||= Form.new(@easy, query_options.fetch(:body, nil), options.fetch(:multipart, nil))
|
75
75
|
end
|
76
76
|
|
77
77
|
# Get the requested array encoding. By default it's
|
data/lib/ethon/easy/options.rb
CHANGED
@@ -16,8 +16,16 @@ module Ethon
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def escape?
|
19
|
-
return true if @escape
|
20
|
-
@escape
|
19
|
+
return true if !defined?(@escape) || @escape.nil?
|
20
|
+
@escape
|
21
|
+
end
|
22
|
+
|
23
|
+
def multipart=(b)
|
24
|
+
@multipart = b
|
25
|
+
end
|
26
|
+
|
27
|
+
def multipart?
|
28
|
+
!!@multipart
|
21
29
|
end
|
22
30
|
|
23
31
|
Curl.easy_options(nil).each do |opt, props|
|
@@ -69,6 +69,32 @@ module Ethon
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
# Set on_progress callback.
|
73
|
+
#
|
74
|
+
# @example Set on_progress.
|
75
|
+
# request.on_progress {|dltotal, dlnow, ultotal, ulnow| p "#{dltotal} #{dlnow} #{ultotal} #{ulnow}" }
|
76
|
+
#
|
77
|
+
# @param [ Block ] block The block to execute.
|
78
|
+
def on_progress(&block)
|
79
|
+
@on_progress ||= []
|
80
|
+
if block_given?
|
81
|
+
@on_progress << block
|
82
|
+
set_progress_callback
|
83
|
+
self.noprogress = 0
|
84
|
+
end
|
85
|
+
@on_progress
|
86
|
+
end
|
87
|
+
|
88
|
+
# Execute on_progress callbacks.
|
89
|
+
#
|
90
|
+
# @example Execute on_progress.
|
91
|
+
# request.body(1, 1, 1, 1)
|
92
|
+
def progress(dltotal, dlnow, ultotal, ulnow)
|
93
|
+
if defined?(@on_progress) and not @on_progress.nil?
|
94
|
+
@on_progress.each{ |callback| callback.call(dltotal, dlnow, ultotal, ulnow) }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
72
98
|
# Set on_body callback.
|
73
99
|
#
|
74
100
|
# @example Set on_body.
|
data/lib/ethon/version.rb
CHANGED
@@ -8,7 +8,7 @@ describe Ethon::Easy::Callbacks do
|
|
8
8
|
expect(Ethon::Curl).to receive(:set_option).exactly(3).times
|
9
9
|
end
|
10
10
|
|
11
|
-
it "sets write
|
11
|
+
it "sets write-, debug-, and headerfunction" do
|
12
12
|
easy.set_callbacks
|
13
13
|
end
|
14
14
|
|
@@ -28,6 +28,12 @@ describe Ethon::Easy::Callbacks do
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
describe "#progress_callback" do
|
32
|
+
it "returns 0" do
|
33
|
+
expect(easy.progress_callback.call(0,1,1,1,1)).to be(0)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
31
37
|
describe "#body_write_callback" do
|
32
38
|
let(:body_write_callback) { easy.instance_variable_get(:@body_write_callback) }
|
33
39
|
let(:stream) { double(:read_string => "") }
|
@@ -41,6 +41,15 @@ describe Ethon::Easy::Form do
|
|
41
41
|
expect(form.multipart?).to be_truthy
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
45
|
+
context "when options contains multipart=true" do
|
46
|
+
before { form.instance_variable_set(:@multipart, true) }
|
47
|
+
let(:pairs) { [['a', '1'], ['b', '2']] }
|
48
|
+
|
49
|
+
it "returns true" do
|
50
|
+
expect(form.multipart?).to be_truthy
|
51
|
+
end
|
52
|
+
end
|
44
53
|
end
|
45
54
|
|
46
55
|
describe "#materialize" do
|
@@ -74,6 +74,35 @@ describe Ethon::Easy::Options do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
describe '#multipart?' do
|
78
|
+
context 'by default' do
|
79
|
+
it 'returns false' do
|
80
|
+
expect(easy.multipart?).to be_falsey
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when #multipart=nil' do
|
85
|
+
it 'returns false' do
|
86
|
+
easy.multipart = nil
|
87
|
+
expect(easy.multipart?).to be_falsey
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'when #multipart=true' do
|
92
|
+
it 'returns true' do
|
93
|
+
easy.multipart = true
|
94
|
+
expect(easy.multipart?).to be_truthy
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'when #multipart=false' do
|
99
|
+
it 'returns false' do
|
100
|
+
easy.multipart = false
|
101
|
+
expect(easy.multipart?).to be_falsey
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
77
106
|
describe "#httppost=" do
|
78
107
|
it "raises unless given a FFI::Pointer" do
|
79
108
|
expect{ easy.httppost = 1 }.to raise_error(Ethon::Errors::InvalidValue)
|
@@ -152,9 +152,11 @@ describe Ethon::Easy::Queryable do
|
|
152
152
|
end
|
153
153
|
|
154
154
|
context "when MIME" do
|
155
|
-
|
156
|
-
|
157
|
-
|
155
|
+
if defined?(MIME)
|
156
|
+
context "when mime type" do
|
157
|
+
it "sets mime type to text" do
|
158
|
+
expect(mime_type).to eq("application/x-ruby")
|
159
|
+
end
|
158
160
|
end
|
159
161
|
end
|
160
162
|
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Ethon::Easy::ResponseCallbacks do
|
4
4
|
let(:easy) { Ethon::Easy.new }
|
5
5
|
|
6
|
-
[:on_complete, :on_headers, :on_body].each do |callback_type|
|
6
|
+
[:on_complete, :on_headers, :on_body, :on_progress].each do |callback_type|
|
7
7
|
describe "##{callback_type}" do
|
8
8
|
it "responds" do
|
9
9
|
expect(easy).to respond_to("#{callback_type}")
|
@@ -68,6 +68,62 @@ describe Ethon::Easy::ResponseCallbacks do
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
describe "#progress" do
|
72
|
+
context "when requesting for realz" do
|
73
|
+
it "executes callback" do
|
74
|
+
post = Ethon::Easy::Http::Post.new("http://localhost:3001", {:body => "bar=fu"})
|
75
|
+
post.setup(easy)
|
76
|
+
@called = false
|
77
|
+
@has_dltotal = false
|
78
|
+
@has_ultotal = false
|
79
|
+
easy.on_progress { @called = true }
|
80
|
+
easy.on_progress { |dltotal, _, _, _| @has_dltotal ||= true }
|
81
|
+
easy.on_progress { |_, _, ultotal, _| @has_ultotal ||= true }
|
82
|
+
easy.perform
|
83
|
+
expect(@called).to be true
|
84
|
+
expect(@has_dltotal).to be true
|
85
|
+
expect(@has_ultotal).to be true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when pretending" do
|
90
|
+
before do
|
91
|
+
@dltotal = nil
|
92
|
+
@dlnow = nil
|
93
|
+
@ultotal = nil
|
94
|
+
@ulnow = nil
|
95
|
+
easy.on_progress { |dltotal, dlnow, ultotal, ulnow| @dltotal = dltotal ; @dlnow = dlnow; @ultotal = ultotal; @ulnow = ulnow }
|
96
|
+
end
|
97
|
+
|
98
|
+
it "executes blocks and passes dltotal" do
|
99
|
+
easy.progress(1, 2, 3, 4)
|
100
|
+
expect(@dltotal).to eq(1)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "executes blocks and passes dlnow" do
|
104
|
+
easy.progress(1, 2, 3, 4)
|
105
|
+
expect(@dlnow).to eq(2)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "executes blocks and passes ultotal" do
|
109
|
+
easy.progress(1, 2, 3, 4)
|
110
|
+
expect(@ultotal).to eq(3)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "executes blocks and passes ulnow" do
|
114
|
+
easy.progress(1, 2, 3, 4)
|
115
|
+
expect(@ulnow).to eq(4)
|
116
|
+
end
|
117
|
+
|
118
|
+
context "when @on_progress nil" do
|
119
|
+
it "doesn't raise" do
|
120
|
+
easy.instance_variable_set(:@on_progress, nil)
|
121
|
+
expect{ easy.progress(1, 2, 3, 4) }.to_not raise_error
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
71
127
|
describe "#body" do
|
72
128
|
before do
|
73
129
|
@chunk = nil
|
data/spec/ethon/easy_spec.rb
CHANGED
@@ -105,6 +105,7 @@ describe Ethon::Easy do
|
|
105
105
|
easy.url = "http://localhost:3001/"
|
106
106
|
easy.on_complete { 'on_complete' }
|
107
107
|
easy.on_headers { 'on_headers' }
|
108
|
+
easy.on_progress { 'on_progress' }
|
108
109
|
easy.response_body = 'test_body'
|
109
110
|
easy.response_headers = 'test_headers'
|
110
111
|
easy
|
@@ -132,6 +133,10 @@ describe Ethon::Easy do
|
|
132
133
|
expect { easy.perform }.not_to change { e.response_body }
|
133
134
|
end
|
134
135
|
|
136
|
+
it "preserves on_progress callback" do
|
137
|
+
expect(e.on_progress).to be(easy.on_progress)
|
138
|
+
end
|
139
|
+
|
135
140
|
it 'sets new body_write_callback of duplicated handle' do
|
136
141
|
expect { e.perform }.to change { e.response_body }
|
137
142
|
expect { e.perform }.not_to change { easy.response_body }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ethon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hans Hasselberg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|