curb 0.6.5.0 → 0.8.4

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/lib/curl.rb CHANGED
@@ -1,2 +1,62 @@
1
- require 'curb'
1
+ require 'curb_core'
2
+ require 'curl/easy'
3
+ require 'curl/multi'
4
+ require 'uri'
2
5
 
6
+ # expose shortcut methods
7
+ module Curl
8
+
9
+ def self.http(verb, url, post_body=nil, put_data=nil, &block)
10
+ handle = Thread.current[:curb_curl] ||= Curl::Easy.new
11
+ handle.url = url
12
+ handle.post_body = post_body if post_body
13
+ handle.put_data = put_data if put_data
14
+ yield handle if block_given?
15
+ handle.http(verb)
16
+ handle
17
+ end
18
+
19
+ def self.get(url, params={}, &block)
20
+ http :GET, urlalize(url, params), nil, nil, &block
21
+ end
22
+
23
+ def self.post(url, params={}, &block)
24
+ http :POST, url, postalize(params), nil, &block
25
+ end
26
+
27
+ def self.put(url, params={}, &block)
28
+ http :PUT, url, nil, postalize(params), &block
29
+ end
30
+
31
+ def self.delete(url, params={}, &block)
32
+ http :DELETE, url, postalize(params), nil, &block
33
+ end
34
+
35
+ def self.patch(url, params={}, &block)
36
+ http :PATCH, url, postalize(params), nil, &block
37
+ end
38
+
39
+ def self.head(url, params={}, &block)
40
+ http :HEAD, urlalize(url, params), nil, nil, &block
41
+ end
42
+
43
+ def self.options(url, params={}, &block)
44
+ http :OPTIONS, urlalize(url, params), nil, nil, &block
45
+ end
46
+
47
+ def self.urlalize(url, params={})
48
+ query_str = params.map {|k,v| "#{URI.escape(k.to_s)}=#{URI.escape(v.to_s)}" }.join('&')
49
+ if url.match(/\?/)
50
+ "#{url}&#{query_str}"
51
+ elsif query_str.size > 0
52
+ "#{url}?#{query_str}"
53
+ else
54
+ url
55
+ end
56
+ end
57
+
58
+ def self.postalize(params={})
59
+ params.respond_to?(:map) ? URI.encode_www_form(params) : (params.respond_to?(:to_s) ? params.to_s : params)
60
+ end
61
+
62
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ require 'webrick'
4
+ class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
5
+ class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
6
+
7
+ require 'curl'
8
+
9
+ class BugCrashOnDebug < Test::Unit::TestCase
10
+
11
+ def test_on_debug
12
+ server = WEBrick::HTTPServer.new( :Port => 9999 )
13
+ server.mount_proc("/test") do|req,res|
14
+ res.body = "hi"
15
+ res['Content-Type'] = "text/html"
16
+ end
17
+ puts 'a'
18
+ thread = Thread.new(server) do|srv|
19
+ srv.start
20
+ end
21
+ puts 'b'
22
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
23
+ c.on_debug do|x|
24
+ puts x.inspect
25
+ raise "error" # this will get swallowed
26
+ end
27
+ c.perform
28
+ puts 'c'
29
+ ensure
30
+ puts 'd'
31
+ server.shutdown
32
+ puts 'e'
33
+ puts thread.exit
34
+ puts 'f'
35
+ end
36
+
37
+ end
38
+
39
+ #test_on_debug
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+ require 'webrick'
3
+ class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
4
+ class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
5
+
6
+ class BugCrashOnDebug < Test::Unit::TestCase
7
+
8
+ def test_on_debug
9
+ server = WEBrick::HTTPServer.new( :Port => 9999 )
10
+ server.mount_proc("/test") do|req,res|
11
+ res.body = "hi"
12
+ res['Content-Type'] = "text/html"
13
+ end
14
+
15
+ thread = Thread.new(server) do|srv|
16
+ srv.start
17
+ end
18
+
19
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
20
+ c.on_progress do|x|
21
+ raise "error"
22
+ end
23
+ c.perform
24
+
25
+ assert false, "should not reach this point"
26
+
27
+ rescue => e
28
+ assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
29
+ c.close
30
+ ensure
31
+ server.shutdown
32
+ end
33
+ end
@@ -21,7 +21,7 @@ class BugTestInstancePostDiffersFromClassPost < Test::Unit::TestCase
21
21
 
