curb 1.0.6 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/curb.h +3 -3
- data/ext/curb_easy.c +52 -15
- data/ext/curb_multi.c +44 -1
- data/ext/curb_postfield.c +92 -55
- data/ext/extconf.rb +2 -0
- data/lib/curl/multi.rb +1 -1
- data/tests/helper.rb +16 -1
- data/tests/tc_curl_easy.rb +5 -5
- data/tests/tc_curl_easy_cookielist.rb +277 -0
- data/tests/tc_curl_multi.rb +9 -9
- metadata +6 -9
- data/tests/bug_issue277.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 805549f6e3fe9190d76c507fa67bf6f6e2a6bbe65bde611cb3aeee6c78cad51f
|
4
|
+
data.tar.gz: 7f6cab9c618e4535e7ff46b48d11bb5f307158d850b95bd560432dfeb9ea3144
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98f411070f4c3ef1646de29052a2c9a37e7aa2c9009102a7f4e483d1d1188d8bbdae50647e6dd4c8c7439120619e22df5f8c90bba6e1a088e2762cc29109c63d
|
7
|
+
data.tar.gz: bb8ad84d03972d1e42ce61622060019edc4d6286bab9ab459d2fe9e8ccd3cdc04490a8ba58715fd4efa30e3babf82ac96afce3f5b80fddd1d0bd4d47b197a5f1
|
data/ext/curb.h
CHANGED
@@ -28,11 +28,11 @@
|
|
28
28
|
#include "curb_macros.h"
|
29
29
|
|
30
30
|
// These should be managed from the Rake 'release' task.
|
31
|
-
#define CURB_VERSION "1.0.
|
32
|
-
#define CURB_VER_NUM
|
31
|
+
#define CURB_VERSION "1.0.7"
|
32
|
+
#define CURB_VER_NUM 1007
|
33
33
|
#define CURB_VER_MAJ 1
|
34
34
|
#define CURB_VER_MIN 0
|
35
|
-
#define CURB_VER_MIC
|
35
|
+
#define CURB_VER_MIC 7
|
36
36
|
#define CURB_VER_PATCH 0
|
37
37
|
|
38
38
|
|
data/ext/curb_easy.c
CHANGED
@@ -31,6 +31,7 @@ static FILE * rb_io_stdio_file(rb_io_t *fptr) {
|
|
31
31
|
return fptr->f;
|
32
32
|
}
|
33
33
|
#endif
|
34
|
+
static struct curl_slist *duplicate_curl_slist(struct curl_slist *list);
|
34
35
|
|
35
36
|
/* ================== CURL HANDLER FUNCS ==============*/
|
36
37
|
|
@@ -264,7 +265,7 @@ void curl_easy_free(ruby_curl_easy *rbce) {
|
|
264
265
|
static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
|
265
266
|
rbce->opts = rb_hash_new();
|
266
267
|
|
267
|
-
memset(rbce->err_buf, 0,
|
268
|
+
memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
|
268
269
|
|
269
270
|
rbce->curl_headers = NULL;
|
270
271
|
rbce->curl_proxy_headers = NULL;
|
@@ -370,6 +371,16 @@ static VALUE ruby_curl_easy_initialize(int argc, VALUE *argv, VALUE self) {
|
|
370
371
|
return self;
|
371
372
|
}
|
372
373
|
|
374
|
+
/* Helper to duplicate a curl_slist */
|
375
|
+
static struct curl_slist *duplicate_curl_slist(struct curl_slist *list) {
|
376
|
+
struct curl_slist *dup = NULL;
|
377
|
+
struct curl_slist *tmp;
|
378
|
+
for (tmp = list; tmp; tmp = tmp->next) {
|
379
|
+
dup = curl_slist_append(dup, tmp->data);
|
380
|
+
}
|
381
|
+
return dup;
|
382
|
+
}
|
383
|
+
|
373
384
|
/*
|
374
385
|
* call-seq:
|
375
386
|
* easy.clone => <easy clone>
|
@@ -384,14 +395,22 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
|
|
384
395
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
385
396
|
|
386
397
|
newrbce = ALLOC(ruby_curl_easy);
|
398
|
+
/* shallow copy */
|
387
399
|
memcpy(newrbce, rbce, sizeof(ruby_curl_easy));
|
400
|
+
|
401
|
+
/* now deep copy */
|
388
402
|
newrbce->curl = curl_easy_duphandle(rbce->curl);
|
389
|
-
newrbce->curl_headers = NULL;
|
390
|
-
newrbce->curl_proxy_headers = NULL;
|
391
|
-
newrbce->curl_ftp_commands = NULL;
|
392
|
-
newrbce->curl_resolve = NULL;
|
403
|
+
newrbce->curl_headers = (rbce->curl_headers) ? duplicate_curl_slist(rbce->curl_headers) : NULL;
|
404
|
+
newrbce->curl_proxy_headers = (rbce->curl_proxy_headers) ? duplicate_curl_slist(rbce->curl_proxy_headers) : NULL;
|
405
|
+
newrbce->curl_ftp_commands = (rbce->curl_ftp_commands) ? duplicate_curl_slist(rbce->curl_ftp_commands) : NULL;
|
406
|
+
newrbce->curl_resolve = (rbce->curl_resolve) ? duplicate_curl_slist(rbce->curl_resolve) : NULL;
|
393
407
|
|
394
|
-
|
408
|
+
if (rbce->opts != Qnil) {
|
409
|
+
newrbce->opts = rb_funcall(rbce->opts, rb_intern("dup"), 0);
|
410
|
+
}
|
411
|
+
|
412
|
+
/* Set the error buffer on the new curl handle using the new err_buf */
|
413
|
+
curl_easy_setopt(newrbce->curl, CURLOPT_ERRORBUFFER, newrbce->err_buf);
|
395
414
|
|
396
415
|
return Data_Wrap_Struct(cCurlEasy, curl_easy_mark, curl_easy_free, newrbce);
|
397
416
|
}
|
@@ -2614,7 +2633,7 @@ static VALUE ruby_curl_easy_perform_verb_str(VALUE self, const char *verb) {
|
|
2614
2633
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2615
2634
|
curl = rbce->curl;
|
2616
2635
|
|
2617
|
-
memset(rbce->err_buf, 0,
|
2636
|
+
memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
|
2618
2637
|
|
2619
2638
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb);
|
2620
2639
|
|
@@ -2681,7 +2700,7 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
|
|
2681
2700
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2682
2701
|
curl = rbce->curl;
|
2683
2702
|
|
2684
|
-
memset(rbce->err_buf, 0,
|
2703
|
+
memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
|
2685
2704
|
|
2686
2705
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
|
2687
2706
|
|
@@ -2754,7 +2773,7 @@ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
|
|
2754
2773
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2755
2774
|
curl = rbce->curl;
|
2756
2775
|
|
2757
|
-
memset(rbce->err_buf, 0,
|
2776
|
+
memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
|
2758
2777
|
|
2759
2778
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
|
2760
2779
|
ruby_curl_easy_put_data_set(self, data);
|
@@ -3364,14 +3383,16 @@ static VALUE ruby_curl_easy_num_connects_get(VALUE self) {
|
|
3364
3383
|
|
3365
3384
|
/*
|
3366
3385
|
* call-seq:
|
3367
|
-
* easy.cookielist =>
|
3386
|
+
* easy.cookielist => cookielist
|
3368
3387
|
*
|
3369
3388
|
* Retrieves the cookies curl knows in an array of strings.
|
3370
3389
|
* Returned strings are in Netscape cookiejar format or in Set-Cookie format.
|
3390
|
+
* Since 7.43.0 cookies in the Set-Cookie format without a domain name are not exported.
|
3371
3391
|
*
|
3372
|
-
*
|
3373
|
-
*
|
3374
|
-
*
|
3392
|
+
* @see https://curl.se/libcurl/c/CURLINFO_COOKIELIST.html option <code>CURLINFO_COOKIELIST</code> of
|
3393
|
+
* <code>curl_easy_getopt(3)</code> to see how libcurl behaves.
|
3394
|
+
* @note requires libcurl 7.14.1 or higher, otherwise +-1+ is always returned
|
3395
|
+
* @return [Array<String>, nil, -1] array of strings, or +nil+ if there are no cookies, or +-1+ if the libcurl version is too old
|
3375
3396
|
*/
|
3376
3397
|
static VALUE ruby_curl_easy_cookielist_get(VALUE self) {
|
3377
3398
|
#ifdef HAVE_CURLINFO_COOKIELIST
|
@@ -3482,9 +3503,16 @@ static VALUE ruby_curl_easy_last_error(VALUE self) {
|
|
3482
3503
|
|
3483
3504
|
/*
|
3484
3505
|
* call-seq:
|
3485
|
-
* easy.setopt
|
3506
|
+
* easy.setopt(opt, val) => val
|
3486
3507
|
*
|
3487
3508
|
* Initial access to libcurl curl_easy_setopt
|
3509
|
+
*
|
3510
|
+
* @param [Fixnum] opt The option to set, see +Curl::CURLOPT_*+ constants
|
3511
|
+
* @param [Object] val
|
3512
|
+
* @return [Object] val
|
3513
|
+
* @raise [TypeError] if the option is not supported
|
3514
|
+
* @note Some options - like url or cookie - aren't set directly throught +curl_easy_setopt+, but stored in the Ruby object state.
|
3515
|
+
* @note When +curl_easy_setopt+ is called, return value is not checked here.
|
3488
3516
|
*/
|
3489
3517
|
static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
3490
3518
|
ruby_curl_easy *rbce;
|
@@ -3650,6 +3678,11 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3650
3678
|
curl_easy_setopt(rbce->curl, CURLOPT_SSL_SESSIONID_CACHE, NUM2LONG(val));
|
3651
3679
|
break;
|
3652
3680
|
#endif
|
3681
|
+
#if HAVE_CURLOPT_COOKIELIST
|
3682
|
+
case CURLOPT_COOKIELIST: {
|
3683
|
+
curl_easy_setopt(rbce->curl, CURLOPT_COOKIELIST, StringValueCStr(val));
|
3684
|
+
} break;
|
3685
|
+
#endif
|
3653
3686
|
#if HAVE_CURLOPT_PROXY_SSL_VERIFYHOST
|
3654
3687
|
case CURLOPT_PROXY_SSL_VERIFYHOST:
|
3655
3688
|
curl_easy_setopt(rbce->curl, CURLOPT_PROXY_SSL_VERIFYHOST, NUM2LONG(val));
|
@@ -3664,9 +3697,13 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3664
3697
|
|
3665
3698
|
/*
|
3666
3699
|
* call-seq:
|
3667
|
-
* easy.getinfo
|
3700
|
+
* easy.getinfo(opt) => nil
|
3668
3701
|
*
|
3669
3702
|
* Iniital access to libcurl curl_easy_getinfo, remember getinfo doesn't return the same values as setopt
|
3703
|
+
*
|
3704
|
+
* @note This method is not implemented yet.
|
3705
|
+
* @param [Fixnum] code Constant +CURLINFO_*+ from libcurl
|
3706
|
+
* @return [nil]
|
3670
3707
|
*/
|
3671
3708
|
static VALUE ruby_curl_easy_get_opt(VALUE self, VALUE opt) {
|
3672
3709
|
return Qnil;
|
data/ext/curb_multi.c
CHANGED
@@ -27,6 +27,21 @@
|
|
27
27
|
#include <fcntl.h>
|
28
28
|
#endif
|
29
29
|
|
30
|
+
#ifdef HAVE_CURL_MULTI_WAIT
|
31
|
+
#include <stdint.h> /* for intptr_t */
|
32
|
+
|
33
|
+
struct wait_args {
|
34
|
+
CURLM *handle;
|
35
|
+
long timeout_ms;
|
36
|
+
int numfds;
|
37
|
+
};
|
38
|
+
static void *curl_multi_wait_wrapper(void *p) {
|
39
|
+
struct wait_args *args = p;
|
40
|
+
CURLMcode code = curl_multi_wait(args->handle, NULL, 0, args->timeout_ms, &args->numfds);
|
41
|
+
return (void *)(intptr_t)code;
|
42
|
+
}
|
43
|
+
#endif
|
44
|
+
|
30
45
|
extern VALUE mCurl;
|
31
46
|
static VALUE idCall;
|
32
47
|
|
@@ -226,6 +241,8 @@ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
|
|
226
241
|
|
227
242
|
mcode = curl_multi_add_handle(rbcm->handle, rbce->curl);
|
228
243
|
if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
|
244
|
+
ruby_curl_easy_cleanup(easy, rbce);
|
245
|
+
|
229
246
|
raise_curl_multi_error_exception(mcode);
|
230
247
|
}
|
231
248
|
|
@@ -264,6 +281,7 @@ VALUE ruby_curl_multi_remove(VALUE self, VALUE rb_easy_handle) {
|
|
264
281
|
|
265
282
|
return self;
|
266
283
|
}
|
284
|
+
|
267
285
|
static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy) {
|
268
286
|
CURLMcode result;
|
269
287
|
ruby_curl_easy *rbce;
|
@@ -528,7 +546,6 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
|
|
528
546
|
|
529
547
|
do {
|
530
548
|
while (rbcm->running) {
|
531
|
-
|
532
549
|
#ifdef HAVE_CURL_MULTI_TIMEOUT
|
533
550
|
/* get the curl suggested time out */
|
534
551
|
mcode = curl_multi_timeout(rbcm->handle, &timeout_milliseconds);
|
@@ -552,6 +569,31 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
|
|
552
569
|
/* or buggy versions libcurl sometimes reports huge timeouts... let's cap it */
|
553
570
|
}
|
554
571
|
|
572
|
+
#ifdef HAVE_CURL_MULTI_WAIT
|
573
|
+
{
|
574
|
+
struct wait_args wait_args;
|
575
|
+
wait_args.handle = rbcm->handle;
|
576
|
+
wait_args.timeout_ms = timeout_milliseconds;
|
577
|
+
wait_args.numfds = 0;
|
578
|
+
#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
579
|
+
CURLMcode wait_rc = (CURLMcode)(intptr_t)
|
580
|
+
rb_thread_call_without_gvl(curl_multi_wait_wrapper, &wait_args, RUBY_UBF_IO, NULL);
|
581
|
+
#else
|
582
|
+
CURLMcode wait_rc = curl_multi_wait(rbcm->handle, NULL, 0, timeout_milliseconds, &wait_args.numfds);
|
583
|
+
#endif
|
584
|
+
if (wait_rc != CURLM_OK) {
|
585
|
+
raise_curl_multi_error_exception(wait_rc);
|
586
|
+
}
|
587
|
+
if (wait_args.numfds == 0) {
|
588
|
+
rb_thread_wait_for(tv_100ms);
|
589
|
+
}
|
590
|
+
/* Process pending transfers after waiting */
|
591
|
+
rb_curl_multi_run(self, rbcm->handle, &(rbcm->running));
|
592
|
+
rb_curl_multi_read_info(self, rbcm->handle);
|
593
|
+
if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self); }
|
594
|
+
}
|
595
|
+
#else
|
596
|
+
|
555
597
|
tv.tv_sec = 0; /* never wait longer than 1 second */
|
556
598
|
tv.tv_usec = (int)(timeout_milliseconds * 1000); /* XXX: int is the right type for OSX, what about linux? */
|
557
599
|
|
@@ -618,6 +660,7 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
|
|
618
660
|
if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self); }
|
619
661
|
break;
|
620
662
|
}
|
663
|
+
#endif /* HAVE_CURL_MULTI_WAIT */
|
621
664
|
}
|
622
665
|
|
623
666
|
} while( rbcm->running );
|
data/ext/curb_postfield.c
CHANGED
@@ -421,71 +421,108 @@ static VALUE ruby_curl_postfield_content_proc_set(int argc, VALUE *argv, VALUE s
|
|
421
421
|
* Only content fields may be converted to strings.
|
422
422
|
*/
|
423
423
|
static VALUE ruby_curl_postfield_to_str(VALUE self) {
|
424
|
-
// FIXME This is using the deprecated curl_escape func
|
425
424
|
ruby_curl_postfield *rbcpf;
|
426
425
|
VALUE result = Qnil;
|
427
426
|
VALUE name = Qnil;
|
428
427
|
char *tmpchrs;
|
429
|
-
|
428
|
+
#ifdef HAVE_CURL_EASY_ESCAPE
|
429
|
+
CURL *curl_handle = NULL;
|
430
|
+
#endif
|
431
|
+
|
430
432
|
Data_Get_Struct(self, ruby_curl_postfield, rbcpf);
|
431
433
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
} else if (rb_respond_to(name,rb_intern("to_s"))) {
|
434
|
+
if (rbcpf->name != Qnil) {
|
435
|
+
name = rbcpf->name;
|
436
|
+
if (TYPE(name) != T_STRING) {
|
437
|
+
if (rb_respond_to(name, rb_intern("to_s")))
|
437
438
|
name = rb_funcall(name, rb_intern("to_s"), 0);
|
438
|
-
|
439
|
-
|
440
|
-
name = Qnil; // we can't handle this object
|
441
|
-
}
|
442
|
-
}
|
443
|
-
if (name == Qnil) {
|
444
|
-
rb_raise(eCurlErrInvalidPostField, "Cannot convert unnamed field to string %s:%d, make sure your field name responds_to :to_s", __FILE__, __LINE__);
|
439
|
+
else
|
440
|
+
name = Qnil;
|
445
441
|
}
|
442
|
+
}
|
443
|
+
if (name == Qnil) {
|
444
|
+
rb_raise(eCurlErrInvalidPostField,
|
445
|
+
"Cannot convert unnamed field to string %s:%d, make sure your field name responds_to :to_s",
|
446
|
+
__FILE__, __LINE__);
|
447
|
+
}
|
448
|
+
/* Force field name to UTF-8 before escaping */
|
449
|
+
VALUE name_utf8 = rb_str_export_to_enc(name, rb_utf8_encoding());
|
446
450
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
451
|
+
#ifdef HAVE_CURL_EASY_ESCAPE
|
452
|
+
curl_handle = curl_easy_init();
|
453
|
+
if (!curl_handle) {
|
454
|
+
rb_raise(eCurlErrInvalidPostField, "Failed to initialize curl handle for escaping");
|
455
|
+
}
|
456
|
+
tmpchrs = curl_easy_escape(curl_handle, StringValuePtr(name_utf8), (int)RSTRING_LEN(name_utf8));
|
457
|
+
if (!tmpchrs) {
|
458
|
+
curl_easy_cleanup(curl_handle);
|
459
|
+
rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name");
|
460
|
+
}
|
461
|
+
#else
|
462
|
+
tmpchrs = curl_escape(StringValuePtr(name_utf8), (int)RSTRING_LEN(name_utf8));
|
463
|
+
if (!tmpchrs) {
|
464
|
+
rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name");
|
465
|
+
}
|
466
|
+
#endif
|
467
|
+
|
468
|
+
VALUE escd_name = rb_str_new2(tmpchrs);
|
469
|
+
#ifdef HAVE_CURL_EASY_ESCAPE
|
470
|
+
curl_free(tmpchrs);
|
471
|
+
#else
|
472
|
+
curl_free(tmpchrs);
|
473
|
+
#endif
|
474
|
+
|
475
|
+
VALUE tmpcontent = Qnil;
|
476
|
+
if (rbcpf->content_proc != Qnil) {
|
477
|
+
tmpcontent = rb_funcall(rbcpf->content_proc, idCall, 1, self);
|
478
|
+
} else if (rbcpf->content != Qnil) {
|
479
|
+
tmpcontent = rbcpf->content;
|
480
|
+
} else if (rbcpf->local_file != Qnil) {
|
481
|
+
tmpcontent = rbcpf->local_file;
|
482
|
+
} else if (rbcpf->remote_file != Qnil) {
|
483
|
+
tmpcontent = rbcpf->remote_file;
|
484
|
+
} else {
|
485
|
+
tmpcontent = rb_str_new2("");
|
486
|
+
}
|
487
|
+
if (TYPE(tmpcontent) != T_STRING) {
|
488
|
+
if (rb_respond_to(tmpcontent, rb_intern("to_s")))
|
489
|
+
tmpcontent = rb_funcall(tmpcontent, rb_intern("to_s"), 0);
|
490
|
+
else {
|
491
|
+
#ifdef HAVE_CURL_EASY_ESCAPE
|
492
|
+
curl_easy_cleanup(curl_handle);
|
493
|
+
#endif
|
494
|
+
rb_raise(rb_eRuntimeError,
|
495
|
+
"postfield(%s) is not a string and does not respond_to to_s",
|
496
|
+
RSTRING_PTR(escd_name));
|
487
497
|
}
|
488
|
-
|
498
|
+
}
|
499
|
+
/* Force content to UTF-8 before escaping */
|
500
|
+
VALUE content_utf8 = rb_str_export_to_enc(tmpcontent, rb_utf8_encoding());
|
501
|
+
#ifdef HAVE_CURL_EASY_ESCAPE
|
502
|
+
tmpchrs = curl_easy_escape(curl_handle, StringValuePtr(content_utf8), (int)RSTRING_LEN(content_utf8));
|
503
|
+
if (!tmpchrs) {
|
504
|
+
curl_easy_cleanup(curl_handle);
|
505
|
+
rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content");
|
506
|
+
}
|
507
|
+
#else
|
508
|
+
tmpchrs = curl_escape(StringValuePtr(content_utf8), (int)RSTRING_LEN(content_utf8));
|
509
|
+
if (!tmpchrs) {
|
510
|
+
rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content");
|
511
|
+
}
|
512
|
+
#endif
|
513
|
+
|
514
|
+
VALUE escd_content = rb_str_new2(tmpchrs);
|
515
|
+
#ifdef HAVE_CURL_EASY_ESCAPE
|
516
|
+
curl_free(tmpchrs);
|
517
|
+
curl_easy_cleanup(curl_handle);
|
518
|
+
#else
|
519
|
+
curl_free(tmpchrs);
|
520
|
+
#endif
|
521
|
+
|
522
|
+
result = escd_name;
|
523
|
+
rb_str_cat(result, "=", 1);
|
524
|
+
rb_str_concat(result, escd_content);
|
525
|
+
|
489
526
|
return result;
|
490
527
|
}
|
491
528
|
|
data/ext/extconf.rb
CHANGED
@@ -467,6 +467,8 @@ have_func('rb_thread_blocking_region')
|
|
467
467
|
have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
|
468
468
|
have_header('ruby/io.h')
|
469
469
|
have_func('rb_io_stdio_file')
|
470
|
+
have_func('curl_multi_wait')
|
471
|
+
have_func('curl_easy_duphandle')
|
470
472
|
|
471
473
|
create_header('curb_config.h')
|
472
474
|
create_makefile('curb_core')
|
data/lib/curl/multi.rb
CHANGED
@@ -95,7 +95,7 @@ module Curl
|
|
95
95
|
|
96
96
|
# configure the multi handle
|
97
97
|
multi_options.each { |k,v| m.send("#{k}=", v) }
|
98
|
-
callbacks = [:on_progress,:on_debug,:on_failure,:on_success,:on_redirect,:on_body,:on_header]
|
98
|
+
callbacks = [:on_progress,:on_debug,:on_failure,:on_success,:on_redirect,:on_missing,:on_body,:on_header]
|
99
99
|
|
100
100
|
add_free_handle = proc do|conf, easy|
|
101
101
|
c = conf.dup # avoid being destructive to input
|
data/tests/helper.rb
CHANGED
@@ -80,6 +80,10 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
80
80
|
res.status = 404
|
81
81
|
elsif req.path.match(/error$/)
|
82
82
|
res.status = 500
|
83
|
+
elsif req.path.match(/get_cookies$/)
|
84
|
+
res['Content-Type'] = "text/plain"
|
85
|
+
res.body = req['Cookie']
|
86
|
+
return
|
83
87
|
end
|
84
88
|
respond_with("GET#{req.query_string}",req,res)
|
85
89
|
end
|
@@ -90,7 +94,18 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
90
94
|
end
|
91
95
|
|
92
96
|
def do_POST(req,res)
|
93
|
-
if req.
|
97
|
+
if req.path.match(/set_cookies$/)
|
98
|
+
JSON.parse(req.body || '[]', symbolize_names: true).each do |hash|
|
99
|
+
cookie = WEBrick::Cookie.new(hash.fetch(:name), hash.fetch(:value))
|
100
|
+
cookie.domain = hash[:domain] if hash.key?(:domain)
|
101
|
+
cookie.expires = hash[:expires] if hash.key?(:expires)
|
102
|
+
cookie.path = hash[:path] if hash.key?(:path)
|
103
|
+
cookie.secure = hash[:secure] if hash.key?(:secure)
|
104
|
+
cookie.max_age = hash[:max_age] if hash.key?(:max_age)
|
105
|
+
res.cookies.push(cookie)
|
106
|
+
end
|
107
|
+
respond_with('OK', req, res)
|
108
|
+
elsif req.query['filename'].nil?
|
94
109
|
if req.body
|
95
110
|
params = {}
|
96
111
|
req.body.split('&').map{|s| k,v=s.split('='); params[k] = v }
|
data/tests/tc_curl_easy.rb
CHANGED
@@ -110,7 +110,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def test_class_perform_02
|
113
|
-
data =
|
113
|
+
data = String.new
|
114
114
|
assert_instance_of Curl::Easy, c = Curl::Easy.perform($TEST_URL) { |curl| curl.on_body { |d| data << d; d.length } }
|
115
115
|
|
116
116
|
assert_nil c.body_str
|
@@ -211,7 +211,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
211
211
|
end
|
212
212
|
|
213
213
|
def test_get_02
|
214
|
-
data =
|
214
|
+
data = String.new
|
215
215
|
c = Curl::Easy.new($TEST_URL) do |curl|
|
216
216
|
curl.on_body { |d| data << d; d.length }
|
217
217
|
end
|
@@ -1068,13 +1068,13 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
1068
1068
|
end
|
1069
1069
|
|
1070
1070
|
def test_easy_http_verbs_must_respond_to_str
|
1071
|
-
# issue http://github.com/taf2/curb/issues
|
1071
|
+
# issue http://github.com/taf2/curb/issues/45
|
1072
1072
|
assert_nothing_raised do
|
1073
|
-
c = Curl::Easy.new ; c.url =
|
1073
|
+
c = Curl::Easy.new ; c.url = TestServlet.url ; c.http(:get)
|
1074
1074
|
end
|
1075
1075
|
|
1076
1076
|
assert_raise RuntimeError do
|
1077
|
-
c = Curl::Easy.new ; c.url =
|
1077
|
+
c = Curl::Easy.new ; c.url = TestServlet.url ; c.http(FooNoToS.new)
|
1078
1078
|
end
|
1079
1079
|
|
1080
1080
|
end
|
@@ -0,0 +1,277 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class TestCurbCurlEasyCookielist < Test::Unit::TestCase
|
5
|
+
def test_setopt_cookielist
|
6
|
+
easy = Curl::Easy.new
|
7
|
+
# DateTime handles time zone correctly
|
8
|
+
expires = (Date.today + 2).to_datetime
|
9
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: c1=v1; domain=localhost; expires=#{expires.httpdate};")
|
10
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, 'Set-Cookie: c2=v2; domain=localhost')
|
11
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: c3=v3; expires=#{expires.httpdate};")
|
12
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, 'Set-Cookie: c4=v4;')
|
13
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: c5=v5; domain=127.0.0.1; expires=#{expires.httpdate};")
|
14
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, 'Set-Cookie: c6=v6; domain=127.0.0.1;;')
|
15
|
+
|
16
|
+
# Since 7.43.0 cookies that were imported in the Set-Cookie format without a domain name are not exported by this option.
|
17
|
+
# So, before 7.43.0, c3 and c4 will be exported too; but that version is far too old for current curb version, so it's not handled here.
|
18
|
+
if Curl::CURL_VERSION.to_f > 8
|
19
|
+
expected_cookielist = [
|
20
|
+
".127.0.0.1\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc5\tv5",
|
21
|
+
".127.0.0.1\tTRUE\t/\tFALSE\t0\tc6\tv6",
|
22
|
+
".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc1\tv1",
|
23
|
+
".localhost\tTRUE\t/\tFALSE\t0\tc2\tv2",
|
24
|
+
]
|
25
|
+
else
|
26
|
+
expected_cookielist = [
|
27
|
+
"127.0.0.1\tFALSE\t/\tFALSE\t#{expires.to_time.to_i}\tc5\tv5",
|
28
|
+
"127.0.0.1\tFALSE\t/\tFALSE\t0\tc6\tv6",
|
29
|
+
".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc1\tv1",
|
30
|
+
".localhost\tTRUE\t/\tFALSE\t0\tc2\tv2",
|
31
|
+
]
|
32
|
+
end
|
33
|
+
assert_equal expected_cookielist, easy.cookielist
|
34
|
+
|
35
|
+
easy.url = "#{TestServlet.url}/get_cookies"
|
36
|
+
easy.perform
|
37
|
+
assert_equal 'c6=v6; c5=v5; c4=v4; c3=v3', easy.body_str
|
38
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
|
39
|
+
easy.perform
|
40
|
+
assert_equal 'c2=v2; c1=v1', easy.body_str
|
41
|
+
end
|
42
|
+
|
43
|
+
# libcurl documentation says: "This option also enables the cookie engine", but it's not tracked on the curb level
|
44
|
+
def test_setopt_cookielist_enables_cookie_engine
|
45
|
+
easy = Curl::Easy.new
|
46
|
+
expires = (Date.today + 2).to_datetime
|
47
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/set_cookies"
|
48
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: c1=v1; domain=localhost; expires=#{expires.httpdate};")
|
49
|
+
easy.post_body = JSON.generate([{ name: 'c2', value: 'v2', domain: 'localhost', expires: expires.httpdate, path: '/' }])
|
50
|
+
easy.perform
|
51
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
|
52
|
+
easy.post_body = nil
|
53
|
+
easy.perform
|
54
|
+
|
55
|
+
assert !easy.enable_cookies?
|
56
|
+
assert_equal [".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc1\tv1", ".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc2\tv2"], easy.cookielist
|
57
|
+
assert_equal 'c2=v2; c1=v1', easy.body_str
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_setopt_cookielist_invalid_format
|
61
|
+
easy = Curl::Easy.new
|
62
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
|
63
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, 'Not a cookie')
|
64
|
+
assert_nil easy.cookielist
|
65
|
+
easy.perform
|
66
|
+
assert_equal '', easy.body_str
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_setopt_cookielist_netscape_format
|
70
|
+
easy = Curl::Easy.new
|
71
|
+
expires = (Date.today + 2).to_datetime
|
72
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
|
73
|
+
# Note domain changes for include subdomains
|
74
|
+
[
|
75
|
+
['localhost', 'FALSE', '/', 'TRUE', 0, 'session_http_only', '42'].join("\t"),
|
76
|
+
['.localhost', 'TRUE', '/', 'FALSE', 0, 'session', '43'].join("\t"),
|
77
|
+
['localhost', 'TRUE', '/', 'FALSE', expires.to_time.to_i, 'permanent', '44'].join("\t"),
|
78
|
+
['.localhost', 'FALSE', '/', 'TRUE', expires.to_time.to_i, 'permanent_http_only', '45'].join("\t"),
|
79
|
+
].each { |cookie| easy.setopt(Curl::CURLOPT_COOKIELIST, cookie) }
|
80
|
+
|
81
|
+
expected_cookielist = [
|
82
|
+
['localhost', 'FALSE', '/', 'TRUE', 0, 'session_http_only', '42'].join("\t"),
|
83
|
+
['.localhost', 'TRUE', '/', 'FALSE', 0, 'session', '43'].join("\t"),
|
84
|
+
['.localhost', 'TRUE', '/', 'FALSE', expires.to_time.to_i, 'permanent', '44'].join("\t"),
|
85
|
+
['localhost', 'FALSE', '/', 'TRUE', expires.to_time.to_i, 'permanent_http_only', '45'].join("\t"),
|
86
|
+
]
|
87
|
+
assert_equal expected_cookielist, easy.cookielist
|
88
|
+
easy.perform
|
89
|
+
assert_equal 'permanent_http_only=45; session_http_only=42; permanent=44; session=43', easy.body_str
|
90
|
+
end
|
91
|
+
|
92
|
+
# Multiple cookies and comments are not supported
|
93
|
+
def test_setopt_cookielist_netscape_format_mutliline
|
94
|
+
easy = Curl::Easy.new
|
95
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
|
96
|
+
easy.setopt(
|
97
|
+
Curl::CURLOPT_COOKIELIST,
|
98
|
+
[
|
99
|
+
'# Netscape HTTP Cookie File',
|
100
|
+
['.localhost', 'TRUE', '/', 'FALSE', 0, 'session', '42'].join("\t"),
|
101
|
+
'',
|
102
|
+
].join("\n"),
|
103
|
+
)
|
104
|
+
assert_nil easy.cookielist
|
105
|
+
easy.perform
|
106
|
+
assert_equal '', easy.body_str
|
107
|
+
|
108
|
+
easy.setopt(
|
109
|
+
Curl::CURLOPT_COOKIELIST,
|
110
|
+
[
|
111
|
+
['.localhost', 'TRUE', '/', 'FALSE', 0, 'session', '42'].join("\t"),
|
112
|
+
['.localhost', 'TRUE', '/', 'FALSE', 0, 'session2', '84'].join("\t"),
|
113
|
+
'',
|
114
|
+
].join("\n"),
|
115
|
+
)
|
116
|
+
# Only first cookie is set
|
117
|
+
assert_equal [".localhost\tTRUE\t/\tFALSE\t0\tsession\t42"], easy.cookielist
|
118
|
+
easy.perform
|
119
|
+
assert_equal 'session=42', easy.body_str
|
120
|
+
end
|
121
|
+
|
122
|
+
# ALL erases all cookies held in memory
|
123
|
+
# ALL was added in 7.14.1
|
124
|
+
def test_setopt_cookielist_command_all
|
125
|
+
expires = (Date.today + 2).to_datetime
|
126
|
+
with_permanent_and_session_cookies(expires) do |easy|
|
127
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, 'ALL')
|
128
|
+
assert_nil easy.cookielist
|
129
|
+
easy.perform
|
130
|
+
assert_equal '', easy.body_str
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# SESS erases all session cookies held in memory
|
135
|
+
# SESS was added in 7.15.4
|
136
|
+
def test_setopt_cookielist_command_sess
|
137
|
+
expires = (Date.today + 2).to_datetime
|
138
|
+
with_permanent_and_session_cookies(expires) do |easy|
|
139
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, 'SESS')
|
140
|
+
assert_equal [".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tpermanent\t42"], easy.cookielist
|
141
|
+
easy.perform
|
142
|
+
assert_equal 'permanent=42', easy.body_str
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# FLUSH writes all known cookies to the file specified by CURLOPT_COOKIEJAR
|
147
|
+
# FLUSH was added in 7.17.1
|
148
|
+
def test_setopt_cookielist_command_flush
|
149
|
+
expires = (Date.today + 2).to_datetime
|
150
|
+
with_permanent_and_session_cookies(expires) do |easy|
|
151
|
+
cookiejar = File.join(Dir.tmpdir, 'curl_test_cookiejar')
|
152
|
+
assert !File.exist?(cookiejar)
|
153
|
+
begin
|
154
|
+
easy.cookiejar = cookiejar
|
155
|
+
# trick to actually set CURLOPT_COOKIEJAR
|
156
|
+
easy.enable_cookies = true
|
157
|
+
easy.perform
|
158
|
+
assert !File.exist?(cookiejar)
|
159
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, 'FLUSH')
|
160
|
+
expected_cookiejar = <<~COOKIEJAR
|
161
|
+
# Netscape HTTP Cookie File
|
162
|
+
# https://curl.se/docs/http-cookies.html
|
163
|
+
# This file was generated by libcurl! Edit at your own risk.
|
164
|
+
|
165
|
+
.localhost TRUE / FALSE 0 session 420
|
166
|
+
.localhost TRUE / FALSE #{expires.to_time.to_i} permanent 42
|
167
|
+
COOKIEJAR
|
168
|
+
assert_equal expected_cookiejar, File.read(cookiejar)
|
169
|
+
ensure
|
170
|
+
# Otherwise it'll create this file again
|
171
|
+
easy.close
|
172
|
+
File.unlink(cookiejar) if File.exist?(cookiejar)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# RELOAD loads all cookies from the files specified by CURLOPT_COOKIEFILE
|
178
|
+
# RELOAD was added in 7.39.0
|
179
|
+
def test_setopt_cookielist_command_reload
|
180
|
+
expires = (Date.today + 2).to_datetime
|
181
|
+
expires_file = (Date.today + 4).to_datetime
|
182
|
+
with_permanent_and_session_cookies(expires) do |easy|
|
183
|
+
cookiefile = File.join(Dir.tmpdir, 'curl_test_cookiefile')
|
184
|
+
assert !File.exist?(cookiefile)
|
185
|
+
begin
|
186
|
+
cookielist = [
|
187
|
+
# Won't be updated, added instead
|
188
|
+
".localhost\tTRUE\t/\tFALSE\t#{expires_file.to_time.to_i}\tpermanent\t84",
|
189
|
+
".localhost\tTRUE\t/\tFALSE\t#{expires_file.to_time.to_i}\tpermanent_file\t84",
|
190
|
+
# Won't be updated, added instead
|
191
|
+
".localhost\tTRUE\t/\tFALSE\t0\tsession\t840",
|
192
|
+
".localhost\tTRUE\t/\tFALSE\t0\tsession_file\t840",
|
193
|
+
'',
|
194
|
+
]
|
195
|
+
File.write(cookiefile, cookielist.join("\n"))
|
196
|
+
easy.cookiefile = cookiefile
|
197
|
+
# trick to actually set CURLOPT_COOKIEFILE
|
198
|
+
easy.enable_cookies = true
|
199
|
+
easy.perform
|
200
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, 'RELOAD')
|
201
|
+
expected_cookielist = [
|
202
|
+
".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tpermanent\t42",
|
203
|
+
".localhost\tTRUE\t/\tFALSE\t0\tsession\t420",
|
204
|
+
".localhost\tTRUE\t/\tFALSE\t#{expires_file.to_time.to_i}\tpermanent\t84",
|
205
|
+
".localhost\tTRUE\t/\tFALSE\t#{expires_file.to_time.to_i}\tpermanent_file\t84",
|
206
|
+
".localhost\tTRUE\t/\tFALSE\t0\tsession\t840",
|
207
|
+
".localhost\tTRUE\t/\tFALSE\t0\tsession_file\t840",
|
208
|
+
]
|
209
|
+
assert_equal expected_cookielist, easy.cookielist
|
210
|
+
easy.perform
|
211
|
+
# Be careful, duplicates are not removed
|
212
|
+
assert_equal 'permanent_file=84; session_file=840; permanent=84; session=840; permanent=42; session=420', easy.body_str
|
213
|
+
ensure
|
214
|
+
File.unlink(cookiefile) if File.exist?(cookiefile)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_commands_do_not_enable_cookie_engine
|
220
|
+
%w[ALL SESS FLUSH RELOAD].each do |command|
|
221
|
+
easy = Curl::Easy.new
|
222
|
+
expires = (Date.today + 2).to_datetime
|
223
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/set_cookies"
|
224
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, command)
|
225
|
+
easy.post_body = JSON.generate([{ name: 'c2', value: 'v2', domain: 'localhost', expires: expires.httpdate, path: '/' }])
|
226
|
+
easy.perform
|
227
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
|
228
|
+
easy.post_body = nil
|
229
|
+
easy.perform
|
230
|
+
|
231
|
+
assert !easy.enable_cookies?
|
232
|
+
assert_nil easy.cookielist
|
233
|
+
assert_equal '', easy.body_str
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
def test_strings_without_cookie_enable_cookie_engine
|
239
|
+
[
|
240
|
+
'',
|
241
|
+
'# Netscape HTTP Cookie File',
|
242
|
+
'no_a_cookie',
|
243
|
+
].each do |command|
|
244
|
+
easy = Curl::Easy.new
|
245
|
+
expires = (Date.today + 2).to_datetime
|
246
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/set_cookies"
|
247
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, command)
|
248
|
+
easy.post_body = JSON.generate([{ name: 'c2', value: 'v2', domain: 'localhost', expires: expires.httpdate, path: '/' }])
|
249
|
+
easy.perform
|
250
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
|
251
|
+
easy.post_body = nil
|
252
|
+
easy.perform
|
253
|
+
|
254
|
+
assert !easy.enable_cookies?
|
255
|
+
assert_equal [".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc2\tv2"], easy.cookielist
|
256
|
+
assert_equal 'c2=v2', easy.body_str
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def with_permanent_and_session_cookies(expires)
|
261
|
+
easy = Curl::Easy.new
|
262
|
+
easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
|
263
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: permanent=42; domain=localhost; expires=#{expires.httpdate};")
|
264
|
+
easy.setopt(Curl::CURLOPT_COOKIELIST, 'Set-Cookie: session=420; domain=localhost;')
|
265
|
+
assert_equal [".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tpermanent\t42", ".localhost\tTRUE\t/\tFALSE\t0\tsession\t420"], easy.cookielist
|
266
|
+
easy.perform
|
267
|
+
assert_equal 'permanent=42; session=420', easy.body_str
|
268
|
+
|
269
|
+
yield easy
|
270
|
+
end
|
271
|
+
|
272
|
+
include TestServerMethods
|
273
|
+
|
274
|
+
def setup
|
275
|
+
server_setup
|
276
|
+
end
|
277
|
+
end
|
data/tests/tc_curl_multi.rb
CHANGED
@@ -13,7 +13,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
13
13
|
# this test fails with libcurl 7.22.0. I didn't investigate, but it may be related
|
14
14
|
# to CURLOPT_MAXCONNECTS bug fixed in 7.30.0:
|
15
15
|
# https://github.com/curl/curl/commit/e87e76e2dc108efb1cae87df496416f49c55fca0
|
16
|
-
omit("Skip, libcurl too old (< 7.22.0)") if Curl::CURL_VERSION.split('.')[1].to_i <= 22
|
16
|
+
omit("Skip, libcurl too old (< 7.22.0)") if Curl::CURL_VERSION.to_f < 8 && Curl::CURL_VERSION.split('.')[1].to_i <= 22
|
17
17
|
|
18
18
|
@server.shutdown if @server
|
19
19
|
@test_thread.kill if @test_thread
|
@@ -114,13 +114,13 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def test_new_multi_01
|
117
|
-
d1 =
|
117
|
+
d1 = String.new
|
118
118
|
c1 = Curl::Easy.new($TEST_URL) do |curl|
|
119
119
|
curl.headers["User-Agent"] = "myapp-0.0"
|
120
120
|
curl.on_body {|d| d1 << d; d.length }
|
121
121
|
end
|
122
122
|
|
123
|
-
d2 =
|
123
|
+
d2 = String.new
|
124
124
|
c2 = Curl::Easy.new($TEST_URL) do |curl|
|
125
125
|
curl.headers["User-Agent"] = "myapp-0.0"
|
126
126
|
curl.on_body {|d| d2 << d; d.length }
|
@@ -186,7 +186,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
186
186
|
rescue Curl::Err::AbortedByCallbackError => e
|
187
187
|
did_raise = true
|
188
188
|
in_file = e.backtrace.detect {|err| err.match?(File.basename(__FILE__)) }
|
189
|
-
in_file_stack = e.backtrace.select {|err| err.match?(File.basename(__FILE__)) }
|
189
|
+
#in_file_stack = e.backtrace.select {|err| err.match?(File.basename(__FILE__)) }
|
190
190
|
assert_match(__FILE__, in_file)
|
191
191
|
in_file.gsub!(__FILE__)
|
192
192
|
parts = in_file.split(':')
|
@@ -206,7 +206,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
206
206
|
m = Curl::Multi.new
|
207
207
|
responses = []
|
208
208
|
n.times do|i|
|
209
|
-
responses[i] =
|
209
|
+
responses[i] = String.new
|
210
210
|
c = Curl::Easy.new($TEST_URL) do|curl|
|
211
211
|
curl.on_body{|data| responses[i] << data; data.size }
|
212
212
|
end
|
@@ -230,7 +230,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
230
230
|
5.times do|it|
|
231
231
|
responses = []
|
232
232
|
n.times do|i|
|
233
|
-
responses[i] =
|
233
|
+
responses[i] = String.new
|
234
234
|
c = Curl::Easy.new($TEST_URL) do|curl|
|
235
235
|
curl.on_body{|data| responses[i] << data; data.size }
|
236
236
|
end
|
@@ -376,7 +376,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
376
376
|
attr_reader :buf
|
377
377
|
|
378
378
|
def t_method
|
379
|
-
@buf =
|
379
|
+
@buf = String.new
|
380
380
|
@m = Curl::Multi.new
|
381
381
|
10.times do|i|
|
382
382
|
c = Curl::Easy.new($TEST_URL)
|
@@ -422,8 +422,8 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
422
422
|
m = Curl::Multi.new
|
423
423
|
# add a few easy handles
|
424
424
|
requests.each do |url|
|
425
|
-
responses[url] =
|
426
|
-
responses["#{url}-header"] =
|
425
|
+
responses[url] = String.new
|
426
|
+
responses["#{url}-header"] = String.new
|
427
427
|
c = Curl::Easy.new(url) do|curl|
|
428
428
|
curl.follow_location = true
|
429
429
|
curl.on_header{|data| responses["#{url}-header"] << data; data.size }
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: curb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ross Bamford
|
8
8
|
- Todd A. Fisher
|
9
|
-
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2025-02-09 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description: Curb (probably CUrl-RuBy or something) provides Ruby-language bindings
|
15
14
|
for the libcurl(3), a fully-featured client-side URL transfer library. cURL and
|
@@ -53,7 +52,6 @@ files:
|
|
53
52
|
- tests/bug_follow_redirect_288.rb
|
54
53
|
- tests/bug_instance_post_differs_from_class_post.rb
|
55
54
|
- tests/bug_issue102.rb
|
56
|
-
- tests/bug_issue277.rb
|
57
55
|
- tests/bug_multi_segfault.rb
|
58
56
|
- tests/bug_postfields_crash.rb
|
59
57
|
- tests/bug_postfields_crash2.rb
|
@@ -67,6 +65,7 @@ files:
|
|
67
65
|
- tests/tc_curl.rb
|
68
66
|
- tests/tc_curl_download.rb
|
69
67
|
- tests/tc_curl_easy.rb
|
68
|
+
- tests/tc_curl_easy_cookielist.rb
|
70
69
|
- tests/tc_curl_easy_resolve.rb
|
71
70
|
- tests/tc_curl_easy_setopt.rb
|
72
71
|
- tests/tc_curl_maxfilesize.rb
|
@@ -78,9 +77,8 @@ files:
|
|
78
77
|
- tests/unittests.rb
|
79
78
|
homepage: https://github.com/taf2/curb
|
80
79
|
licenses:
|
81
|
-
-
|
80
|
+
- Ruby
|
82
81
|
metadata: {}
|
83
|
-
post_install_message:
|
84
82
|
rdoc_options:
|
85
83
|
- "--main"
|
86
84
|
- README.markdown
|
@@ -98,8 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
96
|
- !ruby/object:Gem::Version
|
99
97
|
version: '0'
|
100
98
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
102
|
-
signing_key:
|
99
|
+
rubygems_version: 3.6.2
|
103
100
|
specification_version: 4
|
104
101
|
summary: Ruby libcurl bindings
|
105
102
|
test_files:
|
@@ -111,7 +108,6 @@ test_files:
|
|
111
108
|
- tests/bug_follow_redirect_288.rb
|
112
109
|
- tests/bug_instance_post_differs_from_class_post.rb
|
113
110
|
- tests/bug_issue102.rb
|
114
|
-
- tests/bug_issue277.rb
|
115
111
|
- tests/bug_multi_segfault.rb
|
116
112
|
- tests/bug_postfields_crash.rb
|
117
113
|
- tests/bug_postfields_crash2.rb
|
@@ -125,6 +121,7 @@ test_files:
|
|
125
121
|
- tests/tc_curl.rb
|
126
122
|
- tests/tc_curl_download.rb
|
127
123
|
- tests/tc_curl_easy.rb
|
124
|
+
- tests/tc_curl_easy_cookielist.rb
|
128
125
|
- tests/tc_curl_easy_resolve.rb
|
129
126
|
- tests/tc_curl_easy_setopt.rb
|
130
127
|
- tests/tc_curl_maxfilesize.rb
|
data/tests/bug_issue277.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
-
|
3
|
-
|
4
|
-
require 'curb'
|
5
|
-
|
6
|
-
class BugIssue102 < Test::Unit::TestCase
|
7
|
-
|
8
|
-
def test_gc_closewait
|
9
|
-
100.times do
|
10
|
-
responses = {}
|
11
|
-
requests = ["http://www.google.co.uk/", "http://www.ruby-lang.org/"]
|
12
|
-
m = Curl::Multi.new
|
13
|
-
# add a few easy handles
|
14
|
-
requests.each do |url|
|
15
|
-
responses[url] = ""
|
16
|
-
c = Curl::Easy.new(url) do|curl|
|
17
|
-
curl.follow_location = true
|
18
|
-
curl.on_body{|data| responses[url] << data; data.size }
|
19
|
-
curl.on_success {|easy| #puts "success, add more easy handles"
|
20
|
-
}
|
21
|
-
end
|
22
|
-
m.add(c)
|
23
|
-
end
|
24
|
-
|
25
|
-
m.perform do
|
26
|
-
#puts "idling... can do some work here"
|
27
|
-
end
|
28
|
-
GC.start
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|