curb 0.9.3 → 0.9.11

Sign up to get free protection for your applications and to get access to all the features.
data/ext/curb_multi.h CHANGED
@@ -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
 
data/ext/extconf.rb CHANGED
@@ -59,6 +59,9 @@ def have_constant(name)
59
59
  end
60
60
  end
61
61
 
62
+ have_constant "curlopt_tcp_keepalive"
63
+ have_constant "curlopt_tcp_keepidle"
64
+ have_constant "curlopt_tcp_keepintvl"
62
65
  have_constant "curlinfo_appconnect_time"
63
66
  have_constant "curlinfo_redirect_time"
64
67
  have_constant "curlinfo_response_code"
@@ -66,6 +69,7 @@ have_constant "curlinfo_filetime"
66
69
  have_constant "curlinfo_redirect_count"
67
70
  have_constant "curlinfo_os_errno"
68
71
  have_constant "curlinfo_num_connects"
72
+ have_constant "curlinfo_cookielist"
69
73
  have_constant "curlinfo_ftp_entry_path"
70
74
  have_constant "curl_version_ssl"
71
75
  have_constant "curl_version_libz"
@@ -83,6 +87,7 @@ have_constant "curlproxy_http"
83
87
  have_constant "curlproxy_socks4"
84
88
  have_constant "curlproxy_socks4a"
85
89
  have_constant "curlproxy_socks5"
90
+ have_constant "curlproxy_socks5_hostname"
86
91
  have_constant "curlauth_basic"
87
92
  have_constant "curlauth_digest"
88
93
  have_constant "curlauth_gssnegotiate"
@@ -101,6 +106,12 @@ have_constant "curle_send_fail_rewind"
101
106
  have_constant "curle_ssl_engine_initfailed"
102
107
  have_constant "curle_login_denied"
103
108
 
109
+ # older than 7.10.0
110
+ have_constant "curlopt_nosignal"
111
+
112
+ # older than 7.16.0
113
+ have_constant "curlmopt_pipelining"
114
+
104
115
  # older than 7.16.3
105
116
  have_constant "curlmopt_maxconnects"
106
117
 
@@ -145,6 +156,8 @@ have_func("curl_multi_timeout")
145
156
  have_func("curl_multi_fdset")
146
157
  have_func("curl_multi_perform")
147
158
 
159
+ have_constant "curlopt_haproxyprotocol"
160
+
148
161
  # constants
149
162
  have_constant "curlopt_interleavefunction"
150
163
  have_constant "curlopt_interleavedata"
@@ -209,6 +222,7 @@ have_constant "curlopt_httppost"
209
222
  have_constant "curlopt_referer"
210
223
  have_constant "curlopt_useragent"
211
224
  have_constant "curlopt_httpheader"
225
+ have_constant "curlopt_proxyheader"
212
226
  have_constant "curlopt_http200aliases"
213
227
  have_constant "curlopt_cookie"
214
228
  have_constant "curlopt_cookiefile"
@@ -318,14 +332,14 @@ have_constant "curlopt_sslengine"
318
332
  have_constant "curlopt_sslengine_default"
319
333
  have_constant "curlopt_sslversion"
320
334
  have_constant "curl_sslversion_default"
321
- have_constant "curl_sslversion_tlsv1"
322
- have_constant "curl_sslversion_sslv2"
323
- have_constant "curl_sslversion_sslv3"
335
+ have_constant :CURL_SSLVERSION_TLSv1
336
+ have_constant :CURL_SSLVERSION_SSLv2
337
+ have_constant :CURL_SSLVERSION_SSLv3
324
338
 
325
339
  # Added in 7.34.0
326
- have_constant "curl_sslversion_tlsv1_0"
327
- have_constant "curl_sslversion_tlsv1_1"
328
- have_constant "curl_sslversion_tlsv1_2"
340
+ have_constant :CURL_SSLVERSION_TLSv1_0
341
+ have_constant :CURL_SSLVERSION_TLSv1_1
342
+ have_constant :CURL_SSLVERSION_TLSv1_2
329
343
 
330
344
  have_constant "curlopt_ssl_verifypeer"
331
345
  have_constant "curlopt_cainfo"
@@ -360,6 +374,16 @@ have_constant "curle_not_built_in"
360
374
 
361
375
  have_constant "curle_obsolete" # removed in 7.24 ?
362
376
 
