curb 1.1.0 → 1.2.0
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.
- checksums.yaml +4 -4
- data/README.md +5 -1
- data/ext/curb.c +6 -4
- data/ext/curb.h +3 -3
- data/ext/curb_easy.c +97 -8
- data/ext/curb_multi.c +477 -15
- data/ext/curb_postfield.c +6 -0
- data/ext/curb_upload.c +3 -0
- data/ext/extconf.rb +214 -17
- data/tests/bug_issue_noproxy.rb +56 -0
- data/tests/bug_issue_post_redirect.rb +93 -0
- data/tests/bug_issue_spnego.rb +41 -0
- data/tests/helper.rb +33 -0
- data/tests/mem_check.rb +3 -0
- data/tests/tc_curl_download.rb +2 -1
- data/tests/tc_curl_easy.rb +65 -6
- data/tests/tc_curl_multi.rb +2 -0
- data/tests/tc_fiber_scheduler.rb +190 -0
- data/tests/test_basic.rb +29 -0
- data/tests/test_fiber_debug.rb +69 -0
- data/tests/test_fiber_simple.rb +65 -0
- data/tests/test_real_url.rb +65 -0
- data/tests/test_simple_fiber.rb +34 -0
- metadata +20 -6
- data/tests/bug_issue277.rb +0 -32
- data/tests/bug_resolve.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 832660904f4d95f97b0795a4e39850f2fca2c70e521a0bb795a9c551f6fdf9f3
|
4
|
+
data.tar.gz: 903cb16a9a77396e90ea9ab2f33fb94a84d6a811525d23506af43195ab49fec2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf99199469304444421b00adbaa2b64707c7eddcdaff9a3c662531ebf5f2220a1b6555145fa516422921ac0980c851e7ce234ff88391d608ca6783211f364ddf
|
7
|
+
data.tar.gz: 41aec998852a8458ed9f5508f37374ac72fb170c4235a7279e4f9864d2af143281cd81e1dec6099c80765d97b2263d1ee34bebd2b193701b9a4175a024ca5991
|
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# Curb - Libcurl bindings for Ruby
|
2
2
|
|
3
|
-
|
3
|
+
[](https://github.com/taf2/curb/actions/workflows/ci.yml)
|
4
|
+
[](https://codecov.io/gh/taf2/curb)
|
5
|
+
[](https://badge.fury.io/rb/curb)
|
6
|
+
|
7
|
+
* [CI Build Status](https://github.com/taf2/curb/actions/workflows/ci.yml)
|
4
8
|
* [rubydoc rdoc](http://www.rubydoc.info/github/taf2/curb/)
|
5
9
|
* [github project](http://github.com/taf2/curb/tree/master)
|
6
10
|
|
data/ext/curb.c
CHANGED
@@ -143,12 +143,14 @@ static VALUE ruby_curl_asyncdns_q(VALUE mod) {
|
|
143
143
|
* in RFC 2478). For libcurl versions < 7.10.8, always returns false.
|
144
144
|
*/
|
145
145
|
static VALUE ruby_curl_spnego_q(VALUE mod) {
|
146
|
-
#ifdef HAVE_CURL_VERSION_SPNEGO
|
147
146
|
curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
|
148
|
-
|
149
|
-
|
150
|
-
return Qfalse;
|
147
|
+
#ifdef HAVE_CURL_VERSION_SPNEGO
|
148
|
+
if (ver->features & CURL_VERSION_SPNEGO) return Qtrue;
|
151
149
|
#endif
|
150
|
+
#ifdef HAVE_CURL_VERSION_GSSNEGOTIATE
|
151
|
+
if (ver->features & CURL_VERSION_GSSNEGOTIATE) return Qtrue;
|
152
|
+
#endif
|
153
|
+
return Qfalse;
|
152
154
|
}
|
153
155
|
|
154
156
|
/*
|
data/ext/curb.h
CHANGED
@@ -28,10 +28,10 @@
|
|
28
28
|
#include "curb_macros.h"
|
29
29
|
|
30
30
|
// These should be managed from the Rake 'release' task.
|
31
|
-
#define CURB_VERSION "1.
|
32
|
-
#define CURB_VER_NUM
|
31
|
+
#define CURB_VERSION "1.2.0"
|
32
|
+
#define CURB_VER_NUM 1020
|
33
33
|
#define CURB_VER_MAJ 1
|
34
|
-
#define CURB_VER_MIN
|
34
|
+
#define CURB_VER_MIN 2
|
35
35
|
#define CURB_VER_MIC 0
|
36
36
|
#define CURB_VER_PATCH 0
|
37
37
|
|
data/ext/curb_easy.c
CHANGED
@@ -12,6 +12,9 @@
|
|
12
12
|
|
13
13
|
#include <errno.h>
|
14
14
|
#include <string.h>
|
15
|
+
#ifndef _WIN32
|
16
|
+
#include <strings.h>
|
17
|
+
#endif
|
15
18
|
|
16
19
|
extern VALUE mCurl;
|
17
20
|
|
@@ -309,6 +312,7 @@ static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
|
|
309
312
|
rbce->enable_cookies = 0;
|
310
313
|
rbce->ignore_content_length = 0;
|
311
314
|
rbce->callback_active = 0;
|
315
|
+
rbce->last_result = 0;
|
312
316
|
}
|
313
317
|
|
314
318
|
/*
|
@@ -317,6 +321,9 @@ static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
|
|
317
321
|
static VALUE ruby_curl_easy_allocate(VALUE klass) {
|
318
322
|
ruby_curl_easy *rbce;
|
319
323
|
rbce = ALLOC(ruby_curl_easy);
|
324
|
+
if (!rbce) {
|
325
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory for Curl::Easy");
|
326
|
+
}
|
320
327
|
rbce->curl = NULL;
|
321
328
|
rbce->opts = Qnil;
|
322
329
|
rbce->multi = Qnil;
|
@@ -375,8 +382,14 @@ static VALUE ruby_curl_easy_initialize(int argc, VALUE *argv, VALUE self) {
|
|
375
382
|
static struct curl_slist *duplicate_curl_slist(struct curl_slist *list) {
|
376
383
|
struct curl_slist *dup = NULL;
|
377
384
|
struct curl_slist *tmp;
|
385
|
+
struct curl_slist *new_list;
|
378
386
|
for (tmp = list; tmp; tmp = tmp->next) {
|
379
|
-
|
387
|
+
new_list = curl_slist_append(dup, tmp->data);
|
388
|
+
if (!new_list) {
|
389
|
+
if (dup) { curl_slist_free_all(dup); }
|
390
|
+
rb_raise(rb_eNoMemError, "Failed to duplicate curl_slist");
|
391
|
+
}
|
392
|
+
dup = new_list;
|
380
393
|
}
|
381
394
|
return dup;
|
382
395
|
}
|
@@ -395,6 +408,9 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
|
|
395
408
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
396
409
|
|
397
410
|
newrbce = ALLOC(ruby_curl_easy);
|
411
|
+
if (!newrbce) {
|
412
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory for Curl::Easy clone");
|
413
|
+
}
|
398
414
|
/* shallow copy */
|
399
415
|
memcpy(newrbce, rbce, sizeof(ruby_curl_easy));
|
400
416
|
|
@@ -405,6 +421,9 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
|
|
405
421
|
newrbce->curl_ftp_commands = (rbce->curl_ftp_commands) ? duplicate_curl_slist(rbce->curl_ftp_commands) : NULL;
|
406
422
|
newrbce->curl_resolve = (rbce->curl_resolve) ? duplicate_curl_slist(rbce->curl_resolve) : NULL;
|
407
423
|
|
424
|
+
/* A cloned easy should not retain ownership reference to the original multi. */
|
425
|
+
newrbce->multi = Qnil;
|
426
|
+
|
408
427
|
if (rbce->opts != Qnil) {
|
409
428
|
newrbce->opts = rb_funcall(rbce->opts, rb_intern("dup"), 0);
|
410
429
|
}
|
@@ -2165,7 +2184,11 @@ static VALUE cb_each_http_header(VALUE header, VALUE wrap, int _c, const VALUE *
|
|
2165
2184
|
|
2166
2185
|
//rb_p(header_str);
|
2167
2186
|
|
2168
|
-
*
|
2187
|
+
struct curl_slist *new_list = curl_slist_append(*list, StringValuePtr(header_str));
|
2188
|
+
if (!new_list) {
|
2189
|
+
rb_raise(rb_eNoMemError, "Failed to append to header list");
|
2190
|
+
}
|
2191
|
+
*list = new_list;
|
2169
2192
|
return header_str;
|
2170
2193
|
}
|
2171
2194
|
|
@@ -2197,7 +2220,11 @@ static VALUE cb_each_http_proxy_header(VALUE proxy_header, VALUE wrap, int _c, c
|
|
2197
2220
|
|
2198
2221
|
//rb_p(header_str);
|
2199
2222
|
|
2200
|
-
*
|
2223
|
+
struct curl_slist *new_list = curl_slist_append(*list, StringValuePtr(proxy_header_str));
|
2224
|
+
if (!new_list) {
|
2225
|
+
rb_raise(rb_eNoMemError, "Failed to append to proxy header list");
|
2226
|
+
}
|
2227
|
+
*list = new_list;
|
2201
2228
|
return proxy_header_str;
|
2202
2229
|
}
|
2203
2230
|
|
@@ -2210,7 +2237,11 @@ static VALUE cb_each_ftp_command(VALUE ftp_command, VALUE wrap, int _c, const VA
|
|
2210
2237
|
Data_Get_Struct(wrap, struct curl_slist *, list);
|
2211
2238
|
|
2212
2239
|
ftp_command_string = rb_obj_as_string(ftp_command);
|
2213
|
-
*
|
2240
|
+
struct curl_slist *new_list = curl_slist_append(*list, StringValuePtr(ftp_command));
|
2241
|
+
if (!new_list) {
|
2242
|
+
rb_raise(rb_eNoMemError, "Failed to append to FTP command list");
|
2243
|
+
}
|
2244
|
+
*list = new_list;
|
2214
2245
|
|
2215
2246
|
return ftp_command_string;
|
2216
2247
|
}
|
@@ -2224,7 +2255,11 @@ static VALUE cb_each_resolve(VALUE resolve, VALUE wrap, int _c, const VALUE *_pt
|
|
2224
2255
|
Data_Get_Struct(wrap, struct curl_slist *, list);
|
2225
2256
|
|
2226
2257
|
resolve_string = rb_obj_as_string(resolve);
|
2227
|
-
*
|
2258
|
+
struct curl_slist *new_list = curl_slist_append(*list, StringValuePtr(resolve));
|
2259
|
+
if (!new_list) {
|
2260
|
+
rb_raise(rb_eNoMemError, "Failed to append to resolve list");
|
2261
|
+
}
|
2262
|
+
*list = new_list;
|
2228
2263
|
|
2229
2264
|
return resolve_string;
|
2230
2265
|
}
|
@@ -2296,6 +2331,14 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2296
2331
|
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, rb_easy_get_str("proxypwd"));
|
2297
2332
|
}
|
2298
2333
|
|
2334
|
+
#if HAVE_CURLOPT_NOPROXY
|
2335
|
+
if (rb_easy_nil("noproxy")) {
|
2336
|
+
curl_easy_setopt(curl, CURLOPT_NOPROXY, NULL);
|
2337
|
+
} else {
|
2338
|
+
curl_easy_setopt(curl, CURLOPT_NOPROXY, rb_easy_get_str("noproxy"));
|
2339
|
+
}
|
2340
|
+
#endif
|
2341
|
+
|
2299
2342
|
// body/header procs
|
2300
2343
|
if (!rb_easy_nil("body_proc")) {
|
2301
2344
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&proc_data_handler_body);
|
@@ -2517,7 +2560,11 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2517
2560
|
rb_iterate(rb_each, rb_easy_get("headers"), cb_each_http_header, wrap);
|
2518
2561
|
} else {
|
2519
2562
|
VALUE headers_str = rb_obj_as_string(rb_easy_get("headers"));
|
2520
|
-
*
|
2563
|
+
struct curl_slist *new_list = curl_slist_append(*hdrs, StringValuePtr(headers_str));
|
2564
|
+
if (!new_list) {
|
2565
|
+
rb_raise(rb_eNoMemError, "Failed to append to headers list");
|
2566
|
+
}
|
2567
|
+
*hdrs = new_list;
|
2521
2568
|
}
|
2522
2569
|
|
2523
2570
|
if (*hdrs) {
|
@@ -2535,7 +2582,11 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2535
2582
|
rb_iterate(rb_each, rb_easy_get("proxy_headers"), cb_each_http_proxy_header, wrap);
|
2536
2583
|
} else {
|
2537
2584
|
VALUE proxy_headers_str = rb_obj_as_string(rb_easy_get("proxy_headers"));
|
2538
|
-
*
|
2585
|
+
struct curl_slist *new_list = curl_slist_append(*phdrs, StringValuePtr(proxy_headers_str));
|
2586
|
+
if (!new_list) {
|
2587
|
+
rb_raise(rb_eNoMemError, "Failed to append to proxy headers list");
|
2588
|
+
}
|
2589
|
+
*phdrs = new_list;
|
2539
2590
|
}
|
2540
2591
|
|
2541
2592
|
if (*phdrs) {
|
@@ -2635,10 +2686,31 @@ static VALUE ruby_curl_easy_perform_verb_str(VALUE self, const char *verb) {
|
|
2635
2686
|
|
2636
2687
|
memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
|
2637
2688
|
|
2689
|
+
/* Use method override and adjust related options for special verbs. */
|
2638
2690
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb);
|
2639
2691
|
|
2692
|
+
/* For HEAD, ensure no body is requested/downloaded, as some servers
|
2693
|
+
* include a Content-Length header which should not cause libcurl to
|
2694
|
+
* wait for a body that will never arrive. */
|
2695
|
+
int is_head = (verb && (
|
2696
|
+
#ifdef _WIN32
|
2697
|
+
_stricmp(verb, "HEAD") == 0
|
2698
|
+
#else
|
2699
|
+
strcasecmp(verb, "HEAD") == 0
|
2700
|
+
#endif
|
2701
|
+
));
|
2702
|
+
if (is_head) {
|
2703
|
+
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
|
2704
|
+
curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L);
|
2705
|
+
curl_easy_setopt(curl, CURLOPT_POST, 0L);
|
2706
|
+
}
|
2707
|
+
|
2640
2708
|
retval = rb_funcall(self, rb_intern("perform"), 0);
|
2641
2709
|
|
2710
|
+
/* Restore state after request. */
|
2711
|
+
if (is_head) {
|
2712
|
+
curl_easy_setopt(curl, CURLOPT_NOBODY, 0L);
|
2713
|
+
}
|
2642
2714
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
|
2643
2715
|
|
2644
2716
|
return retval;
|
@@ -3725,6 +3797,12 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3725
3797
|
VALUE proxypwd = val;
|
3726
3798
|
CURB_OBJECT_HSETTER(ruby_curl_easy, proxypwd);
|
3727
3799
|
} break;
|
3800
|
+
#if HAVE_CURLOPT_NOPROXY
|
3801
|
+
case CURLOPT_NOPROXY: {
|
3802
|
+
VALUE noproxy = val;
|
3803
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, noproxy);
|
3804
|
+
} break;
|
3805
|
+
#endif
|
3728
3806
|
case CURLOPT_COOKIE: {
|
3729
3807
|
VALUE cookies = val;
|
3730
3808
|
CURB_OBJECT_HSETTER(ruby_curl_easy, cookies);
|
@@ -3802,6 +3880,9 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3802
3880
|
Check_Type(val, T_FILE);
|
3803
3881
|
GetOpenFile(val, open_f_ptr);
|
3804
3882
|
curl_easy_setopt(rbce->curl, CURLOPT_STDERR, rb_io_stdio_file(open_f_ptr));
|
3883
|
+
/* Retain a Ruby reference to the IO to prevent GC/finalization
|
3884
|
+
* while libcurl still holds and writes to the underlying FILE*. */
|
3885
|
+
rb_easy_set("stderr_io", val);
|
3805
3886
|
break;
|
3806
3887
|
case CURLOPT_PROTOCOLS:
|
3807
3888
|
case CURLOPT_REDIR_PROTOCOLS:
|
@@ -3832,11 +3913,19 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3832
3913
|
long i, len = RARRAY_LEN(val);
|
3833
3914
|
for (i = 0; i < len; i++) {
|
3834
3915
|
VALUE item = rb_ary_entry(val, i);
|
3835
|
-
|
3916
|
+
struct curl_slist *new_list = curl_slist_append(list, StringValueCStr(item));
|
3917
|
+
if (!new_list) {
|
3918
|
+
curl_slist_free_all(list);
|
3919
|
+
rb_raise(rb_eNoMemError, "Failed to append to resolve list");
|
3920
|
+
}
|
3921
|
+
list = new_list;
|
3836
3922
|
}
|
3837
3923
|
} else {
|
3838
3924
|
/* If a single string is passed, use it directly */
|
3839
3925
|
list = curl_slist_append(NULL, StringValueCStr(val));
|
3926
|
+
if (!list) {
|
3927
|
+
rb_raise(rb_eNoMemError, "Failed to create resolve list");
|
3928
|
+
}
|
3840
3929
|
}
|
3841
3930
|
/* Save the list pointer in the ruby_curl_easy structure for cleanup later */
|
3842
3931
|
rbce->curl_resolve = list;
|