curb 0.8.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/README CHANGED
@@ -56,6 +56,19 @@ Curb provides two classes:
56
56
  + Curl::Easy - simple API, for day-to-day tasks.
57
57
  + Curl::Multi - more advanced API, for operating on multiple URLs simultaneously.
58
58
 
59
+ ### Super simple API (less typing)
60
+
61
+ http = Curl.get("http://www.google.com/")
62
+ puts http.body_str
63
+
64
+ http = Curl.post("http://www.google.com/", {:foo => "bar"})
65
+ puts http.body_str
66
+
67
+ http = Curl.get("http://www.google.com/") do|http|
68
+ http.headers['Cookie'] = 'foo=1;bar=2'
69
+ end
70
+ puts http.body_str
71
+
59
72
  ### Simple fetch via HTTP:
60
73
 
61
74
  c = Curl::Easy.perform("http://www.google.co.uk")
data/ext/curb.c CHANGED
@@ -424,8 +424,12 @@ void Init_curb_core() {
424
424
  CURB_DEFINE(CURLOPT_FAILONERROR);
425
425
  #endif
426
426
  CURB_DEFINE(CURLOPT_URL);
427
+ #if HAVE_CURLOPT_PROTOCOLS
427
428
  CURB_DEFINE(CURLOPT_PROTOCOLS);
429
+ #endif
430
+ #if HAVE_CURLOPT_REDIR_PROTOCOLS
428
431
  CURB_DEFINE(CURLOPT_REDIR_PROTOCOLS);
432
+ #endif
429
433
  CURB_DEFINE(CURLOPT_PROXY);
430
434
  CURB_DEFINE(CURLOPT_PROXYPORT);
431
435
  #if HAVE_CURLOPT_PROXYTYPE
data/ext/curb.h CHANGED
@@ -20,11 +20,11 @@
20
20
  #include "curb_macros.h"
21
21
 
22
22
  // These should be managed from the Rake 'release' task.
23
- #define CURB_VERSION "0.8.0"
24
- #define CURB_VER_NUM 800
23
+ #define CURB_VERSION "0.8.4"
24
+ #define CURB_VER_NUM 804
25
25
  #define CURB_VER_MAJ 0
26
26
  #define CURB_VER_MIN 8
27
- #define CURB_VER_MIC 0
27
+ #define CURB_VER_MIC 4
28
28
  #define CURB_VER_PATCH 0
29
29
 
30
30
 
data/ext/curb_easy.c CHANGED
@@ -115,6 +115,30 @@ static size_t proc_data_handler(char *stream,
115
115
  }
116
116
  }
117
117
 
