curb 0.9.3 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,26 +22,15 @@ end
22
22
  Any insight you care to share would be helpful. Thanks.
23
23
  =end
24
24
  require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
25
- require 'webrick'
26
- class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
27
- class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
28
25
 
29
26
  class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
30
- def test_bug_workaround
31
- server = WEBrick::HTTPServer.new( :Port => 9999 )
32
- server.mount_proc("/test") do|req,res|
33
- assert_equal '15', req['Content-Length']
34
- res.body = "hi"
35
- res['Content-Type'] = "text/html"
36
- end
27
+ include BugTestServerSetupTeardown
37
28
 
38
- thread = Thread.new(server) do|srv|
39
- srv.start
40
- end
29
+ def test_bug_workaround
41
30
  params = {:cat => "hat", :foo => "bar"}
42
31
 
43
32
  post_body = params.map{|f,k| "#{Curl::Easy.new.escape(f)}=#{Curl::Easy.new.escape(k)}"}.join('&')
44
- c = Curl::Easy.http_post("http://127.0.0.1:9999/test",post_body) do |curl|
33
+ c = Curl::Easy.http_post("http://127.0.0.1:#{@port}/test",post_body) do |curl|
45
34
  curl.headers["User-Agent"] = "Curl/Ruby"
46
35
  curl.headers["X-Tender-Auth"] = "A Token"
47
36
  curl.headers["Accept"] = "application/vnd.tender-v1+json"
@@ -50,23 +39,12 @@ class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
50
39
  curl.enable_cookies = true
51
40
  end
52
41
 
53
- server.shutdown
54
- thread.join
55
42
  end
56
- def test_bug
57
- server = WEBrick::HTTPServer.new( :Port => 9999 )
58
- server.mount_proc("/test") do|req,res|
59
- assert_equal '15', req['Content-Length']
60
- res.body = "hi"
61
- res['Content-Type'] = "text/html"
62
- end
63
43
 
64
- thread = Thread.new(server) do|srv|
65
- srv.start
66
- end
44
+ def test_bug
67
45
  params = {:cat => "hat", :foo => "bar"}
68
46
 
69
- c = Curl::Easy.http_post("http://127.0.0.1:9999/test") do |curl|
47
+ c = Curl::Easy.http_post("http://127.0.0.1:#{@port}/test") do |curl|
70
48
  curl.headers["User-Agent"] = "Curl/Ruby"
71
49
  curl.headers["X-Tender-Auth"] = "A Token"
72
50
  curl.headers["Accept"] = "application/vnd.tender-v1+json"
@@ -76,8 +54,6 @@ class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
76
54
  curl.follow_location = true
77
55
  curl.enable_cookies = true
78
56
  end
79
-
80
- server.shutdown
81
- thread.join
82
57
  end
58
+
83
59
  end
