curb 0.4.4.0 → 0.4.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of curb might be problematic. Click here for more details.

data/Rakefile CHANGED
@@ -63,6 +63,11 @@ end
63
63
  desc "Compile the shared object"
64
64
  task :compile => [CURB_SO]
65
65
 
66
+ desc "Create the markdown file"
67
+ task :markdown do
68
+ cp "README", "README.markdown"
69
+ end
70
+
66
71
  desc "Install to your site_ruby directory"
67
72
  task :install => :alltests do
68
73
  m = make 'install'
data/ext/curb.h CHANGED
@@ -20,20 +20,21 @@
20
20
  #include "curb_macros.h"
21
21
 
22
22
  // These should be managed from the Rake 'release' task.
23
- #define CURB_VERSION "0.4.4"
24
- #define CURB_VER_NUM 440
23
+ #define CURB_VERSION "0.4.8.0"
24
+ #define CURB_VER_NUM 480
25
25
  #define CURB_VER_MAJ 0
26
26
  #define CURB_VER_MIN 4
27
- #define CURB_VER_MIC 4
27
+ #define CURB_VER_MIC 8
28
28
  #define CURB_VER_PATCH 0
29
29
 
30
30
 
31
31
  // Maybe not yet defined in Ruby
32
32
  #ifndef RSTRING_LEN
33
- #define RSTRING_LEN(x) RSTRING(x)->len
33
+ #define RSTRING_LEN(x) RSTRING(x)->len
34
34
  #endif
35
+
35
36
  #ifndef RSTRING_PTR
36
- #define RSTRING_PTR(x) RSTRING(x)->ptr
37
+ #define RSTRING_PTR(x) RSTRING(x)->ptr
37
38
  #endif
38
39
 
39
40
  #ifdef HAVE_RUBY19_HASH
data/ext/curb_easy.c CHANGED
@@ -8,6 +8,7 @@
8
8
  #include "curb_errors.h"
9
9
  #include "curb_postfield.h"
10
10
  #include "curb_upload.h"
11
+ #include "curb_multi.h"
11
12
 
12
13
  #include <errno.h>
13
14
  #include <string.h>
@@ -1716,147 +1717,16 @@ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce, VALUE bodybuf, V
1716
1717
  */