377
+ have_constant "curle_ftp_pret_failed"
378
+ have_constant "curle_rtsp_cseq_error"
379
+ have_constant "curle_rtsp_session_error"
380
+ have_constant "curle_ftp_bad_file_list"
381
+ have_constant "curle_chunk_failed"
382
+ have_constant "curle_no_connection_available"
383
+ have_constant "curle_ssl_pinnedpubkeynotmatch"
384
+ have_constant "curle_ssl_invalidcertstatus"
385
+ have_constant "curle_http2_stream"
386
+
363
387
  # gssapi/spnego delegation related constants
364
388
  have_constant "curlopt_gssapi_delegation"
365
389
  have_constant "curlgssapi_delegation_policy_flag"
@@ -370,6 +394,12 @@ have_constant "CURLM_ADDED_ALREADY"
370
394
  # added in 7.40.0
371
395
  have_constant "curlopt_unix_socket_path"
372
396
 
397
+ # added in 7.42.0
398
+ have_constant "curlopt_path_as_is"
399
+
400
+ # added in 7.43.0
401
+ have_constant "curlopt_pipewait"
402
+
373
403
  if try_compile('int main() { return 0; }','-Wall')
374
404
  $CFLAGS << ' -Wall'
375
405
  end
@@ -397,6 +427,8 @@ test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
397
427
 
398
428
  have_func('rb_thread_blocking_region')
399
429
  have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
430
+ have_header('ruby/io.h')
431
+ have_func('rb_io_stdio_file')
400
432
 
401
433
  create_header('curb_config.h')
402
434
  create_makefile('curb_core')
data/lib/curb.rb CHANGED
@@ -1 +1,2 @@
1
+ # frozen_string_literal: true
1
2
  require 'curl'
data/lib/curl/easy.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Curl
2
3
  class Easy
3
4
 
@@ -19,9 +20,9 @@ module Curl
19
20
  # easy.status => String
20
21
  #
21
22
  def status
22
- # Matches the last HTTP Status - following the HTTP protocol specification 'Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF'
23
- statuses = self.header_str.scan(/HTTP\/\d\.\d\s(\d+\s.*)\r\n/).map{ |match| match[0] }
24
- statuses.last.strip
23
+ # Matches the last HTTP Status - following the HTTP protocol specification 'Status-Line = HTTP-Version SP Status-Code SP (Opt:)Reason-Phrase CRLF'
24
+ statuses = self.header_str.scan(/HTTP\/\d(\.\d)?\s(\d+\s.*)\r\n/).map{ |match| match[1] }
25
+ statuses.last.strip if statuses.length > 0
25
26
  end
26
27
 
27
28
  #
@@ -68,9 +69,14 @@ module Curl
68
69
  ret = self.multi.perform
69
70
  self.multi.remove self
70
71
 
72
+ if Curl::Multi.autoclose
73
+ self.multi.close
74
+ self.multi = nil
75
+ end
76
+
71
77
  if self.last_result != 0 && self.on_failure.nil?
72
78
  error = Curl::Easy.error(self.last_result)
73
- raise error.first.new(error.last)
79
+ raise error.first.new(self.head)
74
80
  end
75
81
 
76
82
  ret
data/lib/curl/multi.rb CHANGED
@@ -1,12 +1,12 @@
1
+ # frozen_string_literal: true
1
2
  module Curl
2
-
3
3
  class Multi
4
4
  class << self
5
5
  # call-seq:
6
6
  # Curl::Multi.get(['url1','url2','url3','url4','url5'], :follow_location => true) do|easy|
7
7
  # easy
8
8
  # end
9
- #
9
+ #
10
10
  # Blocking call to fetch multiple url's in parallel.
11
11
  def get(urls, easy_options={}, multi_options={}, &blk)
12
12
  url_confs = []
@@ -25,10 +25,10 @@ module Curl
25
25
  # {:pipeline => Curl::CURLPIPE_HTTP1}) do|easy|
26
26
  # easy_handle_on_request_complete
27
27
  # end
28
- #
28
+ #
29
29
  # Blocking call to POST multiple form's in parallel.
30
- #
31
- # urls_with_config: is a hash of url's pointing to the postfields to send
30
+ #
31
+ # urls_with_config: is a hash of url's pointing to the postfields to send
32
32
  # easy_options: are a set of common options to set on all easy handles
33
33
  # multi_options: options to set on the Curl::Multi handle
34
34
  #
@@ -49,10 +49,10 @@ module Curl
49
49
  # {:pipeline => Curl::CURLPIPE_HTTP1}) do|easy|
50
50
  # easy_handle_on_request_complete
51
51
  # end
52
- #
52
+ #
53
53
  # Blocking call to POST multiple form's in parallel.