@@ -0,0 +1,83 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ class BugFollowRedirect288 < Test::Unit::TestCase
4
+ include BugTestServerSetupTeardown
5
+
6
+ def setup
7
+ @port = 9999
8
+ super
9
+ @server.mount_proc("/redirect_to_test") do|req,res|
10
+ res.set_redirect(WEBrick::HTTPStatus::TemporaryRedirect, "/test")
11
+ end
12
+ end
13
+
14
+ def test_follow_redirect_with_no_redirect
15
+
16
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
17
+ did_call_redirect = false
18
+ c.on_redirect do|x|
19
+ did_call_redirect = true
20
+ end
21
+ c.perform
22
+
23
+ assert !did_call_redirect, "should reach this point redirect should not have been called"
24
+
25
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
26
+ did_call_redirect = false
27
+ c.on_redirect do|x|
28
+ did_call_redirect = true
29
+ end
30
+ c.follow_location = true
31
+ c.perform
32
+
33
+ assert_equal 0, c.redirect_count
34
+ assert !did_call_redirect, "should reach this point redirect should not have been called"
35
+
36
+ c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
37
+ did_call_redirect = false
38
+ c.on_redirect do|x|
39
+ did_call_redirect = true
40
+ end
41
+ c.perform
42
+ assert_equal 307, c.response_code
43
+
44
+ assert did_call_redirect, "we should have called on_redirect"
45
+
46
+ c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
47
+ did_call_redirect = false
48
+ c.follow_location = true
49
+ # NOTE: while this API is not supported by libcurl e.g. there is no redirect function callback in libcurl we could
50
+ # add support in ruby for this by executing this callback if redirect_count is greater than 0 at the end of a request in curb_multi.c
51
+ c.on_redirect do|x|
52
+ did_call_redirect = true
53
+ end
54
+ c.perform
55
+ assert_equal 1, c.redirect_count
56
+ assert_equal 200, c.response_code
57
+
58
+ assert did_call_redirect, "we should have called on_redirect"
59
+
60
+ c.url = 'http://127.0.0.1:9999/test'
61
+ c.perform
62
+ assert_equal 0, c.redirect_count
63
+ assert_equal 200, c.response_code
64
+
65
+ puts "checking for raise support"
66
+ did_raise = false
67
+ begin
68
+ c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
69
+ did_call_redirect = false
70
+ c.on_redirect do|x|
71
+ raise "raise"
72
+ did_call_redirect = true
73
+ end
74
+ c.perform
75
+ rescue => e
76
+ did_raise = true
77
+ end
78
+ assert_equal 307, c.response_code
79
+ assert did_raise
80
+
81
+ end
82
+
83
+ end
@@ -35,15 +35,13 @@ class BugTestInstancePostDiffersFromClassPost < Test::Unit::TestCase
35
35
  end
36
36
 
37
37
  def do_test
38
- c = Curl::Easy.http_post('https://www.google.com/accounts/ServiceLoginAuth',
39
- Curl::PostField.content('ltmpl','m_blanco'))
38
+ c = Curl::Easy.http_post('https://www.google.com/accounts/ServiceLoginAuth', Curl::PostField.content('ltmpl','m_blanco'))
40
39
  body_c, header_c = c.body_str, c.header_str
41
40
 
42
41
  sleep 2
43
42
 
44
- c.http_post('https://www.google.com/accounts/ServiceLoginAuth',
45
- Curl::PostField.content('ltmpl','m_blanco'))
46
- body_i, header_i = c.body_str, c.header_str
43
+ c.http_post('https://www.google.com/accounts/ServiceLoginAuth', Curl::PostField.content('ltmpl','m_blanco'))
44
+ body_i, header_i = c.body, c.head
47
45
 
48
46
  # timestamps will differ, just check first bit. We wont get here if
49
47
  # the bug bites anyway...
@@ -0,0 +1,32 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+
4
+ require 'curb'
5
+
6
+ class BugIssue102 < Test::Unit::TestCase
7
+
8
+ def test_gc_closewait
9
+ 100.times do
10
+ responses = {}
11
+ requests = ["http://www.google.co.uk/", "http://www.ruby-lang.org/"]
12
+ m = Curl::Multi.new
13
+ # add a few easy handles
14
+ requests.each do |url|
15
+ responses[url] = ""
16
+ c = Curl::Easy.new(url) do|curl|
17
+ curl.follow_location = true
18
+ curl.on_body{|data| responses[url] << data; data.size }
19
+ curl.on_success {|easy| #puts "success, add more easy handles"
20
+ }
21
+ end
22
+ m.add(c)
23
+ end
24
+
25
+ m.perform do
26
+ #puts "idling... can do some work here"
27
+ end
28
+ GC.start
29
+ end
30
+ end
31
+
32
+ end
@@ -3,6 +3,7 @@
3
3
  # irb: multi = Curl::Multi.new
4
4
  # irb: exit
5
5
  # <main>:47140: [BUG] Bus Error
6
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
6
7
  $:.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','ext'))
7
8
  $:.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','lib'))