22
22
  5.times do |i|
23
23
  t = Thread.new do
24
- c = Curl::Easy.perform('http://localhost:9999/test')
24
+ c = Curl::Easy.perform('http://127.0.0.1:9999/test')
25
25
  c.header_str
26
26
  end
27
27
  threads << t
@@ -37,7 +37,7 @@ class BugTestInstancePostDiffersFromClassPost < Test::Unit::TestCase
37
37
  timer = Time.now
38
38
  single_responses = []
39
39
  5.times do |i|
40
- c = Curl::Easy.perform('http://localhost:9999/test')
40
+ c = Curl::Easy.perform('http://127.0.0.1:9999/test')
41
41
  single_responses << c.header_str
42
42
  end
43
43
 
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ class BugIssue102 < Test::Unit::TestCase
4
+
5
+ def test_interface
6
+ test = "https://api.twitter.com/1/users/show.json?screen_name=TwitterAPI&include_entities=true"
7
+ ip = "192.168.1.61"
8
+
9
+ c = Curl::Easy.new do |curl|
10
+ curl.url = test
11
+ curl.interface = ip
12
+ end
13
+
14
+ c.perform
15
+ end
16
+
17
+ end
@@ -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
- multi = Curl::Multi.new
10
- exit
9
+
10
+ class BugMultiSegfault < Test::Unit::TestCase
11
+ def test_bug
12
+ multi = Curl::Multi.new
13
+ end
14
+ 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
@@ -24,7 +24,7 @@
24
24
  require 'test/unit'
25
25
  require 'rbconfig'
26
26
 
27
- $rubycmd = Config::CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
27
+ $rubycmd = RbConfig::CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
28
28
 
29
29
  class BugTestRequireLastOrSegfault < Test::Unit::TestCase
30
30
  def test_bug
data/tests/bugtests.rb ADDED
@@ -0,0 +1,9 @@
1
+ $: << $TESTDIR = File.expand_path(File.dirname(__FILE__))
2
+ puts "start"
3
+ begin
4
+ Dir[File.join($TESTDIR, 'bug_*.rb')].each { |lib| require lib }
5
+ rescue Object => e
6
+ puts e.message
7
+ ensure
8
+ puts "done"
9
+ end
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
 
@@ -64,23 +65,35 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
64
65
  end
65
66
 
66
67
  def do_GET(req,res)
67
- respond_with(:GET,req,res)
68
+ if req.path.match /redirect$/
69
+ res.status = 302
70
+ res['Location'] = '/foo'
71
+ elsif req.path.match /not_here$/
72
+ res.status = 404
73
+ elsif req.path.match /error$/
74
+ res.status = 500
75
+ end
76
+ respond_with("GET#{req.query_string}",req,res)
68
77
  end
69
78
 
70
79
  def do_HEAD(req,res)
71
80
  res['Location'] = "/nonexistent"
72
- respond_with(:HEAD, req, res)
81
+ respond_with("HEAD#{req.query_string}",req,res)
73
82
  end
74
83
 
75
84
  def do_POST(req,res)
76
- if req.body
77
- params = {}
78
- req.body.split('&').map{|s| k,v=s.split('='); params[k] = v }
79
- end
80
- if params and params['s'] == '500'
81
- res.status = 500
85
+ if req.query['filename'].nil?
86
+ if req.body
87
+ params = {}
88
+ req.body.split('&').map{|s| k,v=s.split('='); params[k] = v }
89
+ end
90
+ if params and params['s'] == '500'
91
+ res.status = 500
92
+ else
93
+ respond_with("POST\n#{req.body}",req,res)
94
+ end
82
95
  else
