curb 0.9.7 → 0.9.8

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.
@@ -14,7 +14,6 @@
14
14
  typedef struct {
15
15
  int active;
16
16
  int running;
17
- VALUE requests; /* hash of handles currently added */
18
17
  CURLM *handle;
19
18
  } ruby_curl_multi;
20
19
 
@@ -84,6 +84,7 @@ have_constant "curlproxy_http"
84
84
  have_constant "curlproxy_socks4"
85
85
  have_constant "curlproxy_socks4a"
86
86
  have_constant "curlproxy_socks5"
87
+ have_constant "curlproxy_socks5_hostname"
87
88
  have_constant "curlauth_basic"
88
89
  have_constant "curlauth_digest"
89
90
  have_constant "curlauth_gssnegotiate"
@@ -216,6 +217,7 @@ have_constant "curlopt_httppost"
216
217
  have_constant "curlopt_referer"
217
218
  have_constant "curlopt_useragent"
218
219
  have_constant "curlopt_httpheader"
220
+ have_constant "curlopt_proxyheader"
219
221
  have_constant "curlopt_http200aliases"
220
222
  have_constant "curlopt_cookie"
221
223
  have_constant "curlopt_cookiefile"
@@ -70,7 +70,7 @@ module Curl
70
70
 
71
71
  if self.last_result != 0 && self.on_failure.nil?
72
72
  error = Curl::Easy.error(self.last_result)
73
- raise error.first.new(error.last)
73
+ raise error.first.new(self.head)
74
74
  end
75
75
 
76
76
  ret
@@ -1,5 +1,4 @@
1
1
  module Curl
2
-
3
2
  class Multi
4
3
  class << self
5
4
  # call-seq:
@@ -168,6 +167,7 @@ module Curl
168
167
  end
169
168
  free_handles = nil
170
169
  end
170
+
171
171
  end
172
172
 
173
173
  # call-seq:
@@ -242,7 +242,45 @@ module Curl
242
242
  }
243
243
  raise errors unless errors.empty?
244
244
  end
245
+ end
246
+
247
+ def cancel!
248
+ requests.each do |_,easy|
249
+ remove(easy)
250
+ end
251
+ end
252
+
253
+ def idle?
254
+ requests.empty?
255
+ end
245
256
 
257
+ def requests
258
+ @requests ||= {}
246
259
  end
260
+
261
+ def add(easy)
262
+ return self if requests[easy.object_id]
263
+ requests[easy.object_id] = easy
264
+ _add(easy)
265
+ self
266
+ end
267
+
268
+ def remove(easy)
269
+ return self if !requests[easy.object_id]
270
+ requests.delete(easy.object_id)
271
+ _remove(easy)
272
+ self
273
+ end
274
+
275
+ def close
276
+ requests.values.each {|easy|
277
+ _remove(easy)
278
+ }
279
+ @requests = {}
280
+ _close
281
+ self
282
+ end
283
+
284
+
247
285
  end
248
286
  end
@@ -207,3 +207,81 @@ module TestServerMethods
207
207
  rescue Errno::EADDRINUSE
208
208
  end
209
209
  end
