ethon 0.10.1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/ethon.svg)](https://badge.fury.io/rb/ethon)
|
2
|
+
[![Build Status](https://travis-ci.org/typhoeus/ethon.svg?branch=master)](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
|