1717
1718
  static VALUE handle_perform(VALUE self, ruby_curl_easy *rbce) {
1718
1719
 
1719
- CURLcode result = -1;
1720
- struct curl_slist *headers = NULL;
1721
- VALUE bodybuf = Qnil, headerbuf = Qnil;
1722
- // char errors[CURL_ERROR_SIZE*2];
1720
+ VALUE multi = ruby_curl_multi_new(cCurlMulti);
1721
+ ruby_curl_multi_add(multi, self);
1722
+ VALUE ret = ruby_curl_multi_perform(multi);
1723
1723
 
1724
- ruby_curl_easy_setup(rbce, &bodybuf, &headerbuf, &headers);
1725
- // curl_easy_setopt(rbce->curl, CURLOPT_ERRORBUFFER, errors);
1726
- // curl_easy_setopt(rbce->curl, CURLOPT_VERBOSE, 1);
1727
-
1728
- if( rb_thread_alone() ) {
1729
- result = curl_easy_perform(rbce->curl);
1724
+ /* check for errors in the easy response and raise exceptions if anything went wrong and their is no on_failure handler */
1725
+ if( rbce->last_result != 0 && rbce->failure_proc == Qnil ) {
1726
+ raise_curl_easy_error_exception(rbce->last_result);
1730
1727
  }
1731
- else {
1732
- int msgs;
1733
- int still_running = 1;
1734
- CURLMcode mcode = -1;
1735
- CURLM *multi_handle = curl_multi_init();
1736
- long timeout;
1737
- struct timeval tv = {0, 0};
1738
- int rc; /* select() return code */
1739
- int maxfd;
1740
-
1741
- /* NOTE:
1742
- * We create an Curl multi handle here and use rb_thread_select allowing other ruby threads to
1743
- * perform actions... ideally we'd have just 1 shared multi handle per all curl easy handles globally
1744
- */
1745
- mcode = curl_multi_add_handle(multi_handle, rbce->curl);
1746
- if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
1747
- raise_curl_multi_error_exception(mcode);
1748
- }
1749
-
1750
- while(CURLM_CALL_MULTI_PERFORM == (mcode=curl_multi_perform(multi_handle, &still_running)) ) ;
1751
-
1752
- if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
1753
- raise_curl_multi_error_exception(mcode);
1754
- }
1755
-
1756
-
1757
- while(still_running) {
1758
-
1759
- fd_set fdread;
1760
- fd_set fdwrite;
1761
- fd_set fdexcep;
1762
-
1763
- FD_ZERO(&fdread);
1764
- FD_ZERO(&fdwrite);
1765
- FD_ZERO(&fdexcep);
1766
-
1767
- //time_t timer = time(NULL);
1768
- /* get file descriptors from the transfers */
1769
- mcode = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
1770
- if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
1771
- raise_curl_multi_error_exception(mcode);
1772
- }
1773
-
1774
- #ifdef HAVE_CURL_MULTI_TIMEOUT
1775
- /* get the curl suggested time out */
1776
- mcode = curl_multi_timeout(multi_handle, &timeout);
1777
- if (mcode != CURLM_OK) {
1778
- raise_curl_multi_error_exception(mcode);
1779
- }
1780
- #else
1781
- /* libcurl doesn't have a timeout method defined... make a wild guess */
1782
- timeout = 1; /* wait a second */
1783
- #endif
1784
-
1785
- if (timeout == 0) { /* no delay */
1786
- while(CURLM_CALL_MULTI_PERFORM == (mcode=curl_multi_perform(multi_handle, &still_running)) );
1787
- continue;
1788
- }
1789
- else if (timeout == -1) {
1790
- timeout = 1; /* wait a second */
1791
- }
1792
-
1793
- /* set a suitable timeout to play around with - ruby seems to be greedy about this and won't necessarily yield so the timeout is small.. */
1794
- tv.tv_sec = timeout / 1000;
1795
- tv.tv_usec = (timeout * 1000) % 1000000;
1796
- rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
1797
- if (rc < 0) {
1798
- rb_raise(rb_eRuntimeError, "select(): %s", strerror(errno));
1799
- }
1800
1728
 
1801
- if( rc >= 0 ) {
1802
- switch(rc) {
1803
- case 0:
1804
- //printf("timeout(%.6f) :", difftime(time(NULL), timer) );
1805
- default:
1806
- //printf("readable/writable: %d\n", rc);
1807
- /* timeout or readable/writable sockets */
1808
- while(CURLM_CALL_MULTI_PERFORM == (mcode=curl_multi_perform(multi_handle, &still_running)) );
1809
- break;
1810
- }
1811
- }
1812
- else {
1813
- // error
1814
- }
1815
-
1816
- if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
1817
- raise_curl_multi_error_exception(mcode);
1818
- }
1819
-
1820
- }
1821
-
1822
- /* check for errors */
1823
- CURLMsg *msg = curl_multi_info_read(multi_handle, &msgs);
1824
- if (msg && msg->msg == CURLMSG_DONE) {
1825
- result = msg->data.result;
1826
- }
1827
-
1828
- curl_multi_remove_handle(multi_handle, rbce->curl);
1829
- curl_multi_cleanup(multi_handle);
1830
- }
1831
-
1832
- ruby_curl_easy_cleanup(self, rbce, bodybuf, headerbuf, headers);
1833
-
1834
- if (rbce->complete_proc != Qnil) {
1835
- rb_funcall( rbce->complete_proc, idCall, 1, self );
1836
- }
1837
-
1838
- /* check the request status and determine if on_success or on_failure should be called */
1839
- long response_code = -1;
1840
- curl_easy_getinfo(rbce->curl, CURLINFO_RESPONSE_CODE, &response_code);
1841
- if (result != 0) {
1842
- // printf("error: %s\n", errors);
1843
- if (rbce->failure_proc != Qnil) {
1844
- rb_funcall( rbce->failure_proc, idCall, 2, rbce->self, rb_curl_easy_error(result) );
1845
- } else {
1846
- raise_curl_easy_error_exception(result);
1847
- }
1848
- }
1849
- else if (rbce->success_proc != Qnil &&
1850
- /* NOTE: we allow response_code == 0, in the case the file is being read from disk */
1851
- ((response_code >= 200 && response_code < 300) || response_code == 0)) {
1852
- rb_funcall( rbce->success_proc, idCall, 1, self );
1853
- }
1854
- else if (rbce->failure_proc != Qnil &&
1855
- (response_code >= 300 && response_code <= 999)) {
1856
- rb_funcall( rbce->failure_proc, idCall, 2, rbce->self, rb_curl_easy_error(result) );
1857
- }
1858
-
1859
- return Qtrue;
1729
+ return ret;
1860
1730
  }
1861
1731
 
1862
1732
  /*
data/ext/curb_easy.h CHANGED
@@ -89,6 +89,8 @@ typedef struct {
89
89
  VALUE self; /* pointer to self, used by multi interface */
90
90
  VALUE upload; /* pointer to an active upload otherwise Qnil */
91
91
 
92
+ int last_result; /* last result code from multi loop */
93
+
92
94
  } ruby_curl_easy;
93
95
 
94
96
  extern VALUE cCurlEasy;
data/ext/curb_multi.c CHANGED
@@ -6,9 +6,11 @@
6
6
 
7
7
  #include "curb_config.h"
8
8
  #ifdef HAVE_RUBY19_ST_H
9
- #include <ruby/st.h>
9
+ #include <ruby.h>
10
+ #include <ruby/st.h>
10
11
  #else
11
- #include <st.h>
12
+ #include <ruby.h>
13
+ #include <st.h>
12
14
  #endif
13
15
  #include "curb_easy.h"
14
16
  #include "curb_errors.h"
@@ -26,7 +28,6 @@ static VALUE idCall;
26
28
 
27
29
  VALUE cCurlMulti;
28
30
 
29
- static VALUE ruby_curl_multi_remove(VALUE , VALUE );
30
31
  static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy);
31
32
  static void rb_curl_multi_read_info(VALUE self, CURLM *mptr);
32
33
 
@@ -76,7 +77,7 @@ static void curl_multi_free(ruby_curl_multi *rbcm) {
76
77
  *
77
78
  * Create a new Curl::Multi instance
78
79
  */
79
- static VALUE ruby_curl_multi_new(VALUE klass) {
80
+ VALUE ruby_curl_multi_new(VALUE klass) {
80
81
  VALUE new_curlm;
81
82
 
82
83
  ruby_curl_multi *rbcm = ALLOC(ruby_curl_multi);
@@ -93,6 +94,51 @@ static VALUE ruby_curl_multi_new(VALUE klass) {
93
94
  return new_curlm;
94
95
  }
95
96
 
97
+ // Hash#foreach callback for ruby_curl_multi_requests
98
+ static int ruby_curl_multi_requests_callback(VALUE key, VALUE value, VALUE result_array) {
99
+ rb_ary_push(result_array, value);
100
+
101
+ return ST_CONTINUE;
102
+ }
103
+
104
+ /*
105
+ * call-seq:
106
+ * multi.requests => [#&lt;Curl::Easy...&gt;, ...]
107
+ *
108
+ * Returns an array containing all the active requests on this Curl::Multi object.
109
+ */
110
+ static VALUE ruby_curl_multi_requests(VALUE self) {
111
+ ruby_curl_multi *rbcm;
112
+
113
+ Data_Get_Struct(self, ruby_curl_multi, rbcm);
114
+
115
+ VALUE result_array = rb_ary_new();
116
+
117
+ // iterate over the requests hash, and stuff references into the array.
118
+ rb_hash_foreach( rbcm->requests, ruby_curl_multi_requests_callback, result_array );
119
+
120
+ return result_array;
121
+ }
122
+
123
+ /*
124
+ * call-seq:
125
+ * multi.idle? => true or false
126
+ *
127
+ * Returns whether or not this Curl::Multi handle is processing any requests. E.g. this returns
128
+ * true when multi.requests.length == 0.
129
+ */
130
+ static VALUE ruby_curl_multi_idle(VALUE self) {
131
+ ruby_curl_multi *rbcm;
132
+
133
+ Data_Get_Struct(self, ruby_curl_multi, rbcm);
134
+
135
+ if ( FIX2INT( rb_funcall(rbcm->requests, rb_intern("length"), 0) ) == 0 ) {
136
+ return Qtrue;
137
+ } else {
138
+ return Qfalse;
139
+ }
140
+ }
141
+
96
142
  /*
97
143
  * call-seq:
98
144
  * multi = Curl::Multi.new
@@ -141,7 +187,7 @@ static VALUE ruby_curl_multi_pipeline(VALUE self, VALUE onoff) {
141
187
  *
142
188
  * Add an easy handle to the multi stack
143
189
  */
144
- static VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
190
+ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
145
191
  CURLMcode mcode;
146
192
  ruby_curl_easy *rbce;
147
193
  ruby_curl_multi *rbcm;
@@ -185,11 +231,11 @@ static VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
185
231
  * # sometime later
186
232
  * multi.remove(easy)
187
233
  *
188
- * Remove an easy handle from a multi stack
234
+ * Remove an easy handle from a multi stack.
189
235
  *
190
236
  * Will raise an exception if the easy handle is not found
191
237
  */
192
- static VALUE ruby_curl_multi_remove(VALUE self, VALUE easy) {
238
+ VALUE ruby_curl_multi_remove(VALUE self, VALUE easy) {
193
239
  ruby_curl_multi *rbcm;
194
240
 
195
241
  Data_Get_Struct(self, ruby_curl_multi, rbcm);
@@ -226,6 +272,30 @@ static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy) {
226
272
  }
227
273
  }
228
274
 
275
+ // Hash#foreach callback for ruby_curl_multi_cancel
276
+ static int ruby_curl_multi_cancel_callback(VALUE key, VALUE value, ruby_curl_multi *rbcm) {
277
+ rb_curl_multi_remove(rbcm, value);
278
+
279
+ return ST_CONTINUE;
280
+ }
281
+
282
+ /*
283
+ * call-seq:
284
+ * multi.cancel!
285
+ *
286
+ * Cancels all requests currently being made on this Curl::Multi handle.
287
+ */
288
+ static VALUE ruby_curl_multi_cancel(VALUE self) {
289
+ ruby_curl_multi *rbcm;
290
+
291
+ Data_Get_Struct(self, ruby_curl_multi, rbcm);
292
+
293
+ rb_hash_foreach( rbcm->requests, ruby_curl_multi_cancel_callback, (VALUE)rbcm );
294
+
295
+ // for chaining
296
+ return self;
297
+ }
298
+
229
299
  static void rb_curl_multi_read_info(VALUE self, CURLM *multi_handle) {
230
300
  int msgs_left, result;
231
301
  CURLMsg *msg;
@@ -247,6 +317,7 @@ static void rb_curl_multi_read_info(VALUE self, CURLM *multi_handle) {
247
317
  if (ecode != 0) {
248
318
  raise_curl_easy_error_exception(ecode);
249
319
  }
320
+ rbce->last_result = result; // save the last easy result code
250
321
  ruby_curl_multi_remove( self, rbce->self );
251
322
 
252
323
  if (rbce->complete_proc != Qnil) {
@@ -308,7 +379,7 @@ static void rb_curl_multi_run(VALUE self, CURLM *multi_handle, int *still_runnin
308
379
  *
309
380
  * Run multi handles, looping selecting when data can be transfered
310
381
  */
311
- static VALUE ruby_curl_multi_perform(VALUE self) {
382
+ VALUE ruby_curl_multi_perform(VALUE self) {
312
383
  CURLMcode mcode;
313
384
  ruby_curl_multi *rbcm;
314
385
  int maxfd, rc;
@@ -368,7 +439,7 @@ static VALUE ruby_curl_multi_perform(VALUE self) {
368
439
 
369
440
  }
370
441
 
371
- return Qnil;
442
+ return Qtrue;
372
443
  }
373
444
 
374
445
  /* =================== INIT LIB =====================*/
@@ -379,11 +450,16 @@ void init_curb_multi() {
379
450
 
380
451
  /* Class methods */
381
452
  rb_define_singleton_method(cCurlMulti, "new", ruby_curl_multi_new, 0);
382
-
453
+
454
+ /* "Attributes" */
455
+ rb_define_method(cCurlMulti, "requests", ruby_curl_multi_requests, 0);
456
+ rb_define_method(cCurlMulti, "idle?", ruby_curl_multi_idle, 0);
457
+
383
458
  /* Instnace methods */
384
459
  rb_define_method(cCurlMulti, "max_connects=", ruby_curl_multi_max_connects, 1);
385
460
  rb_define_method(cCurlMulti, "pipeline=", ruby_curl_multi_pipeline, 1);
386
461
  rb_define_method(cCurlMulti, "add", ruby_curl_multi_add, 1);
387
462
  rb_define_method(cCurlMulti, "remove", ruby_curl_multi_remove, 1);
463
+ rb_define_method(cCurlMulti, "cancel!", ruby_curl_multi_cancel, 0);
388
464
  rb_define_method(cCurlMulti, "perform", ruby_curl_multi_perform, 0);
389
465
  }
data/ext/curb_multi.h CHANGED
@@ -20,6 +20,10 @@ typedef struct {
20
20
 
21
21
  extern VALUE cCurlMulti;
22
22
  void init_curb_multi();
23
+ VALUE ruby_curl_multi_new(VALUE klass);
24
+ VALUE ruby_curl_multi_perform(VALUE self);
25
+ VALUE ruby_curl_multi_add(VALUE self, VALUE easy);
26
+ VALUE ruby_curl_multi_remove(VALUE self, VALUE easy);
23
27
 
24
28
 
25
29
  #endif
data/ext/curb_upload.c CHANGED
@@ -6,6 +6,10 @@
6
6
  extern VALUE mCurl;
7
7
  VALUE cCurlUpload;
8
8
 
9
+ #ifdef RDOC_NEVER_DEFINED
10
+ mCurl = rb_define_module("Curl");
11
+ #endif
12
+
9
13
  static void curl_upload_mark(ruby_curl_upload *rbcu) {
10
14
  if (rbcu->stream) rb_gc_mark(rbcu->stream);
11
15
  }
@@ -13,6 +17,10 @@ static void curl_upload_free(ruby_curl_upload *rbcu) {
13
17
  free(rbcu);
14
18
  }
15
19
 
20
+ /*
21
+ * call-seq:
22
+ * internal class for sending large file uploads
23
+ */
16
24
  VALUE ruby_curl_upload_new(VALUE klass) {
17
25
  VALUE upload;
18
26
  ruby_curl_upload *rbcu = ALLOC(ruby_curl_upload);
@@ -22,23 +30,39 @@ VALUE ruby_curl_upload_new(VALUE klass) {
22
30
  return upload;
23
31
  }
24
32
 
33
+ /*
34
+ * call-seq:
35
+ * internal class for sending large file uploads
36
+ */
25
37
  VALUE ruby_curl_upload_stream_set(VALUE self, VALUE stream) {
26
38
  ruby_curl_upload *rbcu;
27
39
  Data_Get_Struct(self, ruby_curl_upload, rbcu);
28
40
  rbcu->stream = stream;
29
41
  return stream;
30
42
  }
43
+ /*
44
+ * call-seq:
45
+ * internal class for sending large file uploads
46
+ */
31
47
  VALUE ruby_curl_upload_stream_get(VALUE self) {
32
48
  ruby_curl_upload *rbcu;
33
49
  Data_Get_Struct(self, ruby_curl_upload, rbcu);
34
50
  return rbcu->stream;
35
51
  }
52
+ /*
53
+ * call-seq:
54
+ * internal class for sending large file uploads
55
+ */
36
56
  VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset) {
37
57
  ruby_curl_upload *rbcu;
38
58
  Data_Get_Struct(self, ruby_curl_upload, rbcu);
39
59
  rbcu->offset = FIX2INT(offset);
40
60
  return offset;
41
61
  }
62
+ /*
63
+ * call-seq:
64
+ * internal class for sending large file uploads
65
+ */
42
66
  VALUE ruby_curl_upload_offset_get(VALUE self) {
43
67
  ruby_curl_upload *rbcu;
44
68
  Data_Get_Struct(self, ruby_curl_upload, rbcu);
data/lib/curb.rb CHANGED
@@ -75,11 +75,51 @@ module Curl
75
75
  easy_options.each do|k,v|
76
76
  c.send("#{k}=",v)
77
77
  end
78
- c.on_complete {|curl| blk.call curl }
78
+ c.on_complete {|curl| blk.call curl } if blk
79
79
  m.add(c)
80
80
  end
81
81
  m.perform
82
82
  end
83
+
84
+ # call-seq:
85
+ #
86
+ # Curl::Multi.post([{:url => 'url1', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}},
87
+ # {:url => 'url2', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}},
88
+ # {:url => 'url3', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}}],
89
+ # { :follow_location => true, :multipart_form_post => true },
90
+ # {:pipeline => true }) do|easy|
91
+ # easy_handle_on_request_complete
92
+ # end
93
+ #
94
+ # Blocking call to POST multiple form's in parallel.
95
+ #
96
+ # urls_with_config: is a hash of url's pointing to the postfields to send
97
+ # easy_options: are a set of common options to set on all easy handles
98
+ # multi_options: options to set on the Curl::Multi handle
99
+ #
100
+ def post(urls_with_config, easy_options, multi_options, &blk)
101
+ m = Curl::Multi.new
102
+ # configure the multi handle
103
+ multi_options.each do|k,v|
104
+ m.send("#{k}=", v)
105
+ end
106
+
107
+ urls_with_config.each do|conf|
108
+ c = conf.dup # avoid being destructive to input
109
+ url = c.delete(:url)
110
+ fields = c.delete(:post_fields)
111
+ easy = Curl::Easy.new(url)
112
+ # set the post post using the url fields
113
+ easy.post_body = fields.map{|f,k| "#{easy.escape(f)}=#{easy.escape(k)}"}.join('&')
114
+ # configure the easy handle
115
+ easy_options.each do|k,v|
116
+ easy.send("#{k}=",v)
117
+ end
118
+ easy.on_complete {|curl| blk.call curl } if blk
119
+ m.add(easy)
120
+ end
121
+ m.perform
122
+ end
83
123
  end
84
124
  end
85
125
  end
data/tests/helper.rb CHANGED
@@ -21,7 +21,7 @@ require 'webrick'
21
21
  # or to test with multiple threads set it to false
22
22
  # this is important since, some code paths will change depending
23
23
  # on the presence of multiple threads
24
- TEST_SINGLE_THREADED=true
24
+ TEST_SINGLE_THREADED=false
25
25
 
26
26
  # keep webrick quiet
27
27
  class ::WEBrick::HTTPServer
@@ -100,6 +100,50 @@ class TestCurbCurlMulti < Test::Unit::TestCase
100
100
  m = nil
101
101
 
102
102
  end
103
+
104
+ def test_idle_check
105
+ m = Curl::Multi.new
106
+ e = Curl::Easy.new($TEST_URL)
107
+
108
+ assert(m.idle?, 'A new Curl::Multi handle should be idle')
109
+
110
+ m.add(e)
111
+
112
+ assert((not m.idle?), 'A Curl::Multi handle with a request should not be idle')
113
+
114
+ m.perform
115
+
116
+ assert(m.idle?, 'A Curl::Multi handle should be idle after performing its requests')
117
+ end
118
+
119
+ def test_requests
120
+ m = Curl::Multi.new
121
+
122
+ assert_equal([], m.requests, 'A new Curl::Multi handle should have no requests')
123
+
124
+ 10.times do
125
+ m.add(Curl::Easy.new($TEST_URL))
126
+ end
127
+
128
+ assert_equal(10, m.requests.length, 'multi.requests should contain all the active requests')
129
+
130
+ m.perform
131
+
132
+ assert_equal([], m.requests, 'A new Curl::Multi handle should have no requests after a perform')
133
+ end
134
+
135
+ def test_cancel
136
+ m = Curl::Multi.new
137
+ m.cancel! # shouldn't raise anything
138
+
139
+ 10.times do
140
+ m.add(Curl::Easy.new($TEST_URL))
141
+ end
142
+
143
+ m.cancel!
144
+
145
+ assert_equal([], m.requests, 'A new Curl::Multi handle should have no requests after being canceled')
146
+ end
103
147
 
104
148
  def test_with_success
105
149
  c1 = Curl::Easy.new($TEST_URL)
@@ -260,6 +304,23 @@ class TestCurbCurlMulti < Test::Unit::TestCase
260
304
  end
261
305
  end
262
306
 
307
+ def test_multi_easy_post_01
308
+ urls = [
309
+ { :url => TestServlet.url + '?q=1', :post_fields => {'field1' => 'value1', 'k' => 'j'}},
310
+ { :url => TestServlet.url + '?q=2', :post_fields => {'field2' => 'value2', 'foo' => 'bar', 'i' => 'j' }},
311
+ { :url => TestServlet.url + '?q=3', :post_fields => {'field3' => 'value3', 'field4' => 'value4'}}
312
+ ]
313
+ Curl::Multi.post(urls, {:follow_location => true, :multipart_form_post => true}, {:pipeline => true}) do|easy|
314
+ str = easy.body_str
315
+ assert_match /POST/, str
316
+ fields = {}
317
+ str.gsub(/POST\n/,'').split('&').map{|sv| k, v = sv.split('='); fields[k] = v }
318
+ expected = urls.find{|s| s[:url] == easy.last_effective_url }
319
+ assert_equal expected[:post_fields], fields
320
+ #puts "#{easy.last_effective_url} #{fields.inspect}"
321
+ end
322
+ end
323
+
263
324
  include TestServerMethods
264
325
 
265
326
  def setup
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4.0
4
+ version: 0.4.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ross Bamford
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-07-12 00:00:00 -04:00
13
+ date: 2009-07-21 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -32,19 +32,19 @@ files:
32
32
  - lib/curb.rb
33
33
  - lib/curl.rb
34
34
  - ext/curb.c
35
- - ext/curb_postfield.c
36
- - ext/curb_multi.c
37
- - ext/curb_errors.c
38
35
  - ext/curb_easy.c
36
+ - ext/curb_errors.c
37
+ - ext/curb_multi.c
38
+ - ext/curb_postfield.c
39
39
  - ext/curb_upload.c
40
+ - ext/curb.h
41
+ - ext/curb_config.h
40
42
  - ext/curb_easy.h
41
43
  - ext/curb_errors.h
42
- - ext/curb_upload.h
43
44
  - ext/curb_macros.h
44
- - ext/curb.h
45
- - ext/curb_postfield.h
46
- - ext/curb_config.h
47
45
  - ext/curb_multi.h
46
+ - ext/curb_postfield.h
47
+ - ext/curb_upload.h
48
48
  has_rdoc: true
49
49
  homepage: http://curb.rubyforge.org/
50
50
  licenses: []
@@ -76,14 +76,14 @@ signing_key:
76
76
  specification_version: 3
77
77
  summary: Ruby libcurl bindings
78
78
  test_files:
79
- - tests/tc_curl_multi.rb
80
- - tests/tc_curl_postfield.rb
79
+ - tests/alltests.rb
81
80
  - tests/bug_curb_easy_blocks_ruby_threads.rb
82
- - tests/unittests.rb
83
- - tests/bug_require_last_or_segfault.rb
84
81
  - tests/bug_instance_post_differs_from_class_post.rb
85
- - tests/tc_curl_download.rb
86
- - tests/alltests.rb
82
+ - tests/bug_require_last_or_segfault.rb
87
83
  - tests/helper.rb
88
- - tests/tc_curl_easy.rb
89
84
  - tests/require_last_or_segfault_script.rb
85
+ - tests/tc_curl_download.rb
86
+ - tests/tc_curl_easy.rb
87
+ - tests/tc_curl_multi.rb
88
+ - tests/tc_curl_postfield.rb
89
+ - tests/unittests.rb