54
- #
55
- # urls_with_config: is a hash of url's pointing to the postfields to send
54
+ #
55
+ # urls_with_config: is a hash of url's pointing to the postfields to send
56
56
  # easy_options: are a set of common options to set on all easy handles
57
57
  # multi_options: options to set on the Curl::Multi handle
58
58
  #
@@ -79,7 +79,7 @@ module Curl
79
79
  # Blocking call to issue multiple HTTP requests with varying verb's.
80
80
  #
81
81
  # urls_with_config: is a hash of url's pointing to the easy handle options as well as the special option :method, that can by one of [:get, :post, :put, :delete, :head], when no verb is provided e.g. :method => nil -> GET is used
82
- # multi_options: options for the multi handle
82
+ # multi_options: options for the multi handle
83
83
  # blk: a callback, that yeilds when a handle is completed
84
84
  #
85
85
  def http(urls_with_config, multi_options={}, &blk)
@@ -128,7 +128,7 @@ module Curl
128
128
 
129
129
  # headers is a special key
130
130
  headers.each {|k,v| easy.headers[k] = v } if headers
131
-
131
+
132
132
  #
133
133
  # use the remaining options as specific configuration to the easy handle
134
134
  # bad options should raise an undefined method error
@@ -144,7 +144,7 @@ module Curl
144
144
 
145
145
  max_connects.times do
146
146
  conf = urls_with_config.pop
147
- add_free_handle.call conf, nil
147
+ add_free_handle.call(conf, nil) if conf
148
148
  break if urls_with_config.empty?
149
149
  end
150
150
 
@@ -153,7 +153,7 @@ module Curl
153
153
  if urls_with_config.size > 0 && free_handles.size > 0
154
154
  easy = free_handles.pop
155
155
  conf = urls_with_config.pop
156
- add_free_handle.call conf, easy
156
+ add_free_handle.call(conf, easy) if conf
157
157
  end
158
158
  end
159
159
 
@@ -168,6 +168,7 @@ module Curl
168
168
  end
169
169
  free_handles = nil
170
170
  end
171
+
171
172
  end
172
173
 
173
174
  # call-seq:
@@ -175,7 +176,7 @@ module Curl
175
176
  # Curl::Multi.download(['http://example.com/p/a/t/h/file1.txt','http://example.com/p/a/t/h/file2.txt']){|c|}
176
177
  #
177
178
  # will create 2 new files file1.txt and file2.txt
178
- #
179
+ #
179
180
  # 2 files will be opened, and remain open until the call completes
180
181
  #
181
182
  # when using the :post or :put method, urls should be a hash, including the individual post fields per post
@@ -242,7 +243,45 @@ module Curl
242
243
  }
243
244
  raise errors unless errors.empty?
244
245
  end
246
+ end
245
247
 
248
+ def cancel!
249
+ requests.each do |_,easy|
250
+ remove(easy)
251
+ end
246
252
  end
253
+
254
+ def idle?
255
+ requests.empty?
256
+ end
257
+
258
+ def requests
259
+ @requests ||= {}
260
+ end
261
+
262
+ def add(easy)
263
+ return self if requests[easy.object_id]
264
+ requests[easy.object_id] = easy
265
+ _add(easy)
266
+ self
267
+ end
268
+
269
+ def remove(easy)
270
+ return self if !requests[easy.object_id]
271
+ requests.delete(easy.object_id)
272
+ _remove(easy)
273
+ self
274
+ end
275
+
276
+ def close
277
+ requests.values.each {|easy|
278
+ _remove(easy)
279
+ }
280
+ @requests = {}
281
+ _close
282
+ self
283
+ end
284
+
285
+
247
286
  end
248
287
  end
data/lib/curl.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'curb_core'
2
3
  require 'curl/easy'
3
4
  require 'curl/multi'
@@ -6,7 +7,7 @@ require 'cgi'
6
7
 
7
8
  # expose shortcut methods
8
9
  module Curl
9
-
10
+
10
11
  def self.http(verb, url, post_body=nil, put_data=nil, &block)
11
12
  handle = Thread.current[:curb_curl] ||= Curl::Easy.new
12
13
  handle.reset
@@ -47,14 +48,13 @@ module Curl
47
48
  end
48
49
 
49
50
  def self.urlalize(url, params={})