8
9
  require 'curb'
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ class BugRaiseOnCallback < Test::Unit::TestCase
4
+ include BugTestServerSetupTeardown
5
+
6
+ def setup
7
+ @port = 9999
8
+ super
9
+ end
10
+
11
+ def test_on_complte
12
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
13
+ did_raise = false
14
+ begin
15
+ c.on_complete do|x|
16
+ assert_equal 'http://127.0.0.1:9999/test', x.url
17
+ raise "error complete" # this will get swallowed
18
+ end
19
+ c.perform
20
+ rescue => e
21
+ did_raise = true
22
+ end
23
+ assert did_raise, "we want to raise an exception if the ruby callbacks raise"
24
+
25
+ end
26
+
27
+ end
28
+
29
+ #test_on_debug
data/tests/helper.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  # Copyright (c)2006 Ross Bamford. See LICENSE.
3
3
  $CURB_TESTING = true
4
4
  require 'uri'
5
+ require 'stringio'
5
6
 
6
7
  $TOPDIR = File.expand_path(File.join(File.dirname(__FILE__), '..'))
7
8
  $EXTDIR = File.join($TOPDIR, 'ext')
@@ -18,7 +19,7 @@ rescue LoadError
18
19
  end
19
20
  require 'fileutils'
20
21
 
21
- $TEST_URL = "file://#{URI.escape(File.expand_path(__FILE__).tr('\\','/').tr(':','|'))}"
22
+ $TEST_URL = "file://#{'/' if RUBY_DESCRIPTION =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/}#{File.expand_path(__FILE__).tr('\\','/')}"
22
23
 
23
24
  require 'thread'
24
25
  require 'webrick'
@@ -30,19 +31,22 @@ require 'webrick'
30
31
  TEST_SINGLE_THREADED=false
31
32
 
32
33
  # keep webrick quiet
33
- class ::WEBrick::HTTPServer
34
+ ::WEBrick::HTTPServer.send(:remove_method,:access_log) if ::WEBrick::HTTPServer.instance_methods.include?(:access_log)
35
+ ::WEBrick::BasicLog.send(:remove_method,:log) if ::WEBrick::BasicLog.instance_methods.include?(:log)
36
+
37
+ ::WEBrick::HTTPServer.class_eval do
34
38
  def access_log(config, req, res)
35
39
  # nop
36
40
  end
37
41
  end
38
- class ::WEBrick::BasicLog
42
+ ::WEBrick::BasicLog.class_eval do
39
43
  def log(level, data)
40
44
  # nop
41
45
  end
42
46
  end
43
47
 
44
48
  #
45
- # Simple test server to record number of times a request is sent/recieved of a specific
49
+ # Simple test server to record number of times a request is sent/recieved of a specific
46
50
  # request type, e.g. GET,POST,PUT,DELETE
47
51
  #
48
52
  class TestServlet < WEBrick::HTTPServlet::AbstractServlet
@@ -52,13 +56,12 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
52
56
  end
53
57
 
54
58
  def self.port
55
- (@port or 9129)
59
+ @port ||= 9129
56
60
  end
57
61
 
58
62
  def self.path
59
63
  '/methods'
60
64
  end
61
-
62
65
  def self.url
63
66
  "http://127.0.0.1:#{port}#{path}"
64
67
  end
@@ -70,12 +73,12 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
70
73
  end
71
74
 
72
75
  def do_GET(req,res)
73
- if req.path.match /redirect$/
76
+ if req.path.match(/redirect$/)
74
77
  res.status = 302
75
78
  res['Location'] = '/foo'
76
- elsif req.path.match /not_here$/
79
+ elsif req.path.match(/not_here$/)
77
80
  res.status = 404
78
- elsif req.path.match /error$/
81
+ elsif req.path.match(/error$/)
79
82
  res.status = 500
80
83
  end
81
84
  respond_with("GET#{req.query_string}",req,res)
@@ -94,6 +97,9 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
94
97
  end
95
98
  if params and params['s'] == '500'
96
99
  res.status = 500
100
+ elsif params and params['c']
101
+ cookie = URI.decode_www_form_component(params['c']).split('=')
102
+ res.cookies << WEBrick::Cookie.new(*cookie)
97
103
  else
98
104
  respond_with("POST\n#{req.body}",req,res)
99
105
  end
@@ -129,6 +135,32 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
129
135
 
130
136
  end
131
137
 
