ethon 0.10.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +41 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +16 -1
- data/Gemfile +14 -4
- data/Guardfile +1 -0
- data/README.md +4 -1
- data/Rakefile +1 -0
- data/ethon.gemspec +2 -1
- data/lib/ethon.rb +1 -0
- data/lib/ethon/curl.rb +1 -0
- data/lib/ethon/curls/classes.rb +1 -0
- data/lib/ethon/curls/codes.rb +1 -1
- data/lib/ethon/curls/constants.rb +1 -0
- data/lib/ethon/curls/form_options.rb +1 -0
- data/lib/ethon/curls/functions.rb +4 -12
- data/lib/ethon/curls/infos.rb +4 -3
- data/lib/ethon/curls/messages.rb +1 -0
- data/lib/ethon/curls/options.rb +35 -23
- data/lib/ethon/curls/settings.rb +2 -0
- data/lib/ethon/easy.rb +3 -1
- data/lib/ethon/easy/callbacks.rb +25 -3
- data/lib/ethon/easy/debug_info.rb +1 -0
- data/lib/ethon/easy/features.rb +1 -0
- data/lib/ethon/easy/form.rb +5 -2
- data/lib/ethon/easy/header.rb +2 -7
- data/lib/ethon/easy/http.rb +1 -0
- data/lib/ethon/easy/http/actionable.rb +2 -1
- data/lib/ethon/easy/http/custom.rb +1 -0
- data/lib/ethon/easy/http/delete.rb +1 -0
- data/lib/ethon/easy/http/get.rb +1 -0
- data/lib/ethon/easy/http/head.rb +1 -0
- data/lib/ethon/easy/http/options.rb +1 -0
- data/lib/ethon/easy/http/patch.rb +1 -0
- data/lib/ethon/easy/http/post.rb +1 -0
- data/lib/ethon/easy/http/postable.rb +1 -0
- data/lib/ethon/easy/http/put.rb +1 -0
- data/lib/ethon/easy/http/putable.rb +1 -0
- data/lib/ethon/easy/informations.rb +1 -0
- data/lib/ethon/easy/mirror.rb +1 -0
- data/lib/ethon/easy/operations.rb +16 -1
- data/lib/ethon/easy/options.rb +11 -2
- data/lib/ethon/easy/params.rb +1 -0
- data/lib/ethon/easy/queryable.rb +4 -1
- data/lib/ethon/easy/response_callbacks.rb +27 -0
- data/lib/ethon/easy/util.rb +1 -0
- data/lib/ethon/errors.rb +1 -0
- data/lib/ethon/errors/ethon_error.rb +1 -0
- data/lib/ethon/errors/global_init.rb +1 -0
- data/lib/ethon/errors/invalid_option.rb +1 -0
- data/lib/ethon/errors/invalid_value.rb +1 -0
- data/lib/ethon/errors/multi_add.rb +1 -0
- data/lib/ethon/errors/multi_fdset.rb +1 -0
- data/lib/ethon/errors/multi_remove.rb +1 -0
- data/lib/ethon/errors/multi_timeout.rb +1 -0
- data/lib/ethon/errors/select.rb +1 -0
- data/lib/ethon/libc.rb +1 -0
- data/lib/ethon/loggable.rb +1 -0
- data/lib/ethon/multi.rb +1 -0
- data/lib/ethon/multi/operations.rb +1 -0
- data/lib/ethon/multi/options.rb +9 -8
- data/lib/ethon/multi/stack.rb +1 -0
- data/lib/ethon/version.rb +2 -1
- data/profile/benchmarks.rb +1 -0
- data/profile/memory_leaks.rb +1 -0
- data/profile/perf_spec_helper.rb +1 -0
- data/profile/support/memory_test_helpers.rb +1 -0
- data/profile/support/os_memory_leak_tracker.rb +1 -0
- data/profile/support/ruby_object_leak_tracker.rb +1 -0
- data/spec/ethon/curl_spec.rb +1 -0
- data/spec/ethon/easy/callbacks_spec.rb +8 -1
- data/spec/ethon/easy/debug_info_spec.rb +2 -0
- data/spec/ethon/easy/features_spec.rb +1 -0
- data/spec/ethon/easy/form_spec.rb +10 -0
- data/spec/ethon/easy/header_spec.rb +1 -30
- data/spec/ethon/easy/http/custom_spec.rb +1 -0
- data/spec/ethon/easy/http/delete_spec.rb +1 -0
- data/spec/ethon/easy/http/get_spec.rb +1 -0
- data/spec/ethon/easy/http/head_spec.rb +1 -0
- data/spec/ethon/easy/http/options_spec.rb +1 -0
- data/spec/ethon/easy/http/patch_spec.rb +1 -0
- data/spec/ethon/easy/http/post_spec.rb +1 -0
- data/spec/ethon/easy/http/put_spec.rb +1 -0
- data/spec/ethon/easy/http_spec.rb +1 -0
- data/spec/ethon/easy/informations_spec.rb +1 -0
- data/spec/ethon/easy/mirror_spec.rb +1 -0
- data/spec/ethon/easy/operations_spec.rb +1 -0
- data/spec/ethon/easy/options_spec.rb +31 -1
- data/spec/ethon/easy/queryable_spec.rb +14 -3
- data/spec/ethon/easy/response_callbacks_spec.rb +58 -1
- data/spec/ethon/easy/util_spec.rb +1 -0
- data/spec/ethon/easy_spec.rb +8 -2
- data/spec/ethon/libc_spec.rb +1 -0
- data/spec/ethon/loggable_spec.rb +1 -0
- data/spec/ethon/multi/operations_spec.rb +1 -0
- data/spec/ethon/multi/options_spec.rb +1 -0
- data/spec/ethon/multi/stack_spec.rb +1 -0
- data/spec/ethon/multi_spec.rb +1 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/localhost_server.rb +2 -1
- data/spec/support/server.rb +1 -0
- metadata +6 -7
- data/.travis.yml +0 -26
data/lib/ethon/curls/settings.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Ethon
|
2
3
|
module Curl
|
3
4
|
callback :callback, [:pointer, :size_t, :size_t, :pointer], :size_t
|
4
5
|
callback :debug_callback, [:pointer, :debug_info_type, :pointer, :size_t, :pointer], :int
|
6
|
+
callback :progress_callback, [:pointer, :long_long, :long_long, :long_long, :long_long], :int
|
5
7
|
ffi_lib_flags :now, :global
|
6
8
|
ffi_lib ['libcurl', 'libcurl.so.4']
|
7
9
|
end
|
data/lib/ethon/easy.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'ethon/easy/informations'
|
2
3
|
require 'ethon/easy/features'
|
3
4
|
require 'ethon/easy/callbacks'
|
@@ -159,7 +160,6 @@ module Ethon
|
|
159
160
|
# * :recv_error: Failure with receiving network data.
|
160
161
|
# * :ssl_certproblem: problem with the local client certificate.
|
161
162
|
# * :ssl_cipher: Couldn't use specified cipher.
|
162
|
-
# * :ssl_cacert: Peer certificate cannot be authenticated with known CA certificates.
|
163
163
|
# * :bad_content_encoding: Unrecognized transfer encoding.
|
164
164
|
# * :ldap_invalid_url: Invalid LDAP URL.
|
165
165
|
# * :filesize_exceeded: Maximum file size exceeded.
|
@@ -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
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Ethon
|
2
3
|
class Easy
|
3
4
|
|
@@ -22,8 +23,8 @@ module Ethon
|
|
22
23
|
Curl.set_option(:writefunction, body_write_callback, handle)
|
23
24
|
Curl.set_option(:headerfunction, header_write_callback, handle)
|
24
25
|
Curl.set_option(:debugfunction, debug_callback, handle)
|
25
|
-
@response_body =
|
26
|
-
@response_headers =
|
26
|
+
@response_body = String.new
|
27
|
+
@response_headers = String.new
|
27
28
|
@headers_called = false
|
28
29
|
@debug_info = Ethon::Easy::DebugInfo.new
|
29
30
|
end
|
@@ -60,7 +61,7 @@ module Ethon
|
|
60
61
|
# write the raw http request headers.
|
61
62
|
#
|
62
63
|
# @example Return the callback.
|
63
|
-
# easy.
|
64
|
+
# easy.debug_callback
|
64
65
|
#
|
65
66
|
# @return [ Proc ] The callback.
|
66
67
|
def debug_callback
|
@@ -72,6 +73,27 @@ module Ethon
|
|
72
73
|
}
|
73
74
|
end
|
74
75
|
|
76
|
+
def set_progress_callback
|
77
|
+
if Curl.version_info[:version] >= "7.32.0"
|
78
|
+
Curl.set_option(:xferinfofunction, progress_callback, handle)
|
79
|
+
else
|
80
|
+
Curl.set_option(:progressfunction, progress_callback, handle)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the progress callback.
|
85
|
+
#
|
86
|
+
# @example Return the callback.
|
87
|
+
# easy.progress_callback
|
88
|
+
#
|
89
|
+
# @return [ Proc ] The callback.
|
90
|
+
def progress_callback
|
91
|
+
@progress_callback ||= proc { |_, dltotal, dlnow, ultotal, ulnow|
|
92
|
+
progress(dltotal, dlnow, ultotal, ulnow)
|
93
|
+
0
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
75
97
|
# Set the read callback. This callback is used by libcurl to
|
76
98
|
# read data when performing a PUT request.
|
77
99
|
#
|
data/lib/ethon/easy/features.rb
CHANGED
data/lib/ethon/easy/form.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'ethon/easy/util'
|
2
3
|
require 'ethon/easy/queryable'
|
3
4
|
|
@@ -21,9 +22,10 @@ module Ethon
|
|
21
22
|
# @param [ Hash ] params The parameter with which to initialize the form.
|
22
23
|
#
|
23
24
|
# @return [ Form ] A new Form.
|
24
|
-
def initialize(easy, params)
|
25
|
+
def initialize(easy, params, multipart = nil)
|
25
26
|
@easy = easy
|
26
27
|
@params = params || {}
|
28
|
+
@multipart = multipart
|
27
29
|
end
|
28
30
|
|
29
31
|
# Return a pointer to the first form element in libcurl.
|
@@ -47,13 +49,14 @@ module Ethon
|
|
47
49
|
end
|
48
50
|
|
49
51
|
# Return if form is multipart. The form is multipart
|
50
|
-
# when it contains a file.
|
52
|
+
# when it contains a file or multipart option is set on the form during creation.
|
51
53
|
#
|
52
54
|
# @example Return if form is multipart.
|
53
55
|
# form.multipart?
|
54
56
|
#
|
55
57
|
# @return [ Boolean ] True if form is multipart, else false.
|
56
58
|
def multipart?
|
59
|
+
return true if @multipart
|
57
60
|
query_pairs.any?{|pair| pair.respond_to?(:last) && pair.last.is_a?(Array)}
|
58
61
|
end
|
59
62
|
|
data/lib/ethon/easy/header.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Ethon
|
2
3
|
class Easy
|
3
4
|
# This module contains the logic around adding headers to libcurl.
|
4
5
|
#
|
5
6
|
# @api private
|
6
7
|
module Header
|
7
|
-
EMPTY_STRING_VALUE = "".freeze
|
8
|
-
|
9
8
|
# Return headers, return empty hash if none.
|
10
9
|
#
|
11
10
|
# @example Return the headers.
|
@@ -55,11 +54,7 @@ module Ethon
|
|
55
54
|
#
|
56
55
|
# @return [ String ] The composed header.
|
57
56
|
def compose_header(key, value)
|
58
|
-
|
59
|
-
Util.escape_zero_byte("#{key};")
|
60
|
-
else
|
61
|
-
Util.escape_zero_byte("#{key}: #{value}")
|
62
|
-
end
|
57
|
+
Util.escape_zero_byte("#{key}: #{value}")
|
63
58
|
end
|
64
59
|
end
|
65
60
|
end
|
data/lib/ethon/easy/http.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'ethon/easy/http/putable'
|
2
3
|
require 'ethon/easy/http/postable'
|
3
4
|
|
@@ -71,7 +72,7 @@ module Ethon
|
|
71
72
|
#
|
72
73
|
# @return [ Form ] The form.
|
73
74
|
def form
|
74
|
-
@form ||= Form.new(@easy, query_options.fetch(:body, nil))
|
75
|
+
@form ||= Form.new(@easy, query_options.fetch(:body, nil), options.fetch(:multipart, nil))
|
75
76
|
end
|
76
77
|
|
77
78
|
# Get the requested array encoding. By default it's
|
data/lib/ethon/easy/http/get.rb
CHANGED
data/lib/ethon/easy/http/head.rb
CHANGED
data/lib/ethon/easy/http/post.rb
CHANGED
data/lib/ethon/easy/http/put.rb
CHANGED
data/lib/ethon/easy/mirror.rb
CHANGED
@@ -1,8 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Ethon
|
2
3
|
class Easy
|
3
4
|
# This module contains the logic to prepare and perform
|
4
5
|
# an easy.
|
5
6
|
module Operations
|
7
|
+
|
8
|
+
class PointerHelper
|
9
|
+
class<<self
|
10
|
+
def synchronize( &block )
|
11
|
+
(@mutex ||= Mutex.new).synchronize( &block )
|
12
|
+
end
|
13
|
+
|
14
|
+
def release( pointer )
|
15
|
+
synchronize { Curl.easy_cleanup pointer }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
synchronize{}
|
19
|
+
end
|
20
|
+
|
6
21
|
# Returns a pointer to the curl easy handle.
|
7
22
|
#
|
8
23
|
# @example Return the handle.
|
@@ -10,7 +25,7 @@ module Ethon
|
|
10
25
|
#
|
11
26
|
# @return [ FFI::Pointer ] A pointer to the curl easy handle.
|
12
27
|
def handle
|
13
|
-
@handle ||= FFI::AutoPointer.new(Curl.easy_init,
|
28
|
+
@handle ||= FFI::AutoPointer.new(Curl.easy_init, PointerHelper.method(:release) )
|
14
29
|
end
|
15
30
|
|
16
31
|
# Sets a pointer to the curl easy handle.
|
data/lib/ethon/easy/options.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Ethon
|
2
3
|
class Easy
|
3
4
|
|
@@ -16,8 +17,16 @@ module Ethon
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def escape?
|
19
|
-
return true if @escape
|
20
|
-
@escape
|
20
|
+
return true if !defined?(@escape) || @escape.nil?
|
21
|
+
@escape
|
22
|
+
end
|
23
|
+
|
24
|
+
def multipart=(b)
|
25
|
+
@multipart = b
|
26
|
+
end
|
27
|
+
|
28
|
+
def multipart?
|
29
|
+
!!@multipart
|
21
30
|
end
|
22
31
|
|
23
32
|
Curl.easy_options(nil).each do |opt, props|
|
data/lib/ethon/easy/params.rb
CHANGED
data/lib/ethon/easy/queryable.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Ethon
|
2
3
|
class Easy
|
3
4
|
|
@@ -102,6 +103,8 @@ module Ethon
|
|
102
103
|
encode_rack_array_pairs(h, prefix, pairs)
|
103
104
|
elsif params_encoding == :multi
|
104
105
|
encode_multi_array_pairs(h, prefix, pairs)
|
106
|
+
elsif params_encoding == :none
|
107
|
+
pairs << [prefix, h]
|
105
108
|
else
|
106
109
|
encode_indexed_array_pairs(h, prefix, pairs)
|
107
110
|
end
|
@@ -128,7 +131,7 @@ module Ethon
|
|
128
131
|
pairs_for(v, key, pairs)
|
129
132
|
end
|
130
133
|
end
|
131
|
-
|
134
|
+
|
132
135
|
def encode_multi_array_pairs(h, prefix, pairs)
|
133
136
|
h.each_with_index do |v, i|
|
134
137
|
key = prefix
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Ethon
|
2
3
|
class Easy
|
3
4
|
|
@@ -69,6 +70,32 @@ module Ethon
|
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
73
|
+
# Set on_progress callback.
|
74
|
+
#
|
75
|
+
# @example Set on_progress.
|
76
|
+
# request.on_progress {|dltotal, dlnow, ultotal, ulnow| p "#{dltotal} #{dlnow} #{ultotal} #{ulnow}" }
|
77
|
+
#
|
78
|
+
# @param [ Block ] block The block to execute.
|
79
|
+
def on_progress(&block)
|
80
|
+
@on_progress ||= []
|
81
|
+
if block_given?
|
82
|
+
@on_progress << block
|
83
|
+
set_progress_callback
|
84
|
+
self.noprogress = 0
|
85
|
+
end
|
86
|
+
@on_progress
|
87
|
+
end
|
88
|
+
|
89
|
+
# Execute on_progress callbacks.
|
90
|
+
#
|
91
|
+
# @example Execute on_progress.
|
92
|
+
# request.body(1, 1, 1, 1)
|
93
|
+
def progress(dltotal, dlnow, ultotal, ulnow)
|
94
|
+
if defined?(@on_progress) and not @on_progress.nil?
|
95
|
+
@on_progress.each{ |callback| callback.call(dltotal, dlnow, ultotal, ulnow) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
72
99
|
# Set on_body callback.
|
73
100
|
#
|
74
101
|
# @example Set on_body.
|
data/lib/ethon/easy/util.rb
CHANGED
data/lib/ethon/errors.rb
CHANGED