ghazel-curb 0.6.2.3 → 0.7.9.1
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.
- data/README +8 -1
- data/Rakefile +20 -1
- data/ext/curb.c +34 -0
- data/ext/curb.h +6 -4
- data/ext/curb_easy.c +627 -181
- data/ext/curb_easy.h +28 -2
- data/ext/curb_errors.c +2 -0
- data/ext/curb_errors.h +1 -0
- data/ext/curb_macros.h +1 -1
- data/ext/curb_multi.c +155 -59
- data/ext/curb_postfield.c +61 -49
- data/ext/curb_upload.c +2 -2
- data/ext/extconf.rb +7 -2
- data/lib/curb.rb +94 -5
- data/tests/bug_curb_easy_post_with_string_no_content_length_header.rb +83 -0
- data/tests/bug_multi_segfault.rb +6 -2
- data/tests/bug_postfields_crash.rb +26 -0
- data/tests/bug_postfields_crash2.rb +57 -0
- data/tests/bugtests.rb +9 -0
- data/tests/helper.rb +21 -7
- data/tests/mem_check.rb +65 -0
- data/tests/tc_curl_download.rb +44 -1
- data/tests/tc_curl_easy.rb +181 -11
- data/tests/tc_curl_multi.rb +36 -3
- data/tests/tc_curl_postfield.rb +3 -1
- data/tests/timeout.rb +100 -0
- data/tests/timeout_server.rb +33 -0
- metadata +44 -5
data/lib/curb.rb
CHANGED
@@ -26,16 +26,24 @@ module Curl
|
|
26
26
|
def download(url, filename = url.split(/\?/).first.split(/\//).last, &blk)
|
27
27
|
curl = Curl::Easy.new(url, &blk)
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
output = if filename.is_a? IO
|
30
|
+
filename.binmode if filename.respond_to?(:binmode)
|
31
|
+
filename
|
32
|
+
else
|
33
|
+
File.open(filename, 'wb')
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
old_on_body = curl.on_body do |data|
|
31
38
|
result = old_on_body ? old_on_body.call(data) : data.length
|
32
39
|
output << data if result == data.length
|
33
40
|
result
|
34
41
|
end
|
35
|
-
|
36
42
|
curl.perform
|
37
|
-
|
38
|
-
|
43
|
+
ensure
|
44
|
+
output.close rescue IOError
|
45
|
+
end
|
46
|
+
|
39
47
|
return curl
|
40
48
|
end
|
41
49
|
end
|
@@ -142,6 +150,7 @@ module Curl
|
|
142
150
|
m = Curl::Multi.new
|
143
151
|
# configure the multi handle
|
144
152
|
multi_options.each { |k,v| m.send("#{k}=", v) }
|
153
|
+
callbacks = [:on_progress,:on_debug,:on_failure,:on_success,:on_body,:on_header]
|
145
154
|
|
146
155
|
urls_with_config.each do|conf|
|
147
156
|
c = conf.dup # avoid being destructive to input
|
@@ -151,6 +160,12 @@ module Curl
|
|
151
160
|
|
152
161
|
easy = Curl::Easy.new(url)
|
153
162
|
|
163
|
+
# assign callbacks
|
164
|
+
callbacks.each do |cb|
|
165
|
+
cbproc = c.delete(cb)
|
166
|
+
easy.send(cb,&cbproc) if cbproc
|
167
|
+
end
|
168
|
+
|
154
169
|
case method
|
155
170
|
when :post
|
156
171
|
fields = c.delete(:post_fields)
|
@@ -181,6 +196,80 @@ module Curl
|
|
181
196
|
end
|
182
197
|
m.perform
|
183
198
|
end
|
199
|
+
|
200
|
+
# call-seq:
|
201
|
+
#
|
202
|
+
# Curl::Multi.download(['http://example.com/p/a/t/h/file1.txt','http://example.com/p/a/t/h/file2.txt']){|c|}
|
203
|
+
#
|
204
|
+
# will create 2 new files file1.txt and file2.txt
|
205
|
+
#
|
206
|
+
# 2 files will be opened, and remain open until the call completes
|
207
|
+
#
|
208
|
+
# when using the :post or :put method, urls should be a hash, including the individual post fields per post
|
209
|
+
#
|
210
|
+
def download(urls,easy_options={},multi_options={},download_paths=nil,&blk)
|
211
|
+
errors = []
|
212
|
+
procs = []
|
213
|
+
files = []
|
214
|
+
urls_with_config = []
|
215
|
+
url_to_download_paths = {}
|
216
|
+
|
217
|
+
urls.each_with_index do|urlcfg,i|
|
218
|
+
if urlcfg.is_a?(Hash)
|
219
|
+
url = url[:url]
|
220
|
+
else
|
221
|
+
url = urlcfg
|
222
|
+
end
|
223
|
+
|
224
|
+
if download_paths and download_paths[i]
|
225
|
+
download_path = download_paths[i]
|
226
|
+
else
|
227
|
+
download_path = File.basename(url)
|
228
|
+
end
|
229
|
+
|
230
|
+
file = lambda do|dp|
|
231
|
+
file = File.open(dp,"wb")
|
232
|
+
procs << (lambda {|data| file.write data; data.size })
|
233
|
+
files << file
|
234
|
+
file
|
235
|
+
end.call(download_path)
|
236
|
+
|
237
|
+
if urlcfg.is_a?(Hash)
|
238
|
+
urls_with_config << urlcfg.merge({:on_body => procs.last}.merge(easy_options))
|
239
|
+
else
|
240
|
+
urls_with_config << {:url => url, :on_body => procs.last, :method => :get}.merge(easy_options)
|
241
|
+
end
|
242
|
+
url_to_download_paths[url] = {:path => download_path, :file => file} # store for later
|
243
|
+
end
|
244
|
+
|
245
|
+
if blk
|
246
|
+
# when injecting the block, ensure file is closed before yielding
|
247
|
+
Curl::Multi.http(urls_with_config, multi_options) do |c,code,method|
|
248
|
+
info = url_to_download_paths[c.url]
|
249
|
+
begin
|
250
|
+
file = info[:file]
|
251
|
+
files.reject!{|f| f == file }
|
252
|
+
file.close
|
253
|
+
rescue => e
|
254
|
+
errors << e
|
255
|
+
end
|
256
|
+
blk.call(c,info[:path])
|
257
|
+
end
|
258
|
+
else
|
259
|
+
Curl::Multi.http(urls_with_config, multi_options)
|
260
|
+
end
|
261
|
+
|
262
|
+
ensure
|
263
|
+
files.each {|f|
|
264
|
+
begin
|
265
|
+
f.close
|
266
|
+
rescue => e
|
267
|
+
errors << e
|
268
|
+
end
|
269
|
+
}
|
270
|
+
raise errors unless errors.empty?
|
271
|
+
end
|
272
|
+
|
184
273
|
end
|
185
274
|
end
|
186
275
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
=begin
|
2
|
+
From jwhitmire
|
3
|
+
Todd, I'm trying to use curb to post data to a REST url. We're using it to post support questions from our iphone app directly to tender. The post looks good to me, but curl is not adding the content-length header so I get a 411 length required response from the server.
|
4
|
+
|
5
|
+
Here's my post block, do you see anything obvious? Do I need to manually add the Content-Length header?
|
6
|
+
|
7
|
+
c = Curl::Easy.http_post(url) do |curl|
|
8
|
+
curl.headers["User-Agent"] = "Curl/Ruby"
|
9
|
+
if user
|
10
|
+
curl.headers["X-Multipass"] = user.multipass
|
11
|
+
else
|
12
|
+
curl.headers["X-Tender-Auth"] = TOKEN
|
13
|
+
end
|
14
|
+
curl.headers["Accept"] = "application/vnd.tender-v1+json"
|
15
|
+
|
16
|
+
curl.post_body = params.map{|f,k| "#{curl.escape(f)}=#{curl.escape(k)}"}.join('&')
|
17
|
+
|
18
|
+
curl.verbose = true
|
19
|
+
curl.follow_location = true
|
20
|
+
curl.enable_cookies = true
|
21
|
+
end
|
22
|
+
Any insight you care to share would be helpful. Thanks.
|
23
|
+
=end
|
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
|
+
|
29
|
+
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
|
37
|
+
|
38
|
+
thread = Thread.new(server) do|srv|
|
39
|
+
srv.start
|
40
|
+
end
|
41
|
+
params = {:cat => "hat", :foo => "bar"}
|
42
|
+
|
43
|
+
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|
|
45
|
+
curl.headers["User-Agent"] = "Curl/Ruby"
|
46
|
+
curl.headers["X-Tender-Auth"] = "A Token"
|
47
|
+
curl.headers["Accept"] = "application/vnd.tender-v1+json"
|
48
|
+
|
49
|
+
curl.follow_location = true
|
50
|
+
curl.enable_cookies = true
|
51
|
+
end
|
52
|
+
|
53
|
+
server.shutdown
|
54
|
+
thread.join
|
55
|
+
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
|
+
|
64
|
+
thread = Thread.new(server) do|srv|
|
65
|
+
srv.start
|
66
|
+
end
|
67
|
+
params = {:cat => "hat", :foo => "bar"}
|
68
|
+
|
69
|
+
c = Curl::Easy.http_post("http://127.0.0.1:9999/test") do |curl|
|
70
|
+
curl.headers["User-Agent"] = "Curl/Ruby"
|
71
|
+
curl.headers["X-Tender-Auth"] = "A Token"
|
72
|
+
curl.headers["Accept"] = "application/vnd.tender-v1+json"
|
73
|
+
|
74
|
+
curl.post_body = params.map{|f,k| "#{curl.escape(f)}=#{curl.escape(k)}"}.join('&')
|
75
|
+
|
76
|
+
curl.follow_location = true
|
77
|
+
curl.enable_cookies = true
|
78
|
+
end
|
79
|
+
|
80
|
+
server.shutdown
|
81
|
+
thread.join
|
82
|
+
end
|
83
|
+
end
|
data/tests/bug_multi_segfault.rb
CHANGED
@@ -6,5 +6,9 @@
|
|
6
6
|
$:.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','ext'))
|
7
7
|
$:.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','lib'))
|
8
8
|
require 'curb'
|
9
|
-
|
10
|
-
|
9
|
+
|
10
|
+
class BugMultiSegfault < Test::Unit::TestCase
|
11
|
+
def test_bug
|
12
|
+
multi = Curl::Multi.new
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# From GICodeWarrior:
|
2
|
+
#
|
3
|
+
# $ ruby crash_curb.rb
|
4
|
+
# crash_curb.rb:7: [BUG] Segmentation fault
|
5
|
+
# ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]
|
6
|
+
#
|
7
|
+
# Aborted
|
8
|
+
# crash_curb.rb:
|
9
|
+
# #!/usr/bin/ruby
|
10
|
+
# require 'rubygems'
|
11
|
+
# require 'curb'
|
12
|
+
#
|
13
|
+
# curl = Curl::Easy.new('http://example.com/')
|
14
|
+
# curl.multipart_form_post = true
|
15
|
+
# curl.http_post(Curl::PostField.file('test', 'test.xml'){'example data'})
|
16
|
+
# Ubuntu 9.10
|
17
|
+
# curb gem version 0.6.2.1
|
18
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
19
|
+
|
20
|
+
class BugPostFieldsCrash < Test::Unit::TestCase
|
21
|
+
def test_crash
|
22
|
+
curl = Curl::Easy.new('http://example.com/')
|
23
|
+
curl.multipart_form_post = true
|
24
|
+
curl.http_post(Curl::PostField.file('test', 'test.xml'){'example data'})
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Not sure if this is an IRB bug, but thought you guys should know.
|
2
|
+
#
|
3
|
+
# ** My Ruby version: ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]
|
4
|
+
# ** Version of Rubygems: 1.3.5
|
5
|
+
# ** Version of the Curb gem: 0.6.6.0
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# Transcript of IRB session:
|
9
|
+
# ------------------------------------------------------------------------------------------------------------------
|
10
|
+
# irb(main):001:0> a = {
|
11
|
+
# irb(main):002:1* :type => :pie,
|
12
|
+
# irb(main):003:1* :series => {
|
13
|
+
# irb(main):004:2* :names => [:a,:b],
|
14
|
+
# irb(main):005:2* :values => [70,30],
|
15
|
+
# irb(main):006:2* :colors => [:red,:green]
|
16
|
+
# irb(main):007:2> },
|
17
|
+
# irb(main):008:1* :output_format => :png
|
18
|
+
# irb(main):009:1> }
|
19
|
+
# => {:type=>:pie, :output_format=>:png, :series=>{:names=>[:a, :b], :values=>[70, 30], :colors=>[:red, :green]}}
|
20
|
+
# irb(main):010:0> post = []
|
21
|
+
# => []
|
22
|
+
# irb(main):011:0> require 'rubygems'
|
23
|
+
# => true
|
24
|
+
# irb(main):012:0> require 'curb'
|
25
|
+
# => true
|
26
|
+
# irb(main):013:0> include Curl
|
27
|
+
# => Object
|
28
|
+
# irb(main):014:0> a.each_pair do |k,v|
|
29
|
+
# irb(main):015:1* post << PostField.content(k,v)
|
30
|
+
# irb(main):016:1> end
|
31
|
+
# => {:type=>:pie, :output_format=>:png, :series=>{:names=>[:a, :b], :values=>[70, 30], :colors=>[:red, :green]}}
|
32
|
+
# irb(main):017:0> post
|
33
|
+
# /usr/lib/ruby/1.8/irb.rb:302: [BUG] Segmentation fault
|
34
|
+
# ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]
|
35
|
+
#
|
36
|
+
# Aborted
|
37
|
+
# ------------------------------------------------------------------------------------------------------------------
|
38
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
39
|
+
|
40
|
+
class BugPostFieldsCrash2 < Test::Unit::TestCase
|
41
|
+
def test_crash
|
42
|
+
a = {
|
43
|
+
:type => :pie,
|
44
|
+
:series => {
|
45
|
+
:names => [:a,:b],
|
46
|
+
:values => [70,30],
|
47
|
+
:colors => [:red,:green]
|
48
|
+
},
|
49
|
+
:output_format => :png
|
50
|
+
}
|
51
|
+
post = []
|
52
|
+
a.each_pair do |k,v|
|
53
|
+
post << Curl::PostField.content(k,v)
|
54
|
+
end
|
55
|
+
post.inspect
|
56
|
+
end
|
57
|
+
end
|
data/tests/bugtests.rb
ADDED
data/tests/helper.rb
CHANGED
@@ -11,6 +11,7 @@ $:.unshift($EXTDIR)
|
|
11
11
|
|
12
12
|
require 'curb'
|
13
13
|
require 'test/unit'
|
14
|
+
require 'fileutils'
|
14
15
|
|
15
16
|
$TEST_URL = "file://#{URI.escape(File.expand_path(__FILE__).tr('\\','/').tr(':','|'))}"
|
16
17
|
|
@@ -73,14 +74,18 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
73
74
|
end
|
74
75
|
|
75
76
|
def do_POST(req,res)
|
76
|
-
if req.
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
77
|
+
if req.query['filename'].nil?
|
78
|
+
if req.body
|
79
|
+
params = {}
|
80
|
+
req.body.split('&').map{|s| k,v=s.split('='); params[k] = v }
|
81
|
+
end
|
82
|
+
if params and params['s'] == '500'
|
83
|
+
res.status = 500
|
84
|
+
else
|
85
|
+
respond_with("POST\n#{req.body}",req,res)
|
86
|
+
end
|
82
87
|
else
|
83
|
-
respond_with(
|
88
|
+
respond_with(req.query['filename'],req,res)
|
84
89
|
end
|
85
90
|
end
|
86
91
|
|
@@ -93,6 +98,14 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
93
98
|
respond_with(:DELETE,req,res)
|
94
99
|
end
|
95
100
|
|
101
|
+
def do_PURGE(req,res)
|
102
|
+
respond_with(:PURGE,req,res)
|
103
|
+
end
|
104
|
+
|
105
|
+
def do_COPY(req,res)
|
106
|
+
respond_with(:COPY,req,res)
|
107
|
+
end
|
108
|
+
|
96
109
|
end
|
97
110
|
|
98
111
|
module TestServerMethods
|
@@ -165,5 +178,6 @@ module TestServerMethods
|
|
165
178
|
at_exit{exit_code.call}
|
166
179
|
|
167
180
|
end
|
181
|
+
rescue Errno::EADDRINUSE
|
168
182
|
end
|
169
183
|
end
|
data/tests/mem_check.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
+
#require 'rubygems'
|
3
|
+
#require 'rmem'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Run some tests to measure the memory usage of curb, these tests require fork and ps
|
7
|
+
#
|
8
|
+
class TestCurbMemory < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_easy_memory
|
11
|
+
easy_avg, easy_std = measure_object_memory(Curl::Easy)
|
12
|
+
printf "Easy average: %.2f kilobytes +/- %.2f kilobytes\n", easy_avg.to_f, easy_std.to_f
|
13
|
+
|
14
|
+
multi_avg, multi_std = measure_object_memory(Curl::Multi)
|
15
|
+
printf "Multi average: %.2f kilobytes +/- %.2f kilobytes\n", multi_avg.to_f, multi_std.to_f
|
16
|
+
|
17
|
+
# now that we have the average size of an easy handle lets see how much a multi request consumes with 10 requests
|
18
|
+
end
|
19
|
+
|
20
|
+
def c_avg(report)
|
21
|
+
sum = 0
|
22
|
+
report.each {|r| sum += r.last }
|
23
|
+
(sum.to_f / report.size)
|
24
|
+
end
|
25
|
+
|
26
|
+
def c_std(report,avg)
|
27
|
+
var = 0
|
28
|
+
report.each {|r| var += (r.last-avg)*(r.last-avg) }
|
29
|
+
Math.sqrt(var / (report.size-1))
|
30
|
+
end
|
31
|
+
|
32
|
+
def measure_object_memory(klass)
|
33
|
+
report = []
|
34
|
+
200.times do
|
35
|
+
res = mem_check do
|
36
|
+
obj = klass.new
|
37
|
+
end
|
38
|
+
report << res
|
39
|
+
end
|
40
|
+
avg = c_avg(report)
|
41
|
+
std = c_std(report,avg)
|
42
|
+
[avg,std]
|
43
|
+
end
|
44
|
+
|
45
|
+
def mem_check
|
46
|
+
# see: http://gist.github.com/264060 for inspiration of ps command line
|
47
|
+
rd, wr = IO.pipe
|
48
|
+
memory_usage = `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
|
49
|
+
fork do
|
50
|
+
before = `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
|
51
|
+
rd.close
|
52
|
+
yield
|
53
|
+
after = `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
|
54
|
+
wr.write((after - before))
|
55
|
+
wr.flush
|
56
|
+
wr.close
|
57
|
+
end
|
58
|
+
wr.close
|
59
|
+
total = rd.read.to_i
|
60
|
+
rd.close
|
61
|
+
Process.wait
|
62
|
+
# return the delta and the total
|
63
|
+
[memory_usage, total]
|
64
|
+
end
|
65
|
+
end
|
data/tests/tc_curl_download.rb
CHANGED
@@ -7,7 +7,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
|
|
7
7
|
server_setup
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
10
|
+
def test_download_url_to_file_via_string
|
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
|
|
@@ -18,6 +18,49 @@ class TestCurbCurlDownload < Test::Unit::TestCase
|
|
18
18
|
File.unlink(dl_path) if File.exist?(dl_path)
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_download_url_to_file_via_file_io
|
22
|
+
dl_url = "http://127.0.0.1:9129/ext/curb_easy.c"
|
23
|
+
dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
|
24
|
+
io = File.open(dl_path, 'wb')
|
25
|
+
|
26
|
+
curb = Curl::Easy.download(dl_url, io)
|
27
|
+
assert io.closed?
|
28
|
+
assert File.exist?(dl_path)
|
29
|
+
assert_equal File.read(File.join(File.dirname(__FILE__), '..','ext','curb_easy.c')), File.read(dl_path)
|
30
|
+
ensure
|
31
|
+
File.unlink(dl_path) if File.exist?(dl_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_download_url_to_file_via_io
|
35
|
+
dl_url = "http://127.0.0.1:9129/ext/curb_easy.c"
|
36
|
+
dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
|
37
|
+
reader, writer = IO.pipe
|
38
|
+
|
39
|
+
# Write to local file
|
40
|
+
fork do
|
41
|
+
begin
|
42
|
+
writer.close
|
43
|
+
File.open(dl_path, 'wb') { |file| file << reader.read }
|
44
|
+
ensure
|
45
|
+
reader.close rescue IOError # if the stream has already been closed
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Download remote source
|
50
|
+
begin
|
51
|
+
reader.close
|
52
|
+
curb = Curl::Easy.download(dl_url, writer)
|
53
|
+
Process.wait
|
54
|
+
ensure
|
55
|
+
writer.close rescue IOError # if the stream has already been closed, which occurs in Easy::download
|
56
|
+
end
|
57
|
+
|
58
|
+
assert File.exist?(dl_path)
|
59
|
+
assert_equal File.read(File.join(File.dirname(__FILE__), '..','ext','curb_easy.c')), File.read(dl_path)
|
60
|
+
ensure
|
61
|
+
File.unlink(dl_path) if File.exist?(dl_path)
|
62
|
+
end
|
63
|
+
|
21
64
|
def test_download_bad_url_gives_404
|
22
65
|
dl_url = "http://127.0.0.1:9129/this_file_does_not_exist.html"
|
23
66
|
dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
|