138
+ module BugTestServerSetupTeardown
139
+ def setup
140
+ @port ||= 9992
141
+ @server = WEBrick::HTTPServer.new( :Port => @port )
142
+ @server.mount_proc("/test") do|req,res|
143
+ if @response_proc
144
+ @response_proc.call(res)
145
+ else
146
+ res.body = "hi"
147
+ res['Content-Type'] = "text/html"
148
+ end
149
+ end
150
+
151
+ @thread = Thread.new(@server) do|srv|
152
+ srv.start
153
+ end
154
+ end
155
+
156
+ def teardown
157
+ while @server.status != :Shutdown
158
+ @server.shutdown
159
+ end
160
+ @thread.join
161
+ end
162
+ end
163
+
132
164
  module TestServerMethods
133
165
  def locked_file
134
166
  File.join(File.dirname(__FILE__),"server_lock-#{@__port}")
@@ -136,8 +168,7 @@ module TestServerMethods
136
168
 
137
169
  def server_setup(port=9129,servlet=TestServlet)
138
170
  @__port = port
139
- if @server.nil? and !File.exist?(locked_file)
140
-
171
+ if (@server ||= nil).nil? and !File.exist?(locked_file)
141
172
  File.open(locked_file,'w') {|f| f << 'locked' }
142
173
  if TEST_SINGLE_THREADED
143
174
  rd, wr = IO.pipe
@@ -145,7 +176,7 @@ module TestServerMethods
145
176
  rd.close
146
177
  rd = nil
147
178
 
148
- # start up a webrick server for testing delete
179
+ # start up a webrick server for testing delete
149
180
  server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => File.expand_path(File.dirname(__FILE__))
150
181
 
151
182
  server.mount(servlet.path, servlet)
@@ -161,7 +192,7 @@ module TestServerMethods
161
192
  rd.read
162
193
  rd.close
163
194
  else
164
- # start up a webrick server for testing delete
195
+ # start up a webrick server for testing delete
165
196
  @server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => File.expand_path(File.dirname(__FILE__))
166
197
 
167
198
  @server.mount(servlet.path, servlet)
@@ -202,3 +233,81 @@ module TestServerMethods
202
233
  rescue Errno::EADDRINUSE
203
234
  end
204
235
  end
236
+
237
+
238
+
239
+ # Backport for Ruby 1.8
240
+ module Backports
241
+ module Ruby18
242
+ module URIFormEncoding
243
+ TBLENCWWWCOMP_ = {}
244
+ TBLDECWWWCOMP_ = {}
245
+
246
+ def encode_www_form_component(str)
247
+ if TBLENCWWWCOMP_.empty?
248
+ 256.times do |i|
249
+ TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
250
+ end
251
+ TBLENCWWWCOMP_[' '] = '+'
252
+ TBLENCWWWCOMP_.freeze
253
+ end
254
+ str.to_s.gsub( /([^*\-.0-9A-Z_a-z])/ ) {|*| TBLENCWWWCOMP_[$1] }
255
+ end
256
+
257
+ def decode_www_form_component(str)
258
+ if TBLDECWWWCOMP_.empty?
259
+ 256.times do |i|
260
+ h, l = i>>4, i&15
261
+ TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
262
+ TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
263
+ TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
264
+ TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
265
+ end
266
+ TBLDECWWWCOMP_['+'] = ' '
267
+ TBLDECWWWCOMP_.freeze
268
+ end
269
+
270
+ raise ArgumentError, "invalid %-encoding (#{str.dump})" unless /\A(?:%[[:xdigit:]]{2}|[^%]+)*\z/ =~ str
271
+ str.gsub( /(\+|%[[:xdigit:]]{2})/ ) {|*| TBLDECWWWCOMP_[$1] }
272
+ end
273
+
274
+ def encode_www_form( enum )
275
+ enum.map do |k,v|
276
+ if v.nil?
277
+ encode_www_form_component(k)
278
+ elsif v.respond_to?(:to_ary)
279
+ v.to_ary.map do |w|
280
+ str = encode_www_form_component(k)
281
+ unless w.nil?
282
+ str << '='
283
+ str << encode_www_form_component(w)
284
+ end
285
+ end.join('&')
286
+ else
287
+ str = encode_www_form_component(k)
288
+ str << '='
289
+ str << encode_www_form_component(v)
290
+ end
291
+ end.join('&')
292
+ end
293
+
294
+ WFKV_ = '(?:%\h\h|[^%#=;&])'
295
+ def decode_www_form(str, _)
296
+ return [] if str.to_s == ''
297
+
298
+ unless /\A#{WFKV_}=#{WFKV_}(?:[;&]#{WFKV_}=#{WFKV_})*\z/ =~ str
299
+ raise ArgumentError, "invalid data of application/x-www-form-urlencoded (#{str})"
300
+ end
301
+ ary = []
302
+ $&.scan(/([^=;&]+)=([^;&]*)/) do
303
+ ary << [decode_www_form_component($1, enc), decode_www_form_component($2, enc)]
304
+ end
305
+ ary
306
+ end
307
+ end
308
+ end
309
+ end
310
+
311
+ unless URI.methods.include?(:encode_www_form)
312
+ URI.extend(Backports::Ruby18::URIFormEncoding)
313
+ end
data/tests/tc_curl.rb CHANGED
@@ -31,7 +31,37 @@ class TestCurl < Test::Unit::TestCase
31
31
  assert_equal "OPTIONSfoo=bar", curl.body_str
