curb 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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