210
+
211
+
212
+
213
+ # Backport for Ruby 1.8
214
+ module Backports
215
+ module Ruby18
216
+ module URIFormEncoding
217
+ TBLENCWWWCOMP_ = {}
218
+ TBLDECWWWCOMP_ = {}
219
+
220
+ def encode_www_form_component(str)
221
+ if TBLENCWWWCOMP_.empty?
222
+ 256.times do |i|
223
+ TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
224
+ end
225
+ TBLENCWWWCOMP_[' '] = '+'
226
+ TBLENCWWWCOMP_.freeze
227
+ end
228
+ str.to_s.gsub( /([^*\-.0-9A-Z_a-z])/ ) {|*| TBLENCWWWCOMP_[$1] }
229
+ end
230
+
231
+ def decode_www_form_component(str)
232
+ if TBLDECWWWCOMP_.empty?
233
+ 256.times do |i|
234
+ h, l = i>>4, i&15
235
+ TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
236
+ TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
237
+ TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
238
+ TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
239
+ end
240
+ TBLDECWWWCOMP_['+'] = ' '
241
+ TBLDECWWWCOMP_.freeze
242
+ end
243
+
244
+ raise ArgumentError, "invalid %-encoding (#{str.dump})" unless /\A(?:%[[:xdigit:]]{2}|[^%]+)*\z/ =~ str
245
+ str.gsub( /(\+|%[[:xdigit:]]{2})/ ) {|*| TBLDECWWWCOMP_[$1] }
246
+ end
247
+
248
+ def encode_www_form( enum )
249
+ enum.map do |k,v|
250
+ if v.nil?
251
+ encode_www_form_component(k)
252
+ elsif v.respond_to?(:to_ary)
253
+ v.to_ary.map do |w|
254
+ str = encode_www_form_component(k)
255
+ unless w.nil?
256
+ str << '='
257
+ str << encode_www_form_component(w)
258
+ end
259
+ end.join('&')
260
+ else
261
+ str = encode_www_form_component(k)
262
+ str << '='
263
+ str << encode_www_form_component(v)
264
+ end
265
+ end.join('&')
266
+ end
267
+
268
+ WFKV_ = '(?:%\h\h|[^%#=;&])'
269
+ def decode_www_form(str, _)
270
+ return [] if str.to_s == ''
271
+
272
+ unless /\A#{WFKV_}=#{WFKV_}(?:[;&]#{WFKV_}=#{WFKV_})*\z/ =~ str
273
+ raise ArgumentError, "invalid data of application/x-www-form-urlencoded (#{str})"
274
+ end
275
+ ary = []
276
+ $&.scan(/([^=;&]+)=([^;&]*)/) do
277
+ ary << [decode_www_form_component($1, enc), decode_www_form_component($2, enc)]
278
+ end
279
+ ary
280
+ end
281
+ end
282
+ end
283
+ end
284
+
285
+ unless URI.methods.include?(:encode_www_form)
286
+ URI.extend(Backports::Ruby18::URIFormEncoding)
287
+ end
@@ -28,8 +28,6 @@ class TestCurbCurlEasy < Test::Unit::TestCase
28
28
  c = Curl.get($TEST_URL)
29
29
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
30
30
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body)
31
- assert_equal "", c.header_str
32
- assert_equal "", c.head
33
31
  end
34
32
  end
35
33
  end
@@ -41,7 +39,6 @@ class TestCurbCurlEasy < Test::Unit::TestCase
41
39
  assert_instance_of Curl::Easy, c = Curl::Easy.perform($TEST_URL)
42
40
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
43
41
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body)
44
- assert_equal "", c.header_str
45
42
  end
46
43
 
47
44
  def test_class_perform_02
@@ -49,7 +46,6 @@ class TestCurbCurlEasy < Test::Unit::TestCase
49
46
  assert_instance_of Curl::Easy, c = Curl::Easy.perform($TEST_URL) { |curl| curl.on_body { |d| data << d; d.length } }
50
47
 
51
48
  assert_nil c.body_str
52
- assert_equal "", c.header_str
53
49
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, data)
54
50
  end
55
51
 
@@ -144,7 +140,6 @@ class TestCurbCurlEasy < Test::Unit::TestCase
144
140
  c = Curl::Easy.new($TEST_URL)
145
141
  assert_equal true, c.http_get
146
142
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
147
- assert_equal "", c.header_str
148
143
  end
149
144
 
150
145
  def test_get_02
@@ -156,7 +151,6 @@ class TestCurbCurlEasy < Test::Unit::TestCase
156
151
  assert_equal true, c.http_get
157
152
 
158
153
  assert_nil c.body_str
159
- assert_equal "", c.header_str
160
154
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, data)
161
155
  end
162
156
 
@@ -339,29 +333,69 @@ class TestCurbCurlEasy < Test::Unit::TestCase
339
333
  c.max_redirects = nil
340
334
  assert_nil c.max_redirects
341
335
  end