50
- query_str = params.map {|k,v| "#{URI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
51
- if url.match(/\?/) && query_str.size > 0
52
- "#{url}&#{query_str}"
53
- elsif query_str.size > 0
54
- "#{url}?#{query_str}"
55
- else
56
- url
57
- end
51
+ uri = URI(url)
52
+ # early return if we didn't specify any extra params
53
+ return uri.to_s if (params || {}).empty?
54
+
55
+ params_query = URI.encode_www_form(params || {})
56
+ uri.query = [uri.query.to_s, params_query].reject(&:empty?).join('&')
57
+ uri.to_s
58
58
  end
59
59
 
60
60
  def self.postalize(params={})
@@ -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
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
@@ -136,7 +142,7 @@ module TestServerMethods
136
142
 
137
143
  def server_setup(port=9129,servlet=TestServlet)
138
144
  @__port = port
139
- if @server.nil? and !File.exist?(locked_file)
145
+ if (@server ||= nil).nil? and !File.exist?(locked_file)
140
146
 
141
147
  File.open(locked_file,'w') {|f| f << 'locked' }
142
148
  if TEST_SINGLE_THREADED
@@ -145,7 +151,7 @@ module TestServerMethods
145
151
  rd.close
146
152
  rd = nil
147
153
 
148
- # start up a webrick server for testing delete
154
+ # start up a webrick server for testing delete
149
155
  server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => File.expand_path(File.dirname(__FILE__))
150
156
 
151
157
  server.mount(servlet.path, servlet)
@@ -161,7 +167,7 @@ module TestServerMethods
161
167
  rd.read
162
168
  rd.close
163
169
  else
164
- # start up a webrick server for testing delete
170
+ # start up a webrick server for testing delete
165
171
  @server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => File.expand_path(File.dirname(__FILE__))
166
172
 
167
173
  @server.mount(servlet.path, servlet)
@@ -202,3 +208,81 @@ module TestServerMethods
202
208
  rescue Errno::EADDRINUSE
203
209
  end
204
210
  end
211
+
212
+
213
+
214
+ # Backport for Ruby 1.8
215
+ module Backports
216
+ module Ruby18
217
+ module URIFormEncoding
218
+ TBLENCWWWCOMP_ = {}
219
+ TBLDECWWWCOMP_ = {}
220
+
221
+ def encode_www_form_component(str)
222
+ if TBLENCWWWCOMP_.empty?
223
+ 256.times do |i|
224
+ TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
225
+ end
226
+ TBLENCWWWCOMP_[' '] = '+'
227
+ TBLENCWWWCOMP_.freeze
228
+ end
229
+ str.to_s.gsub( /([^*\-.0-9A-Z_a-z])/ ) {|*| TBLENCWWWCOMP_[$1] }
230
+ end
231
+
232
+ def decode_www_form_component(str)
233
+ if TBLDECWWWCOMP_.empty?
234
+ 256.times do |i|
235
+ h, l = i>>4, i&15
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
+ TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
240
+ end
241
+ TBLDECWWWCOMP_['+'] = ' '
242
+ TBLDECWWWCOMP_.freeze
243
+ end
244
+
245
+ raise ArgumentError, "invalid %-encoding (#{str.dump})" unless /\A(?:%[[:xdigit:]]{2}|[^%]+)*\z/ =~ str
246
+ str.gsub( /(\+|%[[:xdigit:]]{2})/ ) {|*| TBLDECWWWCOMP_[$1] }
247
+ end
248
+
249
+ def encode_www_form( enum )
250
+ enum.map do |k,v|
251
+ if v.nil?
252
+ encode_www_form_component(k)
253
+ elsif v.respond_to?(:to_ary)
254
+ v.to_ary.map do |w|
255
+ str = encode_www_form_component(k)
256
+ unless w.nil?
257
+ str << '='
258
+ str << encode_www_form_component(w)
259
+ end
260
+ end.join('&')
261
+ else
262
+ str = encode_www_form_component(k)
263
+ str << '='
264
+ str << encode_www_form_component(v)
265
+ end
266
+ end.join('&')
267
+ end
268
+
269
+ WFKV_ = '(?:%\h\h|[^%#=;&])'
270
+ def decode_www_form(str, _)
271
+ return [] if str.to_s == ''
272
+
273
+ unless /\A#{WFKV_}=#{WFKV_}(?:[;&]#{WFKV_}=#{WFKV_})*\z/ =~ str
274
+ raise ArgumentError, "invalid data of application/x-www-form-urlencoded (#{str})"
275
+ end
276
+ ary = []
277
+ $&.scan(/([^=;&]+)=([^;&]*)/) do
278
+ ary << [decode_www_form_component($1, enc), decode_www_form_component($2, enc)]
279
+ end
280
+ ary
281
+ end
282
+ end
283
+ end
284
+ end
285
+
286
+ unless URI.methods.include?(:encode_www_form)
287
+ URI.extend(Backports::Ruby18::URIFormEncoding)
288
+ 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