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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3cc64826630c9f25f87d4a4140a9cecc43575994
4
- data.tar.gz: 01f6e1dc05161204a18eabe86e64c941fcb5bda1
3
+ metadata.gz: ac54c9df1c6dfd22a65124a64c7bb93b2792dc55
4
+ data.tar.gz: 5fedd427db76181d6bde8c7c4af4116bdf1cc272
5
5
  SHA512:
6
- metadata.gz: d98725e35b6e1d81fcd4f2b1207d54f178e058230b2bbf49249e94e4ff05067d8e7a5e6cdfb7be2465ac7a2c6f8b4a7145e5bf9e291817dd0e1661c87816f595
7
- data.tar.gz: a60d5cd6436990a8f58d3ef5c2eb47167998b6ade221fdaa66e6464b2119d3a6e395e660ef17031dc72eec059f9b92dc0f4187e57b3d032dd30a5c29cd74f20b
6
+ metadata.gz: 538f6d8f6af52a294d72ecc3f63f8a2a7ed97f90154382979edfbdc6085f38e16ea4e336f1cdff3d107551402ba2408b87f8632added41b2915744b97da47c3c
7
+ data.tar.gz: 54695f47f42ea0838c8da9531d136b52d6d77a8e5cd10374929c878b6ff55f572727d1e8afa3b854672ba6bbbcb5eff1d0d25091bc6d5f1ad6df0d757eeecb6e
@@ -4,6 +4,8 @@ sudo: false
4
4
 
5
5
  bundler_args: --without perf
6
6
  script: bundle exec rake
7
+ before_install:
8
+ - gem install bundler
7
9
 
8
10
  rvm:
9
11
  - 1.8.7
data/Gemfile CHANGED
@@ -18,11 +18,16 @@ group :development, :test do
18
18
  gem "json"
19
19
  end
20
20
 
21
- gem "mime-types", "~> 1.18"
21
+ if Gem.ruby_version >= Gem::Version.new("2.0.0")
22
+ gem "mime-types", "~> 1.18"
23
+ end
22
24
 
23
- unless ENV["CI"]
24
- gem "guard-rspec", "~> 0.7"
25
- gem "rb-fsevent", "~> 0.9.1"
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
- # Ethon [![Build Status](https://secure.travis-ci.org/typhoeus/ethon.png?branch=master)](http://travis-ci.org/typhoeus/ethon) [![Gem Version](https://badge.fury.io/rb/ethon.png)](http://badge.fury.io/rb/ethon)
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
@@ -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, :callback, 56
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
@@ -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
@@ -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
@@ -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
  #
@@ -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
@@ -16,8 +16,16 @@ module Ethon
16
16
  end
17
17
 
18
18
  def escape?
19
- return true if @escape
20
- @escape.nil? ? true : false
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.
@@ -1,5 +1,5 @@
1
1
  module Ethon
2
2
 
3
3
  # Ethon version.
4
- VERSION = '0.10.1'
4
+ VERSION = '0.11.0'
5
5
  end
@@ -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- and headerfunction" do
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 => "") }
@@ -23,6 +23,7 @@ describe Ethon::Easy::DebugInfo do
23
23
  end
24
24
 
25
25
  after do
26
+ easy.verbose = false
26
27
  easy.reset
27
28
  end
28
29
 
@@ -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
- context "when mime type" do
156
- it "sets mime type to text" do
157
- expect(mime_type).to eq("application/x-ruby")
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
@@ -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.10.1
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: 2016-12-02 00:00:00.000000000 Z
11
+ date: 2017-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi