curb 0.8.4 → 0.8.8

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/ext/curb_multi.c CHANGED
@@ -4,13 +4,17 @@
4
4
  *
5
5
  */
6
6
  #include "curb_config.h"
7
- #ifdef HAVE_RUBY19_ST_H
8
- #include <ruby.h>
7
+ #include <ruby.h>
8
+ #ifdef HAVE_RUBY_ST_H
9
9
  #include <ruby/st.h>
10
10
  #else
11
- #include <ruby.h>
12
11
  #include <st.h>
13
12
  #endif
13
+
14
+ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
15
+ #include <ruby/thread.h>
16
+ #endif
17
+
14
18
  #include "curb_easy.h"
15
19
  #include "curb_errors.h"
16
20
  #include "curb_postfield.h"
@@ -64,7 +68,7 @@ rb_hash_clear_i(VALUE key, VALUE value, VALUE dummy) {
64
68
 
65
69
  static void curl_multi_free(ruby_curl_multi *rbcm) {
66
70
 
67
- if (rbcm && !rbcm->requests == Qnil && rb_type(rbcm->requests) == T_HASH && RHASH_LEN(rbcm->requests) > 0) {
71
+ if (rbcm && !rbcm->requests == Qnil && rb_type(rbcm->requests) == T_HASH && RHASH_SIZE(rbcm->requests) > 0) {
68
72
 
69
73
  rb_hash_foreach( rbcm->requests, (int (*)())curl_multi_flush_easy, (VALUE)rbcm );
70
74
 
@@ -262,12 +266,9 @@ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
262
266
  */
263
267
  VALUE ruby_curl_multi_remove(VALUE self, VALUE easy) {
264
268
  ruby_curl_multi *rbcm;
265
- ruby_curl_easy *rbce;
266
269
 
267
270
  Data_Get_Struct(self, ruby_curl_multi, rbcm);
268
271
 
269
- Data_Get_Struct(easy, ruby_curl_easy, rbce);
270
-
271
272
  rb_curl_multi_remove(rbcm,easy);
272
273
 
273
274
  return self;
@@ -471,7 +472,7 @@ void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
471
472
  }
472
473
  #endif
473
474
 
474
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
475
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
475
476
  struct _select_set {
476
477
  int maxfd;
477
478
  fd_set *fdread, *fdwrite, *fdexcep;
@@ -511,7 +512,7 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
511
512
  long timeout_milliseconds;
512
513
  struct timeval tv = {0, 0};
513
514
  VALUE block = Qnil;
514
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
515
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
515
516
  struct _select_set fdset_args;
516
517
  #endif
517
518
 
@@ -570,17 +571,24 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
570
571
  create_crt_fd(&fdexcep, &crt_fdexcep);
571
572
  #endif
572
573
 
573
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
574
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
574
575
  fdset_args.maxfd = maxfd+1;
575
576
  fdset_args.fdread = &fdread;
576
577
  fdset_args.fdwrite = &fdwrite;
577
578
  fdset_args.fdexcep = &fdexcep;
578
579
  fdset_args.tv = &tv;
580
+ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
581
+ rc = (int)(VALUE) rb_thread_call_without_gvl((void *(*)(void *))curb_select, &fdset_args, RUBY_UBF_IO, 0);
582
+ #elif HAVE_RB_THREAD_BLOCKING_REGION
579
583
  rc = rb_thread_blocking_region(curb_select, &fdset_args, RUBY_UBF_IO, 0);
584
+ #elif HAVE_RB_THREAD_FD_SELECT
585
+ rc = rb_thread_fd_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
580
586
  #else
581
587
  rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
582
588
  #endif
583
589
 
590
+ #endif
591
+
584
592
  #ifdef _WIN32
585
593
  cleanup_crt_fd(&fdread, &crt_fdread);
586
594
  cleanup_crt_fd(&fdwrite, &crt_fdwrite);
data/ext/extconf.rb CHANGED
@@ -59,6 +59,7 @@ def have_constant(name)
59
59
  end
60
60
  end
61
61
 
62
+ have_constant "curlinfo_appconnect_time"
62
63
  have_constant "curlinfo_redirect_time"
63
64
  have_constant "curlinfo_response_code"
64
65
  have_constant "curlinfo_filetime"
@@ -79,6 +80,7 @@ have_constant "curl_version_sspi"
79
80
  have_constant "curl_version_conv"
80
81
  have_constant "curlproxy_http"
81
82
  have_constant "curlproxy_socks4"
83
+ have_constant "curlproxy_socks4a"
82
84
  have_constant "curlproxy_socks5"
83
85
  have_constant "curlauth_basic"
84
86
  have_constant "curlauth_digest"
@@ -351,6 +353,13 @@ have_constant "curle_not_built_in"
351
353
 
352
354
  have_constant "curle_obsolete" # removed in 7.24 ?
353
355
 
356
+ # gssapi/spnego delegation related constants
357
+ have_constant "curlopt_gssapi_delegation"
358
+ have_constant "curlgssapi_delegation_policy_flag"
359
+ have_constant "curlgssapi_delegation_flag"
360
+
361
+ have_constant "CURLM_ADDED_ALREADY"
362
+
354
363
  if try_compile('int main() { return 0; }','-Wall')
355
364
  $CFLAGS << ' -Wall'
356
365
  end
@@ -366,23 +375,6 @@ def test_for(name, const, src)
366
375
  end
367
376
  end
368
377
  end
369
- test_for("Ruby 1.9 Hash", "RUBY19_HASH", %{
370
- #include <ruby.h>
371
- int main() {
372
- VALUE hash = rb_hash_new();
373
- if( RHASH(hash)->ntbl->num_entries ) {
374
- return 0;
375
- }
376
- return 1;
377
- }
378
- })
379
- test_for("Ruby 1.9 st.h", "RUBY19_ST_H", %{
380
- #include <ruby.h>
381
- #include <ruby/st.h>
382
- int main() {
383
- return 0;
384
- }
385
- })
386
378
 
387
379
  test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
388
380
  #include <curl/curl.h>
@@ -394,6 +386,7 @@ test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
394
386
  })
395
387
 
396
388
  have_func('rb_thread_blocking_region')
389
+ have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
397
390
 
398
391
  create_header('curb_config.h')
399
392
  create_makefile('curb_core')
data/lib/curl/easy.rb CHANGED
@@ -3,32 +3,44 @@ module Curl
3
3
 
4
4
  alias post http_post
5
5
  alias put http_put
6
+ alias body body_str
7
+ alias head header_str
8
+
9
+ class Error < Exception
10
+ attr_accessor :message, :code
11
+ def initialize(code, msg)
12
+ self.message = msg
13
+ self.code = code
14
+ end
15
+ end
6
16
 
7
17
  #
8
18
  # call-seq:
9
19
  # easy.status => String
10
20
  #
11
21
  def status
12
- parts = self.header_str.split(/\s/)
13
- status = []
14
- parts.shift
15
- while parts.size > 0 && parts.first != ''
16
- status << parts.shift
17
- end
18
- status.join(' ')
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
19
25
  end
20
26
 
21
27
  #
22
28
  # call-seq:
23
29
  # easy.set :sym|Fixnum, value
24
- #
30
+ #
25
31
  # set options on the curl easy handle see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
26
32
  #
27
33
  def set(opt,val)
28
34
  if opt.is_a?(Symbol)
29
- setopt(sym2curl(opt), val)
35
+ option = sym2curl(opt)
30
36
  else
31
- setopt(opt.to_i, val)
37
+ option = opt.to_i
38
+ end
39
+
40
+ begin
41
+ setopt(option, val)
42
+ rescue TypeError
43
+ raise TypeError, "Curb doesn't support setting #{opt} [##{option}] option"
32
44
  end
33
45
  end
34
46
 
@@ -56,8 +68,8 @@ module Curl
56
68
  ret = self.multi.perform
57
69
 
58
70
  if self.last_result != 0 && self.on_failure.nil?
59
- error = Curl::Easy.error(self.last_result)
60
- raise error.first
71
+ error = Curl::Easy.error(self.last_result)
72
+ raise error.first.new(error.last)
61
73
  end
62
74
 
63
75
  ret
@@ -81,54 +93,54 @@ module Curl
81
93
  # easy.perform
82
94
  #
83
95
  def delete=(onoff)
84
- set :customrequest, onoff ? 'delete' : nil
96
+ set :customrequest, onoff ? 'DELETE' : nil
85
97
  onoff
86
98
  end
87
- #
99
+ #
88
100
  # call-seq:
89
- #
101
+ #
90
102
  # easy = Curl::Easy.new("url")
91
103
  # easy.version = Curl::HTTP_1_1
92
104
  # easy.version = Curl::HTTP_1_0
93
105
  # easy.version = Curl::HTTP_NONE
94
- #
106
+ #
95
107
  def version=(http_version)
96
108
  set :http_version, http_version
97
109
  end
98
110
 
99
- #
111
+ #
100
112
  # call-seq:
101
113
  # easy.url = "http://some.url/" => "http://some.url/"
102
- #
114
+ #
103
115
  # Set the URL for subsequent calls to +perform+. It is acceptable
104
116
  # (and even recommended) to reuse Curl::Easy instances by reassigning
105
117
  # the URL between calls to +perform+.
106
- #
118
+ #
107
119
  def url=(u)
108
120
  set :url, u
109
121
  end
110
122
 
111
- #
123
+ #
112
124
  # call-seq:
113
125
  # easy.proxy_url = string => string
114
- #
126
+ #
115
127
  # Set the URL of the HTTP proxy to use for subsequent calls to +perform+.
116
128
  # The URL should specify the the host name or dotted IP address. To specify
117
129
  # port number in this string, append :[port] to the end of the host name.
118
130
  # The proxy string may be prefixed with [protocol]:// since any such prefix
119
131
  # will be ignored. The proxy's port number may optionally be specified with
120
132
  # the separate option proxy_port .
121
- #
133
+ #
122
134
  # When you tell the library to use an HTTP proxy, libcurl will transparently
123
135
  # convert operations to HTTP even if you specify an FTP URL etc. This may have
124
136
  # an impact on what other features of the library you can use, such as
125
137
  # FTP specifics that don't work unless you tunnel through the HTTP proxy. Such
126
138
  # tunneling is activated with proxy_tunnel = true.
127
- #
139
+ #
128
140
  # libcurl respects the environment variables *http_proxy*, *ftp_proxy*,
129
141
  # *all_proxy* etc, if any of those is set. The proxy_url option does however
130
142
  # override any possibly set environment variables.
131
- #
143
+ #
132
144
  # Starting with libcurl 7.14.1, the proxy host string given in environment
133
145
  # variables can be specified the exact same way as the proxy can be set with
134
146
  # proxy_url, including protocol prefix (http://) and embedded user + password.
@@ -143,89 +155,89 @@ module Curl
143
155
  self.ssl_verify_host_integer=value
144
156
  end
145
157
 
146
- #
158
+ #
147
159
  # call-seq:
148
160
  # easy.ssl_verify_host? => boolean
149
- #
161
+ #
150
162
  # Deprecated: call easy.ssl_verify_host instead
151
163
  # can be one of [0,1,2]
152
- #
164
+ #
153
165
  # Determine whether this Curl instance will verify that the server cert
154
166
  # is for the server it is known as.
155
- #
167
+ #
156
168
  def ssl_verify_host?
157
169
  ssl_verify_host.nil? ? false : (ssl_verify_host > 0)
158
170
  end
159
171
 
160
- #
172
+ #
161
173
  # call-seq:
162
174
  # easy.interface = string => string
163
- #
175
+ #
164
176
  # Set the interface name to use as the outgoing network interface.
165
177
  # The name can be an interface name, an IP address or a host name.
166
- #
178
+ #
167
179
  def interface=(value)
168
180
  set :interface, value
169
181
  end
170
182
 
171
- #
183
+ #
172
184
  # call-seq:
173
185
  # easy.userpwd = string => string
174
- #
186
+ #
175
187
  # Set the username/password string to use for subsequent calls to +perform+.
176
188
  # The supplied string should have the form "username:password"
177
- #
189
+ #
178
190
  def userpwd=(value)
179
191
  set :userpwd, value
180
192
  end
181
193
 
182
- #
194
+ #
183
195
  # call-seq:
184
196
  # easy.proxypwd = string => string
185
- #
197
+ #
186
198
  # Set the username/password string to use for proxy connection during
187
199
  # subsequent calls to +perform+. The supplied string should have the
188
200
  # form "username:password"
189
- #
201
+ #
190
202
  def proxypwd=(value)
191
203
  set :proxyuserpwd, value
192
204
  end
193
205
 
194
- #
206
+ #
195
207
  # call-seq:
196
208
  # easy.cookies = "name1=content1; name2=content2;" => string
197
- #
209
+ #
198
210
  # Set cookies to be sent by this Curl::Easy instance. The format of the string should
199
211
  # be NAME=CONTENTS, where NAME is the cookie name and CONTENTS is what the cookie should contain.
200
212
  # Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc.
201
- #
213
+ #
202
214
  def cookies=(value)
203
215
  set :cookie, value
204
216
  end
205
217
 
206
- #
218
+ #
207
219
  # call-seq:
208
220
  # easy.cookiefile = string => string
209
- #
221
+ #
210
222
  # Set a file that contains cookies to be sent in subsequent requests by this Curl::Easy instance.
211
- #
223
+ #
212
224
  # *Note* that you must set enable_cookies true to enable the cookie
213
225
  # engine, or this option will be ignored.
214
- #
226
+ #
215
227
  def cookiefile=(value)
216
228
  set :cookiefile, value
217
229
  end
218
230
 
219
- #
231
+ #
220
232
  # call-seq:
221
233
  # easy.cookiejar = string => string
222
- #
234
+ #
223
235
  # Set a cookiejar file to use for this Curl::Easy instance.
224
236
  # Cookies from the response will be written into this file.
225
- #
237
+ #
226
238
  # *Note* that you must set enable_cookies true to enable the cookie
227
239
  # engine, or this option will be ignored.
228
- #
240
+ #
229
241
  def cookiejar=(value)
230
242
  set :cookiejar, value
231
243
  end
@@ -403,35 +415,35 @@ module Curl
403
415
  c.http_delete
404
416
  c
405
417
  end
406
-
418
+
407
419
  # call-seq:
408
420
  # Curl::Easy.download(url, filename = url.split(/\?/).first.split(/\//).last) { |curl| ... }
409
- #
421
+ #
410
422
  # Stream the specified url (via perform) and save the data directly to the
411
- # supplied filename (defaults to the last component of the URL path, which will
423
+ # supplied filename (defaults to the last component of the URL path, which will
412
424
  # usually be the filename most simple urls).
413
- #
425
+ #
414
426
  # If a block is supplied, it will be passed the curl instance prior to the
415
427
  # perform call.
416
- #
428
+ #
417
429
  # *Note* that the semantics of the on_body handler are subtly changed when using
418
- # download, to account for the automatic routing of data to the specified file: The
430
+ # download, to account for the automatic routing of data to the specified file: The
419
431
  # data string is passed to the handler *before* it is written
420
- # to the file, allowing the handler to perform mutative operations where
432
+ # to the file, allowing the handler to perform mutative operations where
421
433
  # necessary. As usual, the transfer will be aborted if the on_body handler
422
- # returns a size that differs from the data chunk size - in this case, the
434
+ # returns a size that differs from the data chunk size - in this case, the
423
435
  # offending chunk will *not* be written to the file, the file will be closed,
424
436
  # and a Curl::Err::AbortedByCallbackError will be raised.
425
437
  def download(url, filename = url.split(/\?/).first.split(/\//).last, &blk)
426
438
  curl = Curl::Easy.new(url, &blk)
427
-
439
+
428
440
  output = if filename.is_a? IO
429
441
  filename.binmode if filename.respond_to?(:binmode)
430
442
  filename
431
443
  else
432
444
  File.open(filename, 'wb')
433
445
  end
434
-
446
+
435
447
  begin
436
448
  old_on_body = curl.on_body do |data|
437
449
  result = old_on_body ? old_on_body.call(data) : data.length
@@ -442,7 +454,7 @@ module Curl
442
454
  ensure
443
455
  output.close rescue IOError
444
456
  end
445
-
457
+
446
458
  return curl
447
459
  end
448
460
  end
data/lib/curl.rb CHANGED
@@ -2,12 +2,14 @@ require 'curb_core'
2
2
  require 'curl/easy'
3
3
  require 'curl/multi'
4
4
  require 'uri'
5
+ require 'cgi'
5
6
 
6
7
  # expose shortcut methods
7
8
  module Curl
8
9
 
9
10
  def self.http(verb, url, post_body=nil, put_data=nil, &block)
10
11
  handle = Thread.current[:curb_curl] ||= Curl::Easy.new
12
+ handle.reset
11
13
  handle.url = url
12
14
  handle.post_body = post_body if post_body
13
15
  handle.put_data = put_data if put_data
@@ -45,7 +47,7 @@ module Curl
45
47
  end
46
48
 
47
49
  def self.urlalize(url, params={})
48
- query_str = params.map {|k,v| "#{URI.escape(k.to_s)}=#{URI.escape(v.to_s)}" }.join('&')
50
+ query_str = params.map {|k,v| "#{URI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
49
51
  if url.match(/\?/)
50
52
  "#{url}&#{query_str}"
51
53
  elsif query_str.size > 0
@@ -59,4 +61,8 @@ module Curl
59
61
  params.respond_to?(:map) ? URI.encode_www_form(params) : (params.respond_to?(:to_s) ? params.to_s : params)
60
62
  end
61
63
 
64
+ def self.reset
65
+ Thread.current[:curb_curl] = Curl::Easy.new
66
+ end
67
+
62
68
  end
@@ -5,7 +5,7 @@ class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
5
5
 
6
6
  class BugCrashOnDebug < Test::Unit::TestCase
7
7
 
8
- def test_on_debug
8
+ def test_on_progress_raise
9
9
  server = WEBrick::HTTPServer.new( :Port => 9999 )
10
10
  server.mount_proc("/test") do|req,res|
11
11
  res.body = "hi"
@@ -30,4 +30,44 @@ class BugCrashOnDebug < Test::Unit::TestCase
30
30
  ensure
31
31
  server.shutdown
32
32
  end
33
+
34
+ def test_on_progress_abort
35
+ server = WEBrick::HTTPServer.new( :Port => 9999 )
36
+ server.mount_proc("/test") do|req,res|
37
+ res.body = "hi"
38
+ res['Content-Type'] = "text/html"
39
+ end
40
+
41
+ thread = Thread.new(server) do|srv|
42
+ srv.start
43
+ end
44
+
45
+ # see: https://github.com/taf2/curb/issues/192,
46
+ # to pass:
47
+ #
48
+ # c = Curl::Easy.new('http://127.0.0.1:9999/test')
49
+ # c.on_progress do|x|
50
+ # puts "we're in the progress callback"
51
+ # false
52
+ # end
53
+ # c.perform
54
+ #
55
+ # notice no return keyword
56
+ #
57
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
58
+ c.on_progress do|x|
59
+ puts "we're in the progress callback"
60
+ return false
61
+ end
62
+ c.perform
63
+
64
+ assert false, "should not reach this point"
65
+
66
+ rescue => e
67
+ assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
68
+ c.close
69
+ ensure
70
+ server.shutdown
71
+ end
72
+
33
73
  end
@@ -4,7 +4,7 @@ class BugIssue102 < Test::Unit::TestCase
4
4
 
5
5
  def test_interface
6
6
  test = "https://api.twitter.com/1/users/show.json?screen_name=TwitterAPI&include_entities=true"
7
- ip = "192.168.1.61"
7
+ ip = "0.0.0.0"
8
8
 
9
9
  c = Curl::Easy.new do |curl|
10
10
  curl.url = test
data/tests/helper.rb CHANGED
@@ -10,7 +10,12 @@ $:.unshift($LIBDIR)
10
10
  $:.unshift($EXTDIR)
11
11
 
12
12
  require 'curb'
13
- require 'test/unit'
13
+ begin
14
+ require 'test/unit'
15
+ rescue LoadError
16
+ gem 'test/unit'
17
+ require 'test/unit'
18
+ end
14
19
  require 'fileutils'
15
20
 
16
21
  $TEST_URL = "file://#{URI.escape(File.expand_path(__FILE__).tr('\\','/').tr(':','|'))}"
@@ -6,7 +6,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
6
6
  def setup
7
7
  server_setup
8
8
  end
9
-
9
+
10
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")
@@ -4,6 +4,12 @@ class FooNoToS
4
4
  end
5
5
 
6
6
  class TestCurbCurlEasy < Test::Unit::TestCase
7
+ def test_global_reset
8
+ c = Curl.get($TEST_URL)
9
+ # in a Timeout block you should reset the thread current handle
10
+ Curl.reset
11
+ end
12
+
7
13
  def test_threads
8
14
  t = []
9
15
  5.times do
@@ -11,7 +17,9 @@ class TestCurbCurlEasy < Test::Unit::TestCase
11
17
  5.times do
12
18
  c = Curl.get($TEST_URL)
13
19
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
20
+ assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body)
14
21
  assert_equal "", c.header_str
22
+ assert_equal "", c.head
15
23
  end
16
24
  end
17
25
  end
@@ -22,6 +30,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
22
30
  def test_class_perform_01
23
31
  assert_instance_of Curl::Easy, c = Curl::Easy.perform($TEST_URL)
24
32
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
33
+ assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body)
25
34
  assert_equal "", c.header_str
26
35
  end
27
36
 
@@ -642,8 +651,8 @@ class TestCurbCurlEasy < Test::Unit::TestCase
642
651
  curl = Curl::Easy.new(TestServlet.url)
643
652
  curl.multipart_form_post = true
644
653
  fields = [
645
- Curl::PostField.file('foo', File.expand_path(File.join(File.dirname(__FILE__),'..','README'))),
646
- Curl::PostField.file('bar', File.expand_path(File.join(File.dirname(__FILE__),'..','README')))
654
+ Curl::PostField.file('foo', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown'))),
655
+ Curl::PostField.file('bar', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown')))
647
656
  ]
648
657
  curl.http_post(fields)
649
658
  assert_match /HTTP POST file upload/, curl.body_str
@@ -671,7 +680,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
671
680
  def test_post_multipart_file_remote
672
681
  curl = Curl::Easy.new(TestServlet.url)
673
682
  curl.multipart_form_post = true
674
- pf = Curl::PostField.file('readme', File.expand_path(File.join(File.dirname(__FILE__),'..','README')))
683
+ pf = Curl::PostField.file('readme', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown')))
675
684
  curl.http_post(pf)
676
685
  assert_match /HTTP POST file upload/, curl.body_str
677
686
  assert_match /Content-Disposition: form-data/, curl.body_str
@@ -719,7 +728,9 @@ class TestCurbCurlEasy < Test::Unit::TestCase
719
728
  assert curl.http_put("message")
720
729
  assert_match /^PUT/, curl.body_str
721
730
  assert_match /message$/, curl.body_str
731
+ assert_match /message$/, curl.body
722
732
  assert_match /application\/json/, curl.header_str
733
+ assert_match /application\/json/, curl.head
723
734
  end
724
735
 
725
736
  def test_put_data
@@ -850,7 +861,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
850
861
  end
851
862
 
852
863
  def test_post_streaming
853
- readme = File.expand_path(File.join(File.dirname(__FILE__),'..','README'))
864
+ readme = File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown'))
854
865
 
855
866
  pf = Curl::PostField.file("filename", readme)
856
867
 
@@ -1017,6 +1028,13 @@ class TestCurbCurlEasy < Test::Unit::TestCase
1017
1028
  end
1018
1029
  end
1019
1030
 
1031
+ def test_set_unsupported_options
1032
+ curl = Curl::Easy.new
1033
+ assert_raises TypeError do
1034
+ curl.set(99999, 1)
1035
+ end
1036
+ end
1037
+
1020
1038
  include TestServerMethods
1021
1039
 
1022
1040
  def setup
@@ -466,7 +466,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
466
466
  m.add(c)
467
467
  m.add(c)
468
468
  rescue => e
469
- assert_equal Curl::Err::MultiBadEasyHandle, e.class
469
+ assert Curl::Err::MultiBadEasyHandle == e.class || Curl::Err::MultiAddedAlready == e.class
470
470
  end
471
471
 
472
472
  def test_multi_default_timeout