342
-
336
+
337
+ def test_timeout_with_floats
338
+ c = Curl::Easy.new($TEST_URL)
339
+
340
+ c.timeout = 1.5
341
+ assert_equal 1500, c.timeout_ms
342
+ assert_equal 1.5, c.timeout
343
+ end
344
+
345
+ def test_timeout_with_negative
346
+ c = Curl::Easy.new($TEST_URL)
347
+
348
+ c.timeout = -1.5
349
+ assert_equal 0, c.timeout
350
+ assert_equal 0, c.timeout_ms
351
+
352
+ c.timeout = -4.8
353
+ assert_equal 0, c.timeout
354
+ assert_equal 0, c.timeout_ms
355
+ end
356
+
343
357
  def test_timeout_01
344
358
  c = Curl::Easy.new($TEST_URL)
345
-
346
- assert_nil c.timeout
347
-
359
+
360
+ assert_equal 0, c.timeout
361
+
348
362
  c.timeout = 3
349
363
  assert_equal 3, c.timeout
350
-
351
- c.timeout = nil
352
- assert_nil c.timeout
364
+
365
+ c.timeout = 0
366
+ assert_equal 0, c.timeout
353
367
  end
354
368
 
355
369
  def test_timeout_ms_01
356
370
  c = Curl::Easy.new($TEST_URL)
357
371
 
358
- assert_nil c.timeout_ms
372
+ assert_equal 0, c.timeout_ms
359
373
 
360
374
  c.timeout_ms = 100
361
375
  assert_equal 100, c.timeout_ms
362
376
 
363
377
  c.timeout_ms = nil
364
- assert_nil c.timeout_ms
378
+ assert_equal 0, c.timeout_ms
379
+ end
380
+
381
+ def test_timeout_ms_with_floats
382
+ c = Curl::Easy.new($TEST_URL)
383
+
384
+ c.timeout_ms = 55.5
385
+ assert_equal 55, c.timeout_ms
386
+ assert_equal 0.055, c.timeout
387
+ end
388
+
389
+ def test_timeout_ms_with_negative
390
+ c = Curl::Easy.new($TEST_URL)
391
+
392
+ c.timeout_ms = -1.5
393
+ assert_equal 0, c.timeout
394
+ assert_equal 0, c.timeout_ms
395
+
396
+ c.timeout_ms = -4.8
397
+ assert_equal 0, c.timeout
398
+ assert_equal 0, c.timeout_ms
365
399
  end
366
400
 
367
401
  def test_connect_timeout_01
@@ -608,7 +642,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
608
642
  def test_cookielist
609
643
  c = Curl::Easy.new TestServlet.url
610
644
  c.enable_cookies = true
611
- c.post_body = URI.encode_www_form c: 'somename=somevalue'
645
+ c.post_body = URI.encode_www_form('c' => 'somename=somevalue')
612
646
  assert_nil c.cookielist
613
647
  c.perform
614
648
  assert_match(/somevalue/, c.cookielist.join(''))
@@ -6,6 +6,69 @@ class TestCurbCurlMulti < Test::Unit::TestCase
6
6
  ObjectSpace.garbage_collect
7
7
  end
8
8
 