32
32
  end
33
33
 
34
- include TestServerMethods
34
+ def test_urlalize_without_extra_params
35
+ url_no_params = 'http://localhost/test'
36
+ url_with_params = 'http://localhost/test?a=1'
37
+
38
+ assert_equal(url_no_params, Curl.urlalize(url_no_params))
39
+ assert_equal(url_with_params, Curl.urlalize(url_with_params))
40
+ end
41
+
42
+ def test_urlalize_with_nil_as_params
43
+ url = 'http://localhost/test'
44
+ assert_equal(url, Curl.urlalize(url, nil))
45
+ end
46
+
47
+ def test_urlalize_with_extra_params
48
+ url_no_params = 'http://localhost/test'
49
+ url_with_params = 'http://localhost/test?a=1'
50
+ extra_params = { :b => 2 }
51
+
52
+ expected_url_no_params = 'http://localhost/test?b=2'
53
+ expected_url_with_params = 'http://localhost/test?a=1&b=2'
54
+
55
+ assert_equal(expected_url_no_params, Curl.urlalize(url_no_params, extra_params))
56
+ assert_equal(expected_url_with_params, Curl.urlalize(url_with_params, extra_params))
57
+ end
58
+
59
+ def test_urlalize_does_not_strip_trailing_?
60
+ url_empty_params = 'http://localhost/test?'
61
+ assert_equal(url_empty_params, Curl.urlalize(url_empty_params))
62
+ end
63
+
64
+ include TestServerMethods
35
65
 
36
66
  def setup
37
67
  server_setup
@@ -11,7 +11,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
11
11
  dl_url = "http://127.0.0.1:9129/ext/curb_easy.c"
12
12
  dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
13
13
 
14
- curb = Curl::Easy.download(dl_url, dl_path)
14
+ Curl::Easy.download(dl_url, dl_path)
15
15
  assert File.exist?(dl_path)
16
16
  assert_equal File.read(File.join(File.dirname(__FILE__), '..','ext','curb_easy.c')), File.read(dl_path)
17
17
  ensure
@@ -23,7 +23,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
23
23
  dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
24
24
  io = File.open(dl_path, 'wb')
25
25
 
26
- curb = Curl::Easy.download(dl_url, io)
26
+ Curl::Easy.download(dl_url, io)
27
27
  assert io.closed?
28
28
  assert File.exist?(dl_path)
29
29
  assert_equal File.read(File.join(File.dirname(__FILE__), '..','ext','curb_easy.c')), File.read(dl_path)
@@ -49,7 +49,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
49
49
  # Download remote source
50
50
  begin
51
51
  reader.close
52
- curb = Curl::Easy.download(dl_url, writer)
52
+ Curl::Easy.download(dl_url, writer)
53
53
  Process.wait
54
54
  ensure
55
55
  writer.close rescue IOError # if the stream has already been closed, which occurs in Easy::download