83
- respond_with("POST\n#{req.body}",req,res)
96
+ respond_with(req.query['filename'],req,res)
84
97
  end
85
98
  end
86
99
 
@@ -90,7 +103,23 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
90
103
  end
91
104
 
92
105
  def do_DELETE(req,res)
93
- respond_with(:DELETE,req,res)
106
+ respond_with("DELETE#{req.query_string}",req,res)
107
+ end
108
+
109
+ def do_PURGE(req,res)
110
+ respond_with("PURGE#{req.query_string}",req,res)
111
+ end
112
+
113
+ def do_COPY(req,res)
114
+ respond_with("COPY#{req.query_string}",req,res)
115
+ end
116
+
117
+ def do_PATCH(req,res)
118
+ respond_with("PATCH\n#{req.body}",req,res)
119
+ end
120
+
121
+ def do_OPTIONS(req,res)
122
+ respond_with("OPTIONS#{req.query_string}",req,res)
94
123
  end
95
124
 
96
125
  end
@@ -165,5 +194,6 @@ module TestServerMethods
165
194
  at_exit{exit_code.call}
166
195
 
167
196
  end
197
+ rescue Errno::EADDRINUSE
168
198
  end
169
199
  end
data/tests/signals.rb ADDED
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ # This test suite requires the timeout server to be running
4
+ # See tests/timeout.rb for more info about the timeout server
5
+ class TestCurbSignals < Test::Unit::TestCase
6
+
7
+ # Testcase for https://github.com/taf2/curb/issues/117
8
+ def test_continue_after_signal
9
+ trap("SIGUSR1") { }
10
+
11
+ curl = Curl::Easy.new(wait_url(2))
12
+ pid = $$
13
+ Thread.new do
14
+ sleep 1
15
+ Process.kill("SIGUSR1", pid)
16
+ end
17
+ assert_equal true, curl.http_get
18
+ end
19
+
20
+ private
21
+
22
+ def wait_url(time)
23
+ "#{server_base}/wait/#{time}"
24
+ end
25
+
26
+ def serve_url(chunk_size, time, count)
27
+ "#{server_base}/serve/#{chunk_size}/every/#{time}/for/#{count}"
28
+ end
29
+
30
+ def server_base
31
+ 'http://127.0.0.1:9128'
32
+ end
33
+ end
data/tests/tc_curl.rb ADDED
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ class TestCurl < Test::Unit::TestCase
4
+ def test_get
5
+ curl = Curl.get(TestServlet.url, {:foo => "bar"})
6
+ assert_equal "GETfoo=bar", curl.body_str
7
+
8
+ curl = Curl.options(TestServlet.url, {:foo => "bar"}) do|http|
9
+ http.headers['Cookie'] = 'foo=1;bar=2'
10
+ end
11
+ assert_equal "OPTIONSfoo=bar", curl.body_str
12
+ end
13
+
14
+ def test_post
15
+ curl = Curl.post(TestServlet.url, {:foo => "bar"})
16
+ assert_equal "POST\nfoo=bar", curl.body_str
17
+ end
18
+
19
+ def test_put
20
+ curl = Curl.put(TestServlet.url, {:foo => "bar"})
21
+ assert_equal "PUT\nfoo=bar", curl.body_str
22
+ end
23
+
24
+ def test_patch
25
+ curl = Curl.patch(TestServlet.url, {:foo => "bar"})
26
+ assert_equal "PATCH\nfoo=bar", curl.body_str
27
+ end
28
+
29
+ def test_options
30
+ curl = Curl.options(TestServlet.url, {:foo => "bar"})
31
+ assert_equal "OPTIONSfoo=bar", curl.body_str
32
+ end
33
+
34
+ include TestServerMethods
35
+
36
+ def setup
37
+ server_setup
38
+ end
39
+ end
@@ -7,7 +7,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
7
7
  server_setup
8
8
  end
9
9
 
10
- def test_download_url_to_file
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")