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 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