9
+ # for https://github.com/taf2/curb/issues/277
10
+ # must connect to an external
11
+ def test_connection_keepalive
12
+ # 0123456 default & reserved RubyVM. It will probably include 7 from Dir.glob
13
+ open_fds = lambda do
14
+ `/usr/sbin/lsof -p #{Process.pid} | egrep "TCP|UDP" | wc -l`.strip.to_i
15
+ end
16
+ before_open = open_fds.call
17
+ assert !Curl::Multi.autoclose
18
+ multi = Curl::Multi.new
19
+ multi.max_connects = 1 # limit to 1 connection within the multi handle
20
+
21
+ did_complete = false
22
+ 5.times do |n|
23
+ # NOTE: we use google here because connecting to our TEST_URL as a local host address appears to not register correctly with lsof as a socket... if anyone knows a better way would be great to not have an external dependency here in the test
24
+ easy = Curl::Easy.new("http://google.com/") do |curl|
25
+ curl.timeout = 5 # ensure we don't hang for ever connecting to an external host
26
+ curl.on_complete {
27
+ did_complete = true
28
+ }
29
+ end
30
+ multi.add(easy)
31
+ end
32
+
33
+ multi.perform
34
+ assert did_complete
35
+ after_open = open_fds.call
36
+ assert_equal (after_open - before_open), 1, "with max connections set to 1 at this point the connection to google should still be open"
37
+ multi.close
38
+
39
+ after_open = open_fds.call
40
+ assert_equal (after_open - before_open), 0, "after closing the multi handle all connections should be closed"
41
+
42
+ Curl::Multi.autoclose = true
43
+ multi = Curl::Multi.new
44
+ did_complete = false
45
+ 5.times do |n|
46
+ # NOTE: we use google here because connecting to our TEST_URL as a local host address appears to not register correctly with lsof as a socket... if anyone knows a better way would be great to not have an external dependency here in the test
47
+ easy = Curl::Easy.new("http://google.com/") do |curl|
48
+ curl.timeout = 5 # ensure we don't hang for ever connecting to an external host
49
+ curl.on_complete {
50
+ did_complete = true
51
+ }
52
+ end
53
+ multi.add(easy)
54
+ end
55
+
56
+ multi.perform
57
+ assert did_complete
58
+ after_open = open_fds.call
59
+ assert_equal (after_open - before_open), 0, "auto close the connections"
60
+ ensure
61
+ Curl::Multi.autoclose = false # restore default
62
+ end
63
+
64
+ def test_connection_autoclose
65
+ assert !Curl::Multi.autoclose
66
+ Curl::Multi.autoclose = true
67
+ assert Curl::Multi.autoclose
68
+ ensure
69
+ Curl::Multi.autoclose = false # restore default
70
+ end
71
+
9
72
  def test_new_multi_01
10
73
  d1 = ""
11
74
  c1 = Curl::Easy.new($TEST_URL) do |curl|
@@ -125,7 +188,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
125
188
  def test_requests
126
189
  m = Curl::Multi.new
127
190
 
128
- assert_equal([], m.requests, 'A new Curl::Multi handle should have no requests')
191
+ assert_equal(0, m.requests.length, 'A new Curl::Multi handle should have no requests')
129
192
 
130
193
  10.times do
131
194
  m.add(Curl::Easy.new($TEST_URL))
@@ -135,7 +198,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
135
198
 
136
199
  m.perform
137
200
 
138
- assert_equal([], m.requests, 'A new Curl::Multi handle should have no requests after a perform')
201
+ assert_equal(0, m.requests.length, 'A new Curl::Multi handle should have no requests after a perform')
139
202
  end
140
203
 
141
204
  def test_cancel
@@ -148,7 +211,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
148
211
 
149
212
  m.cancel!
150
213
 
151
- assert_equal([], m.requests, 'A new Curl::Multi handle should have no requests after being canceled')
214
+ assert_equal(0, m.requests.size, 'A new Curl::Multi handle should have no requests after being canceled')
152
215
  end
153
216
 
154
217
  def test_with_success
@@ -192,7 +255,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
192
255
  c1.on_success do|c|
193
256
  success_called1 = true
194
257
  #puts "success 1 called: #{c.body_str.inspect}"
195
- #assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
258
+ assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
196
259
  end
197
260
 
198
261
  c1.on_failure do|c,rc|
@@ -484,5 +547,4 @@ class TestCurbCurlMulti < Test::Unit::TestCase
484
547
  def setup
485
548
  server_setup
486
549
  end
487
-
488
550
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ross Bamford
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-11-26 00:00:00.000000000 Z
12
+ date: 2019-01-28 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Curb (probably CUrl-RuBy or something) provides Ruby-language bindings
15
15
  for the libcurl(3), a fully-featured client-side URL transfer library. cURL and
@@ -72,7 +72,7 @@ files:
72
72
  - tests/unittests.rb
73
73
  homepage: http://curb.rubyforge.org/
74
74
  licenses:
75
- - MIT
75
+ - Ruby
76
76
  metadata: {}
77
77
  post_install_message:
78
78
  rdoc_options:
@@ -93,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
93
  version: '0'
94
94
  requirements: []
95
95
  rubyforge_project: curb
96
- rubygems_version: 2.4.3
96
+ rubygems_version: 2.7.7
97
97
  signing_key:
98
98
  specification_version: 4
99
99
  summary: Ruby libcurl bindings