118
+ static size_t proc_data_handler_body(char *stream,
119
+ size_t size,
120
+ size_t nmemb,
121
+ ruby_curl_easy *rbce)
122
+ {
123
+ size_t ret;
124
+ rbce->callback_active = 1;
125
+ ret = proc_data_handler(stream, size, nmemb, rb_easy_get("body_proc"));
126
+ rbce->callback_active = 0;
127
+ return ret;
128
+ }
129
+ static size_t proc_data_handler_header(char *stream,
130
+ size_t size,
131
+ size_t nmemb,
132
+ ruby_curl_easy *rbce)
133
+ {
134
+ size_t ret;
135
+ rbce->callback_active = 1;
136
+ ret = proc_data_handler(stream, size, nmemb, rb_easy_get("header_proc"));
137
+ rbce->callback_active = 0;
138
+ return ret;
139
+ }
140
+
141
+
118
142
  static VALUE call_progress_handler(VALUE ary) {
119
143
  return rb_funcall(rb_ary_entry(ary, 0), idCall, 4,
120
144
  rb_ary_entry(ary, 1), // rb_float_new(dltotal),
@@ -157,13 +181,14 @@ static int proc_debug_handler(CURL *curl,
157
181
  char *data,
158
182
  size_t data_len,
159
183
  VALUE proc) {
160
- VALUE procret;
161
184
  VALUE callargs = rb_ary_new2(3);
162
185
  rb_ary_store(callargs, 0, proc);
163
186
  rb_ary_store(callargs, 1, INT2FIX(type));
164
187
  rb_ary_store(callargs, 2, rb_str_new(data, data_len));
165
188
  rb_rescue(call_debug_handler, callargs, callback_exception, Qnil);
166
- // XXX: no way to indicate to libcurl that we should break out given an exception in the on_debug handler... this means exceptions will be swallowed
189
+ /* no way to indicate to libcurl that we should break out given an exception in the on_debug handler...
190
+ * this means exceptions will be swallowed
191
+ */
167
192
  //rb_funcall(proc, idCall, 2, INT2FIX(type), rb_str_new(data, data_len));
168
193
  return 0;
169
194
  }
@@ -234,6 +259,7 @@ static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
234
259
  rbce->multipart_form_post = 0;
235
260
  rbce->enable_cookies = 0;
236
261
  rbce->ignore_content_length = 0;
262
+ rbce->callback_active = 0;
237
263
  }
238
264
 
239
265
  /*
@@ -320,6 +346,10 @@ static VALUE ruby_curl_easy_close(VALUE self) {
320
346
 
321
347
  Data_Get_Struct(self, ruby_curl_easy, rbce);
322
348
 
349
+ if (rbce->callback_active) {
350
+ rb_raise(rb_eRuntimeError, "Cannot close an active curl handle within a callback");
351
+ }
352
+
323
353
  ruby_curl_easy_free(rbce);
324
354
 
325
355
  /* reinit the handle */
@@ -358,6 +388,11 @@ static VALUE ruby_curl_easy_reset(VALUE self) {
358
388
  ruby_curl_easy *rbce;
359
389
  VALUE opts_dup;
360
390
  Data_Get_Struct(self, ruby_curl_easy, rbce);
391
+
392
+ if (rbce->callback_active) {
393
+ rb_raise(rb_eRuntimeError, "Cannot close an active curl handle within a callback");
394
+ }
395
+
361
396
  opts_dup = rb_funcall(rbce->opts, rb_intern("dup"), 0);
362
397
 
363
398
  curl_easy_reset(rbce->curl);
@@ -668,8 +703,8 @@ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
668
703
  curl = rbce->curl;
669
704
 
670
705
  if ( post_body == Qnil ) {
671
- //rbce->postdata_buffer = Qnil;
672
706
  rb_easy_del("postdata_buffer");
707
+ curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
673
708
 
674
709
  } else {
675
710
  if (rb_type(post_body) == T_STRING) {
@@ -1443,17 +1478,6 @@ static VALUE ruby_curl_easy_use_netrc_q(VALUE self) {
1443
1478
  CURB_BOOLEAN_GETTER(ruby_curl_easy, use_netrc);
1444
1479
  }
1445
1480
 
1446
- /*
1447
- * call-seq:
1448
- * easy.follow_location = boolean => boolean
1449
- *
1450
- * Configure whether this Curl instance will follow Location: headers
1451
- * in HTTP responses. Redirects will only be followed to the extent
1452
- * specified by +max_redirects+.
1453
- */
1454
- static VALUE ruby_curl_easy_follow_location_set(VALUE self, VALUE follow_location) {
1455
- CURB_BOOLEAN_SETTER(ruby_curl_easy, follow_location);
1456
- }
1457
1481
  /*
1458
1482
  * call-seq:
1459
1483
  *
@@ -1872,7 +1896,7 @@ static VALUE cb_each_ftp_command(VALUE ftp_command, VALUE wrap) {
1872
1896
  *
1873
1897
  * Always returns Qtrue, rb_raise on error.
1874
1898
  */
1875
- VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce ) {
1899
+ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
1876
1900
  // TODO this could do with a bit of refactoring...
1877
1901
  CURL *curl;
1878
1902
  VALUE url, _url = rb_easy_get("url");
@@ -1934,8 +1958,8 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce ) {
1934
1958
 
1935
1959
  // body/header procs
1936
1960
  if (!rb_easy_nil("body_proc")) {
1937
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&proc_data_handler);
1938
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, rb_easy_get("body_proc"));//rbce->body_proc);
1961
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&proc_data_handler_body);
1962
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, rbce);
1939
1963
  /* clear out the body_data if it was set */
1940
1964
  rb_easy_del("body_data");
1941
1965
  } else {
@@ -1945,8 +1969,8 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce ) {
1945
1969
  }
1946
1970
 
1947
1971
  if (!rb_easy_nil("header_proc")) {
1948
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&proc_data_handler);
1949
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, rb_easy_get("header_proc"));
1972
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&proc_data_handler_header);
1973
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, rbce);
1950
1974
  /* clear out the header_data if it was set */
1951
1975
  rb_easy_del("header_data");
1952
1976
  } else {
@@ -2202,27 +2226,6 @@ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce ) {
2202
2226
  return Qnil;
2203
2227
  }
2204
2228
 
2205
- /*
2206
- * call-seq:
2207
- * easy.http_get => true
2208
- *
2209
- * GET the currently configured URL using the current options set for
2210
- * this Curl::Easy instance. This method always returns true, or raises
2211
- * an exception (defined under Curl::Err) on error.
2212
- */
2213
- static VALUE ruby_curl_easy_perform_get(VALUE self) {
2214
- ruby_curl_easy *rbce;
2215
- CURL *curl;
2216
-
2217
- Data_Get_Struct(self, ruby_curl_easy, rbce);
2218
- curl = rbce->curl;
2219
-
2220
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2221
- curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
2222
-
2223
- return rb_funcall(self, rb_intern("perform"), 0);
2224
- }
2225
-
2226
2229
  /*
2227
2230
  * Common implementation of easy.http(verb) and easy.http_delete
2228
2231
  */
@@ -2243,18 +2246,6 @@ static VALUE ruby_curl_easy_perform_verb_str(VALUE self, const char *verb) {
2243
2246
  return retval;
2244
2247
  }
2245
2248
 
