ethon 0.16.0 → 0.17.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/CHANGELOG.md +26 -1
- data/README.md +1 -1
- data/ethon.gemspec +6 -3
- data/lib/ethon/curls/codes.rb +3 -2
- data/lib/ethon/version.rb +1 -1
- metadata +6 -85
- data/.github/workflows/ruby.yml +0 -41
- data/.gitignore +0 -8
- data/.rspec +0 -3
- data/Gemfile +0 -43
- data/Guardfile +0 -10
- data/Rakefile +0 -40
- data/profile/benchmarks.rb +0 -104
- data/profile/memory_leaks.rb +0 -114
- data/profile/perf_spec_helper.rb +0 -37
- data/profile/support/memory_test_helpers.rb +0 -76
- data/profile/support/os_memory_leak_tracker.rb +0 -48
- data/profile/support/ruby_object_leak_tracker.rb +0 -49
- data/spec/ethon/curl_spec.rb +0 -38
- data/spec/ethon/easy/callbacks_spec.rb +0 -81
- data/spec/ethon/easy/debug_info_spec.rb +0 -54
- data/spec/ethon/easy/features_spec.rb +0 -24
- data/spec/ethon/easy/form_spec.rb +0 -104
- data/spec/ethon/easy/header_spec.rb +0 -79
- data/spec/ethon/easy/http/custom_spec.rb +0 -177
- data/spec/ethon/easy/http/delete_spec.rb +0 -21
- data/spec/ethon/easy/http/get_spec.rb +0 -126
- data/spec/ethon/easy/http/head_spec.rb +0 -80
- data/spec/ethon/easy/http/options_spec.rb +0 -51
- data/spec/ethon/easy/http/patch_spec.rb +0 -51
- data/spec/ethon/easy/http/post_spec.rb +0 -317
- data/spec/ethon/easy/http/put_spec.rb +0 -168
- data/spec/ethon/easy/http_spec.rb +0 -64
- data/spec/ethon/easy/informations_spec.rb +0 -126
- data/spec/ethon/easy/mirror_spec.rb +0 -47
- data/spec/ethon/easy/operations_spec.rb +0 -271
- data/spec/ethon/easy/options_spec.rb +0 -193
- data/spec/ethon/easy/queryable_spec.rb +0 -235
- data/spec/ethon/easy/response_callbacks_spec.rb +0 -152
- data/spec/ethon/easy/util_spec.rb +0 -28
- data/spec/ethon/easy_spec.rb +0 -203
- data/spec/ethon/libc_spec.rb +0 -14
- data/spec/ethon/loggable_spec.rb +0 -22
- data/spec/ethon/multi/operations_spec.rb +0 -298
- data/spec/ethon/multi/options_spec.rb +0 -182
- data/spec/ethon/multi/stack_spec.rb +0 -80
- data/spec/ethon/multi_spec.rb +0 -152
- data/spec/spec_helper.rb +0 -28
- data/spec/support/localhost_server.rb +0 -95
- data/spec/support/server.rb +0 -115
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe Ethon::Easy::Mirror do
|
5
|
-
let(:options) { nil }
|
6
|
-
let(:mirror) { described_class.new(options) }
|
7
|
-
|
8
|
-
describe "::INFORMATIONS_TO_LOG" do
|
9
|
-
[
|
10
|
-
:return_code, :response_code, :response_body, :response_headers,
|
11
|
-
:total_time, :starttransfer_time, :appconnect_time,
|
12
|
-
:pretransfer_time, :connect_time, :namelookup_time, :redirect_time,
|
13
|
-
:size_upload, :size_download, :speed_upload, :speed_upload,
|
14
|
-
:effective_url, :primary_ip, :redirect_count, :redirect_url, :debug_info
|
15
|
-
].each do |name|
|
16
|
-
it "contains #{name}" do
|
17
|
-
expect(described_class::INFORMATIONS_TO_MIRROR).to include(name)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "#to_hash" do
|
23
|
-
let(:options) { {:return_code => 1} }
|
24
|
-
|
25
|
-
it "returns mirror as hash" do
|
26
|
-
expect(mirror.to_hash).to eq(options)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "#log_informations" do
|
31
|
-
let(:options) { {:return_code => 1} }
|
32
|
-
|
33
|
-
it "returns hash" do
|
34
|
-
expect(mirror.log_informations).to be_a(Hash)
|
35
|
-
end
|
36
|
-
|
37
|
-
it "only calls methods that exist" do
|
38
|
-
described_class::INFORMATIONS_TO_LOG.each do |method_name|
|
39
|
-
expect(mirror.respond_to? method_name).to eql(true)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
it "includes return code" do
|
44
|
-
expect(mirror.log_informations).to include(options)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,271 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe Ethon::Easy::Operations do
|
5
|
-
let(:easy) { Ethon::Easy.new }
|
6
|
-
|
7
|
-
describe "#handle" do
|
8
|
-
it "returns a pointer" do
|
9
|
-
expect(easy.handle).to be_a(FFI::Pointer)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
|
14
|
-
describe "#perform" do
|
15
|
-
let(:url) { nil }
|
16
|
-
let(:timeout) { nil }
|
17
|
-
let(:connect_timeout) { nil }
|
18
|
-
let(:follow_location) { nil }
|
19
|
-
let(:max_redirs) { nil }
|
20
|
-
let(:user_pwd) { nil }
|
21
|
-
let(:http_auth) { nil }
|
22
|
-
let(:headers) { nil }
|
23
|
-
let(:protocols) { nil }
|
24
|
-
let(:redir_protocols) { nil }
|
25
|
-
let(:username) { nil }
|
26
|
-
let(:password) { nil }
|
27
|
-
|
28
|
-
before do
|
29
|
-
Ethon.logger.level = Logger::DEBUG
|
30
|
-
easy.url = url
|
31
|
-
easy.timeout = timeout
|
32
|
-
easy.connecttimeout = connect_timeout
|
33
|
-
easy.followlocation = follow_location
|
34
|
-
easy.maxredirs = max_redirs
|
35
|
-
easy.httpauth = http_auth
|
36
|
-
easy.headers = headers
|
37
|
-
easy.protocols = protocols
|
38
|
-
easy.redir_protocols = redir_protocols
|
39
|
-
|
40
|
-
if user_pwd
|
41
|
-
easy.userpwd = user_pwd
|
42
|
-
else
|
43
|
-
easy.username = username
|
44
|
-
easy.password = password
|
45
|
-
end
|
46
|
-
|
47
|
-
easy.perform
|
48
|
-
end
|
49
|
-
|
50
|
-
it "calls Curl.easy_perform" do
|
51
|
-
expect(Ethon::Curl).to receive(:easy_perform)
|
52
|
-
easy.perform
|
53
|
-
end
|
54
|
-
|
55
|
-
it "calls Curl.easy_cleanup" do
|
56
|
-
expect_any_instance_of(FFI::AutoPointer).to receive(:free)
|
57
|
-
easy.cleanup
|
58
|
-
end
|
59
|
-
|
60
|
-
it "logs" do
|
61
|
-
expect(Ethon.logger).to receive(:debug)
|
62
|
-
easy.perform
|
63
|
-
end
|
64
|
-
|
65
|
-
it "doesn't log after completing because completing could reset" do
|
66
|
-
easy.on_complete{ expect(Ethon.logger).to receive(:debug).never }
|
67
|
-
easy.perform
|
68
|
-
end
|
69
|
-
|
70
|
-
context "when url" do
|
71
|
-
let(:url) { "http://localhost:3001/" }
|
72
|
-
|
73
|
-
it "returns ok" do
|
74
|
-
expect(easy.return_code).to eq(:ok)
|
75
|
-
end
|
76
|
-
|
77
|
-
it "sets response body" do
|
78
|
-
expect(easy.response_body).to be
|
79
|
-
end
|
80
|
-
|
81
|
-
it "sets response headers" do
|
82
|
-
expect(easy.response_headers).to be
|
83
|
-
end
|
84
|
-
|
85
|
-
context "when request timed out" do
|
86
|
-
let(:url) { "http://localhost:3001/?delay=1" }
|
87
|
-
let(:timeout) { 1 }
|
88
|
-
|
89
|
-
it "returns operation_timedout" do
|
90
|
-
expect(easy.return_code).to eq(:operation_timedout)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context "when connection timed out" do
|
95
|
-
let(:url) { "http://localhost:3009" }
|
96
|
-
let(:connect_timeout) { 1 }
|
97
|
-
|
98
|
-
it "returns couldnt_connect" do
|
99
|
-
expect(easy.return_code).to eq(:couldnt_connect)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context "when no follow location" do
|
104
|
-
let(:url) { "http://localhost:3001/redirect" }
|
105
|
-
let(:follow_location) { false }
|
106
|
-
|
107
|
-
it "doesn't follow" do
|
108
|
-
expect(easy.response_code).to eq(302)
|
109
|
-
expect(easy.redirect_url).to eq("http://localhost:3001/")
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context "when follow location" do
|
114
|
-
let(:url) { "http://localhost:3001/redirect" }
|
115
|
-
let(:follow_location) { true }
|
116
|
-
|
117
|
-
it "follows" do
|
118
|
-
expect(easy.response_code).to eq(200)
|
119
|
-
expect(easy.redirect_url).to eq(nil)
|
120
|
-
end
|
121
|
-
|
122
|
-
context "when infinite redirect loop" do
|
123
|
-
let(:url) { "http://localhost:3001/bad_redirect" }
|
124
|
-
let(:max_redirs) { 5 }
|
125
|
-
|
126
|
-
context "when max redirect set" do
|
127
|
-
it "follows only x times" do
|
128
|
-
expect(easy.response_code).to eq(302)
|
129
|
-
expect(easy.redirect_url).to eq("http://localhost:3001/bad_redirect")
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
context "when user agent" do
|
136
|
-
let(:headers) { { 'User-Agent' => 'Ethon' } }
|
137
|
-
|
138
|
-
it "sets" do
|
139
|
-
expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"')
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
context "when auth url" do
|
145
|
-
before { easy.url = url }
|
146
|
-
|
147
|
-
context "when basic auth" do
|
148
|
-
let(:url) { "http://localhost:3001/auth_basic/username/password" }
|
149
|
-
|
150
|
-
context "when no user_pwd" do
|
151
|
-
it "returns 401" do
|
152
|
-
expect(easy.response_code).to eq(401)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
context "when invalid user_pwd" do
|
157
|
-
let(:user_pwd) { "invalid:invalid" }
|
158
|
-
|
159
|
-
it "returns 401" do
|
160
|
-
expect(easy.response_code).to eq(401)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
context "when valid user_pwd" do
|
165
|
-
let(:user_pwd) { "username:password" }
|
166
|
-
|
167
|
-
it "returns 200" do
|
168
|
-
expect(easy.response_code).to eq(200)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
context "when user and password" do
|
173
|
-
let(:username) { "username" }
|
174
|
-
let(:password) { "password" }
|
175
|
-
|
176
|
-
it "returns 200" do
|
177
|
-
expect(easy.response_code).to eq(200)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
context "when ntlm" do
|
183
|
-
let(:url) { "http://localhost:3001/auth_ntlm" }
|
184
|
-
let(:http_auth) { :ntlm }
|
185
|
-
|
186
|
-
context "when no user_pwd" do
|
187
|
-
it "returns 401" do
|
188
|
-
expect(easy.response_code).to eq(401)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
context "when user_pwd" do
|
193
|
-
let(:user_pwd) { "username:password" }
|
194
|
-
|
195
|
-
it "returns 200" do
|
196
|
-
expect(easy.response_code).to eq(200)
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
context "when protocols" do
|
203
|
-
context "when asking for a allowed url" do
|
204
|
-
let(:url) { "http://localhost:3001" }
|
205
|
-
let(:protocols) { :http }
|
206
|
-
|
207
|
-
it "returns ok" do
|
208
|
-
expect(easy.return_code).to be(:ok)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
context "when asking for a not allowed url" do
|
213
|
-
let(:url) { "http://localhost:3001" }
|
214
|
-
let(:protocols) { :https }
|
215
|
-
|
216
|
-
it "returns unsupported_protocol" do
|
217
|
-
expect(easy.return_code).to be(:unsupported_protocol)
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
context "when multiple protocols" do
|
223
|
-
context "when asking for a allowed url" do
|
224
|
-
let(:protocols) { [:http, :https] }
|
225
|
-
|
226
|
-
context "when http" do
|
227
|
-
let(:url) { "http://localhost:3001" }
|
228
|
-
|
229
|
-
it "returns ok for http" do
|
230
|
-
expect(easy.return_code).to be(:ok)
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
context "when https" do
|
235
|
-
let(:url) { "https://localhost:3001" }
|
236
|
-
|
237
|
-
it "returns ssl_connect_error for https" do
|
238
|
-
expect(easy.return_code).to be(:ssl_connect_error)
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
context "when asking for a not allowed url" do
|
244
|
-
let(:url) { "ssh://localhost" }
|
245
|
-
let(:protocols) { [:https, :http] }
|
246
|
-
|
247
|
-
it "returns unsupported_protocol" do
|
248
|
-
expect(easy.return_code).to be(:unsupported_protocol)
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
context "when redir_protocols" do
|
254
|
-
context "when redirecting to a not allowed url" do
|
255
|
-
let(:url) { "http://localhost:3001/redirect" }
|
256
|
-
let(:follow_location) { true }
|
257
|
-
let(:redir_protocols) { :https }
|
258
|
-
|
259
|
-
it "returns unsupported_protocol" do
|
260
|
-
expect(easy.return_code).to be(:unsupported_protocol)
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
context "when no url" do
|
266
|
-
it "returns url_malformat" do
|
267
|
-
expect(easy.perform).to eq(:url_malformat)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
@@ -1,193 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe Ethon::Easy::Options do
|
5
|
-
let(:easy) { Ethon::Easy.new }
|
6
|
-
|
7
|
-
[
|
8
|
-
:accept_encoding, :cainfo, :capath, :connecttimeout, :connecttimeout_ms, :cookie,
|
9
|
-
:cookiejar, :cookiefile, :copypostfields, :customrequest, :dns_cache_timeout,
|
10
|
-
:followlocation, :forbid_reuse, :http_version, :httpauth, :httpget, :httppost,
|
11
|
-
:infilesize, :interface, :keypasswd, :maxredirs, :nobody, :nosignal,
|
12
|
-
:postfieldsize, :postredir, :protocols, :proxy, :proxyauth, :proxyport, :proxytype,
|
13
|
-
:proxyuserpwd, :readdata, :readfunction, :redir_protocols, :ssl_verifyhost,
|
14
|
-
:ssl_verifypeer, :sslcert, :sslcerttype, :sslkey, :sslkeytype, :sslversion,
|
15
|
-
:timeout, :timeout_ms, :unrestricted_auth, :upload, :url, :useragent,
|
16
|
-
:userpwd, :verbose, :pipewait, :dns_shuffle_addresses, :path_as_is
|
17
|
-
].each do |name|
|
18
|
-
describe "#{name}=" do
|
19
|
-
it "responds_to" do
|
20
|
-
expect(easy).to respond_to("#{name}=")
|
21
|
-
end
|
22
|
-
|
23
|
-
it "sets option" do
|
24
|
-
expect_any_instance_of(Ethon::Easy).to receive(:set_callbacks)
|
25
|
-
expect(Ethon::Curl).to receive(:set_option).with(name, anything, anything)
|
26
|
-
value = case name
|
27
|
-
when :http_version
|
28
|
-
:httpv1_0
|
29
|
-
when :httpauth
|
30
|
-
:basic
|
31
|
-
when :protocols, :redir_protocols
|
32
|
-
:http
|
33
|
-
when :postredir
|
34
|
-
:post_301
|
35
|
-
when :proxytype
|
36
|
-
:http
|
37
|
-
when :sslversion
|
38
|
-
:default
|
39
|
-
when :httppost
|
40
|
-
FFI::Pointer::NULL
|
41
|
-
else
|
42
|
-
1
|
43
|
-
end
|
44
|
-
easy.method("#{name}=").call(value)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe '#escape?' do
|
50
|
-
context 'by default' do
|
51
|
-
it 'returns true' do
|
52
|
-
expect(easy.escape?).to be_truthy
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'when #escape=nil' do
|
57
|
-
it 'returns true' do
|
58
|
-
easy.escape = nil
|
59
|
-
expect(easy.escape?).to be_truthy
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context 'when #escape=true' do
|
64
|
-
it 'returns true' do
|
65
|
-
easy.escape = true
|
66
|
-
expect(easy.escape?).to be_truthy
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
context 'when #escape=false' do
|
71
|
-
it 'returns true' do
|
72
|
-
easy.escape = false
|
73
|
-
expect(easy.escape?).to be_falsey
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
describe '#multipart?' do
|
79
|
-
context 'by default' do
|
80
|
-
it 'returns false' do
|
81
|
-
expect(easy.multipart?).to be_falsey
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'when #multipart=nil' do
|
86
|
-
it 'returns false' do
|
87
|
-
easy.multipart = nil
|
88
|
-
expect(easy.multipart?).to be_falsey
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
context 'when #multipart=true' do
|
93
|
-
it 'returns true' do
|
94
|
-
easy.multipart = true
|
95
|
-
expect(easy.multipart?).to be_truthy
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
context 'when #multipart=false' do
|
100
|
-
it 'returns false' do
|
101
|
-
easy.multipart = false
|
102
|
-
expect(easy.multipart?).to be_falsey
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe "#httppost=" do
|
108
|
-
it "raises unless given a FFI::Pointer" do
|
109
|
-
expect{ easy.httppost = 1 }.to raise_error(Ethon::Errors::InvalidValue)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context "when requesting" do
|
114
|
-
let(:url) { "localhost:3001" }
|
115
|
-
let(:timeout) { nil }
|
116
|
-
let(:timeout_ms) { nil }
|
117
|
-
let(:connecttimeout) { nil }
|
118
|
-
let(:connecttimeout_ms) { nil }
|
119
|
-
let(:userpwd) { nil }
|
120
|
-
|
121
|
-
before do
|
122
|
-
easy.url = url
|
123
|
-
easy.timeout = timeout
|
124
|
-
easy.timeout_ms = timeout_ms
|
125
|
-
easy.connecttimeout = connecttimeout
|
126
|
-
easy.connecttimeout_ms = connecttimeout_ms
|
127
|
-
easy.userpwd = userpwd
|
128
|
-
easy.perform
|
129
|
-
end
|
130
|
-
|
131
|
-
context "when userpwd" do
|
132
|
-
context "when contains /" do
|
133
|
-
let(:url) { "localhost:3001/auth_basic/test/te%2Fst" }
|
134
|
-
let(:userpwd) { "test:te/st" }
|
135
|
-
|
136
|
-
it "works" do
|
137
|
-
expect(easy.response_code).to eq(200)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
context "when timeout" do
|
143
|
-
let(:timeout) { 1 }
|
144
|
-
|
145
|
-
context "when request takes longer" do
|
146
|
-
let(:url) { "localhost:3001?delay=2" }
|
147
|
-
|
148
|
-
it "times out" do
|
149
|
-
expect(easy.return_code).to eq(:operation_timedout)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
context "when connecttimeout" do
|
155
|
-
let(:connecttimeout) { 1 }
|
156
|
-
|
157
|
-
context "when cannot connect" do
|
158
|
-
let(:url) { "localhost:3002" }
|
159
|
-
|
160
|
-
it "times out" do
|
161
|
-
expect(easy.return_code).to eq(:couldnt_connect)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
if Ethon::Easy.supports_timeout_ms?
|
167
|
-
context "when timeout_ms" do
|
168
|
-
let(:timeout_ms) { 100 }
|
169
|
-
|
170
|
-
context "when request takes longer" do
|
171
|
-
let(:url) { "localhost:3001?delay=1" }
|
172
|
-
|
173
|
-
it "times out" do
|
174
|
-
expect(easy.return_code).to eq(:operation_timedout)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
context "when connecttimeout_ms" do
|
180
|
-
let(:connecttimeout_ms) { 100 }
|
181
|
-
|
182
|
-
context "when cannot connect" do
|
183
|
-
let(:url) { "localhost:3002" }
|
184
|
-
|
185
|
-
it "times out" do
|
186
|
-
# this can either lead to a timeout or couldnt connect depending on which happens first
|
187
|
-
expect([:couldnt_connect, :operation_timedout]).to include(easy.return_code)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|