2246
- /*
2247
- * call-seq:
2248
- * easy.http_delete
2249
- *
2250
- * DELETE the currently configured URL using the current options set for
2251
- * this Curl::Easy instance. This method always returns true, or raises
2252
- * an exception (defined under Curl::Err) on error.
2253
- */
2254
- static VALUE ruby_curl_easy_perform_delete(VALUE self) {
2255
- return ruby_curl_easy_perform_verb_str(self, "DELETE");
2256
- }
2257
-
2258
2249
  /*
2259
2250
  * call-seq:
2260
2251
  * easy.http(verb)
@@ -2367,52 +2358,6 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
2367
2358
  }
2368
2359
  }
2369
2360
 
2370
- /*
2371
- * call-seq:
2372
- * easy.http_head => true
2373
- *
2374
- * Request headers from the currently configured URL using the HEAD
2375
- * method and current options set for this Curl::Easy instance. This
2376
- * method always returns true, or raises an exception (defined under
2377
- * Curl::Err) on error.
2378
- *
2379
- */
2380
- static VALUE ruby_curl_easy_perform_head(VALUE self) {
2381
- ruby_curl_easy *rbce;
2382
- CURL *curl;
2383
- VALUE ret;
2384
-
2385
- Data_Get_Struct(self, ruby_curl_easy, rbce);
2386
- curl = rbce->curl;
2387
-
2388
- curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
2389
-
2390
- ret = rb_funcall(self, rb_intern("perform"), 0);
2391
-
2392
- curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
2393
- return ret;
2394
- }
2395
-
2396
- /*
2397
- *call-seq:
2398
- * easy = Curl::Easy.new("url") do|c|
2399
- * c.head = true
2400
- * end
2401
- * easy.perform
2402
- */
2403
- static VALUE ruby_curl_easy_set_head_option(VALUE self, VALUE onoff) {
2404
- ruby_curl_easy *rbce;
2405
-
2406
- Data_Get_Struct(self, ruby_curl_easy, rbce);
2407
-
2408
- if (onoff == Qtrue) {
2409
- curl_easy_setopt(rbce->curl, CURLOPT_NOBODY, 1);
2410
- } else {
2411
- curl_easy_setopt(rbce->curl, CURLOPT_NOBODY, 0);
2412
- }
2413
-
2414
- return onoff;
2415
- }
2416
2361
  /*
2417
2362
  * call-seq:
2418
2363
  * easy.http_put(data) => true
@@ -2720,6 +2665,36 @@ static VALUE ruby_curl_easy_redirect_count_get(VALUE self) {
2720
2665
 
2721
2666
  }
2722
2667
 
2668
+ /*
2669
+ * call-seq:
2670
+ * easy.redirect_url => "http://some.url" or nil
2671
+ *
2672
+ * Retrieve the URL a redirect would take you to if you
2673
+ * would enable CURLOPT_FOLLOWLOCATION.
2674
+ *
2675
+ * Requires libcurl 7.18.2 or higher, otherwise -1 is always returned.
2676
+ */
2677
+ static VALUE ruby_curl_easy_redirect_url_get(VALUE self) {
2678
+ #ifdef HAVE_CURLINFO_REDIRECT_URL
2679
+ ruby_curl_easy *rbce;
2680
+ char* url;
2681
+
2682
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2683
+ curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_URL, &url);
2684
+
2685
+ if (url && url[0]) { // curl returns empty string if none
2686
+ return rb_str_new2(url);
2687
+ } else {
2688
+ return Qnil;
2689
+ }
2690
+ #else
2691
+ rb_warn("Installed libcurl is too old to support redirect_url");
2692
+ return INT2FIX(-1);
2693
+ #endif
2694
+ }
2695
+
2696
+
2697
+
2723
2698
  /*
2724
2699
  * call-seq:
2725
2700
  * easy.uploaded_bytes => float
@@ -3070,11 +3045,10 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3070
3045
  VALUE verbose = val;
3071
3046
  CURB_BOOLEAN_SETTER(ruby_curl_easy, verbose);
3072
3047
  } break;
3073
- case CURLOPT_HEADER:
3074
- case CURLOPT_NOPROGRESS:
3075
- case CURLOPT_NOSIGNAL:
3076
- curl_easy_setopt(rbce->curl, CURLOPT_NOSIGNAL, val == Qtrue ? 1 : 0);
3077
- break;
3048
+ case CURLOPT_FOLLOWLOCATION: {
3049
+ VALUE follow_location = val;
3050
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, follow_location);
3051
+ } break;
3078
3052
  /* TODO: CALLBACK OPTIONS */
3079
3053
  /* TODO: ERROR OPTIONS */
3080
3054
  /* NETWORK OPTIONS */
@@ -3096,6 +3070,22 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3096
3070
  VALUE interface_hm = val;
3097
3071
  CURB_OBJECT_HSETTER(ruby_curl_easy, interface_hm);
3098
3072
  } break;
3073
+ case CURLOPT_HEADER:
3074
+ case CURLOPT_NOPROGRESS:
3075
+ case CURLOPT_NOSIGNAL:
3076
+ case CURLOPT_HTTPGET:
3077
+ case CURLOPT_NOBODY: {
3078
+ int type = rb_type(val);
3079
+ VALUE value;
3080
+ if (type == T_TRUE) {
3081
+ value = rb_int_new(1);
3082
+ } else if (type == T_FALSE) {
3083
+ value = rb_int_new(0);
3084
+ } else {
3085
+ value = rb_funcall(val, rb_intern("to_i"), 0);
3086
+ }
3087
+ curl_easy_setopt(rbce->curl, option, FIX2INT(value));
3088
+ } break;
3099
3089
  case CURLOPT_USERPWD: {
3100
3090
  VALUE userpwd = val;
3101
3091
  CURB_OBJECT_HSETTER(ruby_curl_easy, userpwd);
@@ -3116,7 +3106,12 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3116
3106
  VALUE cookiejar = val;
3117
3107
  CURB_OBJECT_HSETTER(ruby_curl_easy, cookiejar);
3118
3108
  } break;
3119
-
3109
+ case CURLOPT_RESUME_FROM: {
3110
+ curl_easy_setopt(rbce->curl, CURLOPT_RESUME_FROM, FIX2LONG(val));
3111
+ } break;
3112
+ case CURLOPT_FAILONERROR: {
3113
+ curl_easy_setopt(rbce->curl, CURLOPT_FAILONERROR, FIX2LONG(val));
3114
+ } break;
3120
3115
  default:
3121
3116
  break;
3122
3117
  }
@@ -3326,7 +3321,6 @@ void init_curb_easy() {
3326
3321
  rb_define_method(cCurlEasy, "header_in_body?", ruby_curl_easy_header_in_body_q, 0);
3327
3322
  rb_define_method(cCurlEasy, "use_netrc=", ruby_curl_easy_use_netrc_set, 1);
3328
3323
  rb_define_method(cCurlEasy, "use_netrc?", ruby_curl_easy_use_netrc_q, 0);
3329
- rb_define_method(cCurlEasy, "follow_location=", ruby_curl_easy_follow_location_set, 1);
3330
3324
  rb_define_method(cCurlEasy, "follow_location?", ruby_curl_easy_follow_location_q, 0);
3331
3325
  rb_define_method(cCurlEasy, "autoreferer=", ruby_curl_easy_autoreferer_set, 1);
3332
3326
  rb_define_method(cCurlEasy, "unrestricted_auth=", ruby_curl_easy_unrestricted_auth_set, 1);
@@ -3353,12 +3347,8 @@ void init_curb_easy() {
3353
3347
  rb_define_method(cCurlEasy, "on_complete", ruby_curl_easy_on_complete_set, -1);
3354
3348
 
3355
3349
  rb_define_method(cCurlEasy, "http", ruby_curl_easy_perform_verb, 1);
3356
- rb_define_method(cCurlEasy, "http_delete", ruby_curl_easy_perform_delete, 0);
3357
- rb_define_method(cCurlEasy, "http_get", ruby_curl_easy_perform_get, 0);
3358
3350
  rb_define_method(cCurlEasy, "http_post", ruby_curl_easy_perform_post, -1);
3359
- rb_define_method(cCurlEasy, "http_head", ruby_curl_easy_perform_head, 0);
3360
3351
  rb_define_method(cCurlEasy, "http_put", ruby_curl_easy_perform_put, 1);
3361
- rb_define_method(cCurlEasy, "head=", ruby_curl_easy_set_head_option, 1);
3362
3352
 
3363
3353
  /* Post-perform info methods */
3364
3354
  rb_define_method(cCurlEasy, "body_str", ruby_curl_easy_body_str_get, 0);
@@ -3378,6 +3368,7 @@ void init_curb_easy() {
3378
3368
  rb_define_method(cCurlEasy, "start_transfer_time", ruby_curl_easy_start_transfer_time_get, 0);
3379
3369
  rb_define_method(cCurlEasy, "redirect_time", ruby_curl_easy_redirect_time_get, 0);
3380
3370
  rb_define_method(cCurlEasy, "redirect_count", ruby_curl_easy_redirect_count_get, 0);
3371
+ rb_define_method(cCurlEasy, "redirect_url", ruby_curl_easy_redirect_url_get, 0);
3381
3372
  rb_define_method(cCurlEasy, "downloaded_bytes", ruby_curl_easy_downloaded_bytes_get, 0);
3382
3373
  rb_define_method(cCurlEasy, "uploaded_bytes", ruby_curl_easy_uploaded_bytes_get, 0);
3383
3374
  rb_define_method(cCurlEasy, "download_speed", ruby_curl_easy_download_speed_get, 0);
data/ext/curb_easy.h CHANGED
@@ -71,6 +71,8 @@ typedef struct {
71
71
  char multipart_form_post;
72
72
  char enable_cookies;
73
73
  char ignore_content_length;
74
+ char callback_active;
75
+
74
76
  struct curl_slist *curl_headers;
75
77
  struct curl_slist *curl_ftp_commands;
76
78
 
data/ext/curb_errors.c CHANGED
@@ -459,7 +459,8 @@ VALUE rb_curl_easy_error(CURLcode code) {
459
459
  /* rb_raise an approriate exception for the supplied CURLcode */
460
460
  void raise_curl_easy_error_exception(CURLcode code) {
461
461
  VALUE obj = rb_curl_easy_error(code);
462
- rb_raise(rb_ary_entry(obj,0), RSTRING_PTR(rb_ary_entry(obj,1)));
462
+ VALUE exmsg = rb_ary_entry(obj,1);
463
+ rb_raise(rb_ary_entry(obj,0), "CURLError: %s", StringValueCStr(exmsg));
463
464
  }
464
465
  VALUE rb_curl_multi_error(CURLMcode code) {
465
466
  VALUE exclz;
@@ -509,7 +510,8 @@ VALUE rb_curl_multi_error(CURLMcode code) {
509
510
  }
510
511
  void raise_curl_multi_error_exception(CURLMcode code) {
511
512
  VALUE obj = rb_curl_multi_error(code);
512
- rb_raise(rb_ary_entry(obj,0), RSTRING_PTR(rb_ary_entry(obj,1)));
513
+ VALUE exmsg = rb_ary_entry(obj,1);
514
+ rb_raise(rb_ary_entry(obj,0), "CURLError: %s", StringValueCStr(exmsg));
513
515
  }
514
516
 
515
517
  void init_curb_errors() {
data/ext/curb_multi.c CHANGED
@@ -354,7 +354,9 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
354
354
 
355
355
  if (!rb_easy_nil("complete_proc")) {
356
356
  callargs = rb_ary_new3(2, rb_easy_get("complete_proc"), easy);
357
+ rbce->callback_active = 1;
357
358
  val = rb_rescue(call_status_handler1, callargs, callback_exception, Qnil);
359
+ rbce->callback_active = 0;
358
360
  //rb_funcall( rb_easy_get("complete_proc"), idCall, 1, easy );
359
361
  }
360
362
 
@@ -363,7 +365,9 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
363
365
  if (result != 0) {
364
366
  if (!rb_easy_nil("failure_proc")) {
365
367
  callargs = rb_ary_new3(3, rb_easy_get("failure_proc"), easy, rb_curl_easy_error(result));
368
+ rbce->callback_active = 1;
366
369
  val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
370
+ rbce->callback_active = 0;
367
371
  //rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
368
372
  }
369
373
  }
@@ -371,23 +375,31 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
371
375
  ((response_code >= 200 && response_code < 300) || response_code == 0)) {
372
376
  /* NOTE: we allow response_code == 0, in the case of non http requests e.g. reading from disk */
373
377
  callargs = rb_ary_new3(2, rb_easy_get("success_proc"), easy);
378
+ rbce->callback_active = 1;
374
379
  val = rb_rescue(call_status_handler1, callargs, callback_exception, Qnil);
380
+ rbce->callback_active = 0;
375
381
  //rb_funcall( rb_easy_get("success_proc"), idCall, 1, easy );
376
382
  }
377
383
  else if (!rb_easy_nil("redirect_proc") &&
378
384
  (response_code >= 300 && response_code < 400)) {
385
+ rbce->callback_active = 1;
379
386
  callargs = rb_ary_new3(3, rb_easy_get("redirect_proc"), easy, rb_curl_easy_error(result));
387
+ rbce->callback_active = 0;
380
388
  val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
381
389
  }
382
390
  else if (!rb_easy_nil("missing_proc") &&
383
391
  (response_code >= 400 && response_code < 500)) {
392
+ rbce->callback_active = 1;
384
393
  callargs = rb_ary_new3(3, rb_easy_get("missing_proc"), easy, rb_curl_easy_error(result));
394
+ rbce->callback_active = 0;
385
395
  val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
386
396
  }
387
397
  else if (!rb_easy_nil("failure_proc") &&
388
398
  (response_code >= 500 && response_code <= 999)) {
389
399
  callargs = rb_ary_new3(3, rb_easy_get("failure_proc"), easy, rb_curl_easy_error(result));
400
+ rbce->callback_active = 1;
390
401
  val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
402
+ rbce->callback_active = 0;
391
403
  //rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
392
404
  }
393
405
 
@@ -577,8 +589,10 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
577
589
 
578
590
  switch(rc) {
579
591
  case -1:
580
- rb_raise(rb_eRuntimeError, "select(): %s", strerror(errno));
581
- break;
592
+ if(errno != EINTR) {
593
+ rb_raise(rb_eRuntimeError, "select(): %s", strerror(errno));
594
+ break;
595
+ }
582
596
  case 0: /* timeout */
583
597
  default: /* action */
584
598
  rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
data/ext/extconf.rb CHANGED
@@ -119,6 +119,9 @@ have_constant "curle_again"
119
119
  have_constant "curle_ssl_crl_badfile"
120
120
  have_constant "curle_ssl_issuer_error"
121
121
 
122
+ # added in 7.18.2
123
+ have_constant "curlinfo_redirect_url"
124
+
122
125
  # username/password added in 7.19.1
123
126
  have_constant "curlopt_username"
124
127
  have_constant "curlopt_password"
data/lib/curb.rb CHANGED
@@ -1,3 +1 @@
1
- require 'curb_core'
2
- require 'curl/easy'
3
- require 'curl/multi'
1
+ require 'curl'
data/lib/curl/easy.rb CHANGED
@@ -1,6 +1,23 @@
1
1
  module Curl
2
2
  class Easy
3
3
 
4
+ alias post http_post
5
+ alias put http_put
6
+
7
+ #
8
+ # call-seq:
9
+ # easy.status => String
10
+ #
11
+ 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(' ')
19
+ end
20
+
4
21
  #
5
22
  # call-seq:
6
23
  # easy.set :sym|Fixnum, value
@@ -213,6 +230,72 @@ module Curl
213
230
  set :cookiejar, value
214
231
  end
215
232
 
233
+ #
234
+ # call-seq:
235
+ # easy = Curl::Easy.new("url") do|c|
236
+ # c.head = true
237
+ # end
238
+ # easy.perform
239
+ #
240
+ def head=(onoff)
241
+ set :nobody, onoff
242
+ end
243
+
244
+ #
245
+ # call-seq:
246
+ # easy.follow_location = boolean => boolean
247
+ #
248
+ # Configure whether this Curl instance will follow Location: headers
249
+ # in HTTP responses. Redirects will only be followed to the extent
250
+ # specified by +max_redirects+.
251
+ #
252
+ def follow_location=(onoff)
253
+ set :followlocation, onoff
254
+ end
255
+
256
+ #
257
+ # call-seq:
258
+ # easy.http_head => true
259
+ #
260
+ # Request headers from the currently configured URL using the HEAD
261
+ # method and current options set for this Curl::Easy instance. This
262
+ # method always returns true, or raises an exception (defined under
263
+ # Curl::Err) on error.
264
+ #
265
+ def http_head
266
+ set :nobody, true
267
+ ret = self.perform
268
+ set :nobody, false
269
+ ret
270
+ end
271
+
272
+ #
273
+ # call-seq:
274
+ # easy.http_get => true
275
+ #
276
+ # GET the currently configured URL using the current options set for
277
+ # this Curl::Easy instance. This method always returns true, or raises
278
+ # an exception (defined under Curl::Err) on error.
279
+ #
280
+ def http_get
281
+ set :httpget, true
282
+ http :GET
283
+ end
284
+ alias get http_get
285
+
286
+ #
287
+ # call-seq:
288
+ # easy.http_delete
289
+ #
290
+ # DELETE the currently configured URL using the current options set for
291
+ # this Curl::Easy instance. This method always returns true, or raises
292
+ # an exception (defined under Curl::Err) on error.
293
+ #
294
+ def http_delete
295
+ self.http :DELETE
296
+ end
297
+ alias delete http_delete
298
+
216
299
  class << self
217
300
 
218
301
  #
@@ -227,7 +310,7 @@ module Curl
227
310
  # the +http_get+ call.
228
311
  #
229
312
  def perform(*args)
230
- c = Curl::Easy.new *args
313
+ c = Curl::Easy.new(*args)
231
314
  yield c if block_given?
232
315
  c.perform
233
316
  c
@@ -244,7 +327,7 @@ module Curl
244
327
  # the +http_get+ call.
245
328
  #
246
329
  def http_get(*args)
247
- c = Curl::Easy.new *args
330
+ c = Curl::Easy.new(*args)
248
331
  yield c if block_given?
249
332
  c.http_get
250
333
  c
@@ -261,7 +344,7 @@ module Curl
261
344
  # the +http_head+ call.
262
345
  #
263
346
  def http_head(*args)
264
- c = Curl::Easy.new *args
347
+ c = Curl::Easy.new(*args)
265
348
  yield c if block_given?
266
349
  c.http_head
267
350
  c
@@ -300,7 +383,7 @@ module Curl
300
383
  url = args.shift
301
384
  c = Curl::Easy.new url
302
385
  yield c if block_given?
303
- c.http_post *args
386
+ c.http_post(*args)
304
387
  c
305
388
  end
306
389
 
@@ -315,7 +398,7 @@ module Curl
315
398
  # the +http_delete+ call.
316
399
  #
317
400
  def http_delete(*args)
318
- c = Curl::Easy.new *args
401
+ c = Curl::Easy.new(*args)
319
402
  yield c if block_given?
320
403
  c.http_delete
321
404
  c
data/lib/curl/multi.rb CHANGED
@@ -157,13 +157,17 @@ module Curl
157
157
  end
158
158
  end
159
159
 
160
- until urls_with_config.empty?
161
- m.perform do
160
+ if urls_with_config.empty?
161
+ m.perform
162
+ else
163
+ until urls_with_config.empty?
164
+ m.perform do
165
+ consume_free_handles.call
166
+ end
162
167
  consume_free_handles.call
163
168
  end
164
- consume_free_handles.call
169
+ free_handles = nil
165
170
  end
166
- free_handles = nil
167
171
  end
168
172
 
169
173
  # call-seq:
data/lib/curl.rb CHANGED
@@ -1 +1,62 @@
1
- require 'curb'
1
+ require 'curb_core'
2
+ require 'curl/easy'
3
+ require 'curl/multi'
4
+ require 'uri'
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
@@ -19,7 +19,7 @@ class BugCrashOnDebug < Test::Unit::TestCase
19
19
  srv.start
20
20
  end
21
21
  puts 'b'
22
- c = Curl::Easy.new('http://localhost:9999/test')
22
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
23
23
  c.on_debug do|x|
24
24
  puts x.inspect
25
25
  raise "error" # this will get swallowed
@@ -16,7 +16,7 @@ class BugCrashOnDebug < Test::Unit::TestCase
16
16
  srv.start
17
17
  end
18
18
 
19
- c = Curl::Easy.new('http://localhost:9999/test')
19
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
20
20
  c.on_progress do|x|
21
21
  raise "error"
22
22
  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
@@ -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/helper.rb CHANGED
@@ -73,12 +73,12 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
73
73
  elsif req.path.match /error$/
74
74
  res.status = 500
75
75
  end
76
- respond_with(:GET,req,res)
76
+ respond_with("GET#{req.query_string}",req,res)
77
77
  end
78
78
 
79
79
  def do_HEAD(req,res)
80
80
  res['Location'] = "/nonexistent"
81
- respond_with(:HEAD, req, res)
81
+ respond_with("HEAD#{req.query_string}",req,res)
82
82
  end
83
83
 
84
84
  def do_POST(req,res)
@@ -103,15 +103,23 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
103
103
  end
104
104
 
105
105
  def do_DELETE(req,res)
106
- respond_with(:DELETE,req,res)
106
+ respond_with("DELETE#{req.query_string}",req,res)
107
107
  end
108
108
 
109
109
  def do_PURGE(req,res)
110
- respond_with(:PURGE,req,res)
110
+ respond_with("PURGE#{req.query_string}",req,res)
111
111
  end
112
112
 
113
113
  def do_COPY(req,res)
114
- respond_with(: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)
115
123
  end
116
124
 
117
125
  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
@@ -8,7 +8,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
8
8
  end
9
9
 
10
10
  def test_download_url_to_file_via_string
11
- dl_url = "http://localhost:9129/ext/curb_easy.c"
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
14
  curb = Curl::Easy.download(dl_url, dl_path)
@@ -19,7 +19,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
19
19
  end
20
20
 
21
21
  def test_download_url_to_file_via_file_io
22
- dl_url = "http://localhost:9129/ext/curb_easy.c"
22
+ dl_url = "http://127.0.0.1:9129/ext/curb_easy.c"
23
23
  dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
24
24
  io = File.open(dl_path, 'wb')
25
25
 
@@ -32,7 +32,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
32
32
  end
33
33
 
34
34
  def test_download_url_to_file_via_io
35
- dl_url = "http://localhost:9129/ext/curb_easy.c"
35
+ dl_url = "http://127.0.0.1:9129/ext/curb_easy.c"
36
36
  dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
37
37
  reader, writer = IO.pipe
38
38
 
@@ -62,7 +62,7 @@ class TestCurbCurlDownload < Test::Unit::TestCase
62
62
  end
63
63
 
64
64
  def test_download_bad_url_gives_404
65
- dl_url = "http://localhost:9129/this_file_does_not_exist.html"
65
+ dl_url = "http://127.0.0.1:9129/this_file_does_not_exist.html"
66
66
  dl_path = File.join(Dir::tmpdir, "dl_url_test.file")
67
67
 
68
68
  curb = Curl::Easy.download(dl_url, dl_path)
@@ -4,6 +4,21 @@ class FooNoToS
4
4
  end
5
5
 
6
6
  class TestCurbCurlEasy < Test::Unit::TestCase
7
+ def test_threads
8
+ t = []
9
+ 5.times do
10
+ t << Thread.new do
11
+ 5.times do
12
+ c = Curl.get($TEST_URL)
13
+ assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
14
+ assert_equal "", c.header_str
15
+ end
16
+ end
17
+ end
18
+
19
+ t.each {|t| t.join }
20
+ end
21
+
7
22
  def test_class_perform_01
8
23
  assert_instance_of Curl::Easy, c = Curl::Easy.perform($TEST_URL)
9
24
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
@@ -988,6 +1003,20 @@ class TestCurbCurlEasy < Test::Unit::TestCase
988
1003
  assert true, "raise in on debug has no effect"
989
1004
  end
990
1005
 
1006
+ def test_status_codes
1007
+ curl = Curl::Easy.new(TestServlet.url)
1008
+ curl.perform
1009
+ assert_equal '200 OK', curl.status
1010
+ end
1011
+
1012
+ def test_close_in_on_callbacks
1013
+ curl = Curl::Easy.new(TestServlet.url)
1014
+ curl.on_body {|d| curl.close; d.size }
1015
+ assert_raises RuntimeError do
1016
+ curl.perform
1017
+ end
1018
+ end
1019
+
991
1020
  include TestServerMethods
992
1021
 
993
1022
  def setup
@@ -385,7 +385,26 @@ class TestCurbCurlMulti < Test::Unit::TestCase
385
385
  end
386
386
  end
387
387
 
388
- def test_mutli_recieves_500
388
+ def test_multi_easy_http_with_max_connects
389
+ urls = [
390
+ { :url => TestServlet.url + '?q=1', :method => :get },
391
+ { :url => TestServlet.url + '?q=2', :method => :get },
392
+ { :url => TestServlet.url + '?q=3', :method => :get }
393
+ ]
394
+ Curl::Multi.http(urls, {:pipeline => true, :max_connects => 1}) do|easy, code, method|
395
+ assert_equal nil, code
396
+ case method
397
+ when :post
398
+ assert_match /POST/, easy.body_str
399
+ when :get
400
+ assert_match /GET/, easy.body_str
401
+ when :put
402
+ assert_match /PUT/, easy.body_str
403
+ end
404
+ end
405
+ end
406
+
407
+ def test_multi_recieves_500
389
408
  m = Curl::Multi.new
390
409
  e = Curl::Easy.new("http://127.0.0.1:9129/methods")
391
410
  failure = false
@@ -410,7 +429,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
410
429
  c = Curl::Easy.new("http://127.9.9.9:999110")
411
430
  m.remove(c)
412
431
  rescue => e
413
- assert_equal 'Invalid easy handle', e.message
432
+ assert_equal 'CURLError: Invalid easy handle', e.message
414
433
  assert_equal 0, m.requests.size
415
434
  end
416
435
 
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.8.0
4
+ version: 0.8.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-01-19 00:00:00.000000000 Z
13
+ date: 2013-05-20 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: Curb (probably CUrl-RuBy or something) provides Ruby-language bindings
16
16
  for the libcurl(3), a fully-featured client-side URL transfer library. cURL and
@@ -51,6 +51,7 @@ files:
51
51
  - tests/bug_curb_easy_blocks_ruby_threads.rb
52
52
  - tests/bug_curb_easy_post_with_string_no_content_length_header.rb
53
53
  - tests/bug_instance_post_differs_from_class_post.rb
54
+ - tests/bug_issue102.rb
54
55
  - tests/bug_multi_segfault.rb
55
56
  - tests/bug_postfields_crash.rb
56
57
  - tests/bug_postfields_crash2.rb
@@ -59,6 +60,8 @@ files:
59
60
  - tests/helper.rb
60
61
  - tests/mem_check.rb
61
62
  - tests/require_last_or_segfault_script.rb
63
+ - tests/signals.rb
64
+ - tests/tc_curl.rb
62
65
  - tests/tc_curl_download.rb
63
66
  - tests/tc_curl_easy.rb
64
67
  - tests/tc_curl_easy_setopt.rb
@@ -82,15 +85,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
82
85
  - - ! '>='
83
86
  - !ruby/object:Gem::Version
84
87
  version: '0'
88
+ segments:
89
+ - 0
90
+ hash: -243569426931689339
85
91
  required_rubygems_version: !ruby/object:Gem::Requirement
86
92
  none: false
87
93
  requirements:
88
94
  - - ! '>='
89
95
  - !ruby/object:Gem::Version
90
96
  version: '0'
97
+ segments:
98
+ - 0
99
+ hash: -243569426931689339
91
100
  requirements: []
92
101
  rubyforge_project: curb
93
- rubygems_version: 1.8.10
102
+ rubygems_version: 1.8.24
94
103
  signing_key:
95
104
  specification_version: 3
96
105
  summary: Ruby libcurl bindings
@@ -101,6 +110,7 @@ test_files:
101
110
  - tests/bug_curb_easy_blocks_ruby_threads.rb
102
111
  - tests/bug_curb_easy_post_with_string_no_content_length_header.rb
103
112
  - tests/bug_instance_post_differs_from_class_post.rb
113
+ - tests/bug_issue102.rb
104
114
  - tests/bug_multi_segfault.rb
105
115
  - tests/bug_postfields_crash.rb
106
116
  - tests/bug_postfields_crash2.rb
@@ -109,6 +119,8 @@ test_files:
109
119
  - tests/helper.rb
110
120
  - tests/mem_check.rb
111
121
  - tests/require_last_or_segfault_script.rb
122
+ - tests/signals.rb
123
+ - tests/tc_curl.rb
112
124
  - tests/tc_curl_download.rb
113
125
  - tests/tc_curl_easy.rb
114
126
  - tests/tc_curl_easy_setopt.rb