curb 1.0.7 → 1.0.9
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.markdown +116 -16
- data/Rakefile +4 -0
- data/ext/curb.h +3 -3
- data/ext/curb_easy.c +141 -6
- data/lib/curl/easy.rb +26 -3
- data/tests/bug_issue277.rb +32 -0
- data/tests/tc_curl_easy.rb +62 -14
- data/tests/tc_curl_postfield.rb +2 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0105bb19d8f3c70c7b16dc47ede5eef29b26d78a765b6ab9ac19c81dc34c647a
|
4
|
+
data.tar.gz: 8bb7441583b1caa916969f4a7aad3785777de7912347f6c454bb110c4ab50b08
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9d63ab6203a5d37fe3ef02b081f92afa9ece68acdde249d6f3e09fd21fec5fd1342fa6e2fcbfb6fc58a6fd5ad2fce44fd0915d0b0bd31902cc9c5aef976d250
|
7
|
+
data.tar.gz: cb9f110ebeddb88eddc31d9cf1985148365c6abe5a378e2ea157414dd7bc96c59b2b2883ba0b21ac1569d82ee4bc8744cfbeaae1eaae07245c81a146bae78510
|
data/README.markdown
CHANGED
@@ -37,6 +37,103 @@ POST request
|
|
37
37
|
puts res.body
|
38
38
|
```
|
39
39
|
|
40
|
+
## FTP Support
|
41
|
+
|
42
|
+
require 'curb'
|
43
|
+
|
44
|
+
### Basic FTP Download
|
45
|
+
```ruby
|
46
|
+
puts "=== FTP Download Example ==="
|
47
|
+
ftp = Curl::Easy.new('ftp://ftp.example.com/remote/file.txt')
|
48
|
+
ftp.username = 'user'
|
49
|
+
ftp.password = 'password'
|
50
|
+
ftp.perform
|
51
|
+
puts ftp.body
|
52
|
+
```
|
53
|
+
|
54
|
+
### FTP Upload
|
55
|
+
```ruby
|
56
|
+
puts "\n=== FTP Upload Example ==="
|
57
|
+
upload = Curl::Easy.new('ftp://ftp.example.com/remote/upload.txt')
|
58
|
+
upload.username = 'user'
|
59
|
+
upload.password = 'password'
|
60
|
+
upload.upload = true
|
61
|
+
upload.put_data = File.read('local_file.txt')
|
62
|
+
upload.perform
|
63
|
+
```
|
64
|
+
|
65
|
+
### List Directory Contents
|
66
|
+
```ruby
|
67
|
+
puts "\n=== FTP Directory Listing Example ==="
|
68
|
+
list = Curl::Easy.new('ftp://ftp.example.com/remote/directory/')
|
69
|
+
list.username = 'user'
|
70
|
+
list.password = 'password'
|
71
|
+
list.dirlistonly = true
|
72
|
+
list.perform
|
73
|
+
puts list.body
|
74
|
+
```
|
75
|
+
|
76
|
+
### Advanced FTP Usage with Various Options
|
77
|
+
```
|
78
|
+
puts "\n=== Advanced FTP Example ==="
|
79
|
+
advanced = Curl::Easy.new do |curl|
|
80
|
+
curl.url = 'ftp://ftp.example.com/remote/file.txt'
|
81
|
+
curl.username = 'user'
|
82
|
+
curl.password = 'password'
|
83
|
+
|
84
|
+
# FTP Options
|
85
|
+
curl.ftp_response_timeout = 30
|
86
|
+
curl.ftp_create_missing_dirs = true # Create directories if they don't exist
|
87
|
+
curl.ftp_filemethod = Curl::CURL_MULTICWD # Use multicwd method for traversing paths
|
88
|
+
|
89
|
+
# SSL/TLS Options for FTPS
|
90
|
+
curl.use_ssl = Curl::CURLUSESSL_ALL # Use SSL/TLS for control and data
|
91
|
+
curl.ssl_verify_peer = true
|
92
|
+
curl.ssl_verify_host = true
|
93
|
+
curl.cacert = "/path/to/cacert.pem"
|
94
|
+
|
95
|
+
# Progress callback
|
96
|
+
curl.on_progress do |dl_total, dl_now, ul_total, ul_now|
|
97
|
+
puts "Download: #{dl_now}/#{dl_total} Upload: #{ul_now}/#{ul_total}"
|
98
|
+
true # must return true to continue
|
99
|
+
end
|
100
|
+
|
101
|
+
# Debug output
|
102
|
+
curl.verbose = true
|
103
|
+
curl.on_debug do |type, data|
|
104
|
+
puts "#{type}: #{data}"
|
105
|
+
true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
advanced.perform
|
110
|
+
```
|
111
|
+
|
112
|
+
### Parallel FTP Downloads
|
113
|
+
```
|
114
|
+
puts "\n=== Parallel FTP Downloads Example ==="
|
115
|
+
urls = [
|
116
|
+
'ftp://ftp.example.com/file1.txt',
|
117
|
+
'ftp://ftp.example.com/file2.txt',
|
118
|
+
'ftp://ftp.example.com/file3.txt'
|
119
|
+
]
|
120
|
+
```
|
121
|
+
|
122
|
+
### Common options for all connections
|
123
|
+
```
|
124
|
+
options = {
|
125
|
+
:username => 'user',
|
126
|
+
:password => 'password',
|
127
|
+
:timeout => 30,
|
128
|
+
:on_success => proc { |easy| puts "Successfully downloaded: #{easy.url}" },
|
129
|
+
:on_failure => proc { |easy, code| puts "Failed to download: #{easy.url} (#{code})" }
|
130
|
+
}
|
131
|
+
|
132
|
+
Curl::Multi.download(urls, options) do |curl, file_path|
|
133
|
+
puts "Completed downloading to: #{file_path}"
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
40
137
|
## You will need
|
41
138
|
|
42
139
|
* A working Ruby installation (`2.0.0+` will work but `2.1+` preferred) (it's possible it still works with 1.8.7 but you'd have to tell me if not...)
|
@@ -50,20 +147,23 @@ A **non-exhaustive** set of compatibility versions of the libcurl library
|
|
50
147
|
with this gem are as follows. (Note that these are only the ones that have been
|
51
148
|
tested and reported to work across a variety of platforms / rubies)
|
52
149
|
|
53
|
-
| Gem Version | Release Date
|
54
|
-
| ----------- |
|
55
|
-
| 1.0.
|
56
|
-
| 1.0.
|
57
|
-
| 1.0.
|
58
|
-
| 1.0.
|
59
|
-
| 1.0.
|
60
|
-
| 1.0.
|
61
|
-
| 0.
|
62
|
-
| 0.
|
63
|
-
| 0.
|
64
|
-
| 0.9.
|
65
|
-
| 0.9.
|
66
|
-
| 0.9.
|
150
|
+
| Gem Version | Release Date | libcurl versions |
|
151
|
+
| ----------- | -------------- | ----------------- |
|
152
|
+
| 1.0.8 | Feb 10, 2025 | 7.58 – 8.12.1 |
|
153
|
+
| 1.0.7 | Feb 09, 2025 | 7.58 – 8.12.1 |
|
154
|
+
| 1.0.6 | Aug 23, 2024 | 7.58 – 8.12.1 |
|
155
|
+
| 1.0.5 | Jan 2023 | 7.58 – 8.12.1 |
|
156
|
+
| 1.0.4 | Jan 2023 | 7.58 – 8.12.1 |
|
157
|
+
| 1.0.3* | Dec 2022 | 7.58 – 8.12.1 |
|
158
|
+
| 1.0.2* | Dec 2022 | 7.58 – 8.12.1 |
|
159
|
+
| 1.0.1 | Apr 2022 | 7.58 – 8.12.1 |
|
160
|
+
| 1.0.0 | Jan 2022 | 7.58 – 8.12.1 |
|
161
|
+
| 0.9.8 | Jan 2019 | 7.58 – 7.81 |
|
162
|
+
| 0.9.7 | Nov 2018 | 7.56 – 7.60 |
|
163
|
+
| 0.9.6 | May 2018 | 7.51 – 7.59 |
|
164
|
+
| 0.9.5 | May 2018 | 7.51 – 7.59 |
|
165
|
+
| 0.9.4 | Aug 2017 | 7.41 – 7.58 |
|
166
|
+
| 0.9.3 | Apr 2016 | 7.26 – 7.58 |
|
67
167
|
|
68
168
|
```*avoid using these version are known to have issues with segmentation faults```
|
69
169
|
|
@@ -215,7 +315,7 @@ c = Curl::Easy.new
|
|
215
315
|
["http://www.google.co.uk", "http://www.ruby-lang.org/"].map do |url|
|
216
316
|
c.url = url
|
217
317
|
c.perform
|
218
|
-
c.
|
318
|
+
c.body
|
219
319
|
end
|
220
320
|
```
|
221
321
|
|
@@ -242,7 +342,7 @@ c = Curl::Easy.new("https://http2.akamai.com")
|
|
242
342
|
c.set(:HTTP_VERSION, Curl::HTTP_2_0)
|
243
343
|
|
244
344
|
c.perform
|
245
|
-
puts (c.
|
345
|
+
puts (c.body.include? "You are using HTTP/2 right now!") ? "HTTP/2" : "HTTP/1.x"
|
246
346
|
```
|
247
347
|
|
248
348
|
### Multi Interface (Basic HTTP GET):
|
data/Rakefile
CHANGED
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.9"
|
32
|
+
#define CURB_VER_NUM 1009
|
33
33
|
#define CURB_VER_MAJ 1
|
34
34
|
#define CURB_VER_MIN 0
|
35
|
-
#define CURB_VER_MIC
|
35
|
+
#define CURB_VER_MIC 9
|
36
36
|
#define CURB_VER_PATCH 0
|
37
37
|
|
38
38
|
|
data/ext/curb_easy.c
CHANGED
@@ -2535,7 +2535,7 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2535
2535
|
rb_iterate(rb_each, rb_easy_get("proxy_headers"), cb_each_http_proxy_header, wrap);
|
2536
2536
|
} else {
|
2537
2537
|
VALUE proxy_headers_str = rb_obj_as_string(rb_easy_get("proxy_headers"));
|
2538
|
-
*phdrs = curl_slist_append(*
|
2538
|
+
*phdrs = curl_slist_append(*phdrs, StringValuePtr(proxy_headers_str));
|
2539
2539
|
}
|
2540
2540
|
|
2541
2541
|
if (*phdrs) {
|
@@ -2758,6 +2758,88 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
|
|
2758
2758
|
}
|
2759
2759
|
}
|
2760
2760
|
|
2761
|
+
/*
|
2762
|
+
* call-seq:
|
2763
|
+
* easy.http_patch("url=encoded%20form%20data;and=so%20on") => true
|
2764
|
+
* easy.http_patch("url=encoded%20form%20data", "and=so%20on", ...) => true
|
2765
|
+
* easy.http_patch("url=encoded%20form%20data", Curl::PostField, "and=so%20on", ...) => true
|
2766
|
+
* easy.http_patch(Curl::PostField, Curl::PostField ..., Curl::PostField) => true
|
2767
|
+
*
|
2768
|
+
* PATCH the specified formdata to the currently configured URL using
|
2769
|
+
* the current options set for this Curl::Easy instance. This method
|
2770
|
+
* always returns true, or raises an exception (defined under
|
2771
|
+
* Curl::Err) on error.
|
2772
|
+
*
|
2773
|
+
* When multipart_form_post is true the multipart logic is used; otherwise,
|
2774
|
+
* the arguments are joined into a raw PATCH body.
|
2775
|
+
*/
|
2776
|
+
static VALUE ruby_curl_easy_perform_patch(int argc, VALUE *argv, VALUE self) {
|
2777
|
+
ruby_curl_easy *rbce;
|
2778
|
+
CURL *curl;
|
2779
|
+
int i;
|
2780
|
+
VALUE args_ary;
|
2781
|
+
|
2782
|
+
rb_scan_args(argc, argv, "*", &args_ary);
|
2783
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2784
|
+
curl = rbce->curl;
|
2785
|
+
|
2786
|
+
/* Clear the error buffer */
|
2787
|
+
memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
|
2788
|
+
|
2789
|
+
/* Set the custom HTTP method to PATCH */
|
2790
|
+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
|
2791
|
+
|
2792
|
+
if (rbce->multipart_form_post) {
|
2793
|
+
VALUE ret;
|
2794
|
+
struct curl_httppost *first = NULL, *last = NULL;
|
2795
|
+
|
2796
|
+
/* Build the multipart form (same logic as for POST) */
|
2797
|
+
for (i = 0; i < argc; i++) {
|
2798
|
+
if (rb_obj_is_instance_of(argv[i], cCurlPostField)) {
|
2799
|
+
append_to_form(argv[i], &first, &last);
|
2800
|
+
} else if (rb_type(argv[i]) == T_ARRAY) {
|
2801
|
+
long j, argv_len = RARRAY_LEN(argv[i]);
|
2802
|
+
for (j = 0; j < argv_len; ++j) {
|
2803
|
+
if (rb_obj_is_instance_of(rb_ary_entry(argv[i], j), cCurlPostField)) {
|
2804
|
+
append_to_form(rb_ary_entry(argv[i], j), &first, &last);
|
2805
|
+
} else {
|
2806
|
+
rb_raise(eCurlErrInvalidPostField,
|
2807
|
+
"You must use PostFields only with multipart form posts");
|
2808
|
+
return Qnil;
|
2809
|
+
}
|
2810
|
+
}
|
2811
|
+
} else {
|
2812
|
+
rb_raise(eCurlErrInvalidPostField,
|
2813
|
+
"You must use PostFields only with multipart form posts");
|
2814
|
+
return Qnil;
|
2815
|
+
}
|
2816
|
+
}
|
2817
|
+
/* Disable the POST flag */
|
2818
|
+
curl_easy_setopt(curl, CURLOPT_POST, 0);
|
2819
|
+
/* Use the built multipart form as the request body */
|
2820
|
+
curl_easy_setopt(curl, CURLOPT_HTTPPOST, first);
|
2821
|
+
ret = rb_funcall(self, rb_intern("perform"), 0);
|
2822
|
+
curl_formfree(first);
|
2823
|
+
return ret;
|
2824
|
+
} else {
|
2825
|
+
/* Join arguments into a raw PATCH body */
|
2826
|
+
VALUE patch_body = rb_funcall(args_ary, idJoin, 1, rbstrAmp);
|
2827
|
+
if (patch_body == Qnil) {
|
2828
|
+
rb_raise(eCurlErrError, "Failed to join arguments");
|
2829
|
+
return Qnil;
|
2830
|
+
} else {
|
2831
|
+
if (rb_type(patch_body) == T_STRING && RSTRING_LEN(patch_body) > 0) {
|
2832
|
+
ruby_curl_easy_post_body_set(self, patch_body);
|
2833
|
+
}
|
2834
|
+
/* If postdata_buffer is still nil, set it so that the PATCH header is enabled */
|
2835
|
+
if (rb_easy_nil("postdata_buffer")) {
|
2836
|
+
ruby_curl_easy_post_body_set(self, patch_body);
|
2837
|
+
}
|
2838
|
+
return rb_funcall(self, rb_intern("perform"), 0);
|
2839
|
+
}
|
2840
|
+
}
|
2841
|
+
}
|
2842
|
+
|
2761
2843
|
/*
|
2762
2844
|
* call-seq:
|
2763
2845
|
* easy.http_put(data) => true
|
@@ -2766,18 +2848,70 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
|
|
2766
2848
|
* current options set for this Curl::Easy instance. This method always
|
2767
2849
|
* returns true, or raises an exception (defined under Curl::Err) on error.
|
2768
2850
|
*/
|
2769
|
-
static VALUE ruby_curl_easy_perform_put(VALUE
|
2851
|
+
static VALUE ruby_curl_easy_perform_put(int argc, VALUE *argv, VALUE self) {
|
2770
2852
|
ruby_curl_easy *rbce;
|
2771
2853
|
CURL *curl;
|
2854
|
+
VALUE args_ary;
|
2855
|
+
int i;
|
2772
2856
|
|
2857
|
+
rb_scan_args(argc, argv, "*", &args_ary);
|
2773
2858
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2774
2859
|
curl = rbce->curl;
|
2775
2860
|
|
2776
2861
|
memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
|
2862
|
+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
|
2777
2863
|
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
2864
|
+
/* New: if no arguments were provided, treat as an empty PUT */
|
2865
|
+
if (RARRAY_LEN(args_ary) == 0) {
|
2866
|
+
/* Option 1: explicitly set an empty body */
|
2867
|
+
ruby_curl_easy_put_data_set(self, rb_str_new2(""));
|
2868
|
+
}
|
2869
|
+
/* If a single argument is given and it is a String or responds to read, use legacy behavior */
|
2870
|
+
else if (RARRAY_LEN(args_ary) == 1 &&
|
2871
|
+
(rb_type(rb_ary_entry(args_ary, 0)) == T_STRING ||
|
2872
|
+
rb_respond_to(rb_ary_entry(args_ary, 0), rb_intern("read")))) {
|
2873
|
+
ruby_curl_easy_put_data_set(self, rb_ary_entry(args_ary, 0));
|
2874
|
+
}
|
2875
|
+
/* Otherwise, if multipart_form_post is true, use multipart logic */
|
2876
|
+
else if (rbce->multipart_form_post) {
|
2877
|
+
VALUE ret;
|
2878
|
+
struct curl_httppost *first = NULL, *last = NULL;
|
2879
|
+
for (i = 0; i < RARRAY_LEN(args_ary); i++) {
|
2880
|
+
VALUE field = rb_ary_entry(args_ary, i);
|
2881
|
+
if (rb_obj_is_instance_of(field, cCurlPostField)) {
|
2882
|
+
append_to_form(field, &first, &last);
|
2883
|
+
} else if (rb_type(field) == T_ARRAY) {
|
2884
|
+
long j;
|
2885
|
+
for (j = 0; j < RARRAY_LEN(field); j++) {
|
2886
|
+
VALUE subfield = rb_ary_entry(field, j);
|
2887
|
+
if (rb_obj_is_instance_of(subfield, cCurlPostField)) {
|
2888
|
+
append_to_form(subfield, &first, &last);
|
2889
|
+
} else {
|
2890
|
+
rb_raise(eCurlErrInvalidPostField,
|
2891
|
+
"You must use PostFields only with multipart form posts");
|
2892
|
+
}
|
2893
|
+
}
|
2894
|
+
} else {
|
2895
|
+
rb_raise(eCurlErrInvalidPostField,
|
2896
|
+
"You must use PostFields only with multipart form posts");
|
2897
|
+
}
|
2898
|
+
}
|
2899
|
+
curl_easy_setopt(curl, CURLOPT_POST, 0);
|
2900
|
+
curl_easy_setopt(curl, CURLOPT_HTTPPOST, first);
|
2901
|
+
/* Set the method explicitly to PUT */
|
2902
|
+
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
|
2903
|
+
ret = rb_funcall(self, rb_intern("perform"), 0);
|
2904
|
+
curl_formfree(first);
|
2905
|
+
return ret;
|
2906
|
+
}
|
2907
|
+
/* Fallback: join all arguments */
|
2908
|
+
else {
|
2909
|
+
VALUE post_body = rb_funcall(args_ary, idJoin, 1, rbstrAmp);
|
2910
|
+
if (post_body != Qnil && rb_type(post_body) == T_STRING &&
|
2911
|
+
RSTRING_LEN(post_body) > 0) {
|
2912
|
+
ruby_curl_easy_put_data_set(self, post_body);
|
2913
|
+
}
|
2914
|
+
}
|
2781
2915
|
return rb_funcall(self, rb_intern("perform"), 0);
|
2782
2916
|
}
|
2783
2917
|
|
@@ -3946,7 +4080,8 @@ void init_curb_easy() {
|
|
3946
4080
|
|
3947
4081
|
rb_define_method(cCurlEasy, "http", ruby_curl_easy_perform_verb, 1);
|
3948
4082
|
rb_define_method(cCurlEasy, "http_post", ruby_curl_easy_perform_post, -1);
|
3949
|
-
rb_define_method(cCurlEasy, "http_put", ruby_curl_easy_perform_put, 1);
|
4083
|
+
rb_define_method(cCurlEasy, "http_put", ruby_curl_easy_perform_put, -1);
|
4084
|
+
rb_define_method(cCurlEasy, "http_patch", ruby_curl_easy_perform_patch, -1);
|
3950
4085
|
|
3951
4086
|
/* Post-perform info methods */
|
3952
4087
|
rb_define_method(cCurlEasy, "body_str", ruby_curl_easy_body_str_get, 0);
|
data/lib/curl/easy.rb
CHANGED
@@ -374,13 +374,36 @@ module Curl
|
|
374
374
|
#
|
375
375
|
# call-seq:
|
376
376
|
# Curl::Easy.http_put(url, data) {|c| ... }
|
377
|
+
# Curl::Easy.http_put(url, "some=urlencoded%20form%20data&and=so%20on") => true
|
378
|
+
# Curl::Easy.http_put(url, "some=urlencoded%20form%20data", "and=so%20on", ...) => true
|
379
|
+
# Curl::Easy.http_put(url, "some=urlencoded%20form%20data", Curl::PostField, "and=so%20on", ...) => true
|
380
|
+
# Curl::Easy.http_put(url, Curl::PostField, Curl::PostField ..., Curl::PostField) => true
|
377
381
|
#
|
378
382
|
# see easy.http_put
|
379
383
|
#
|
380
|
-
def http_put(
|
381
|
-
|
384
|
+
def http_put(*args)
|
385
|
+
url = args.shift
|
386
|
+
c = Curl::Easy.new(url)
|
387
|
+
yield c if block_given?
|
388
|
+
c.http_put(*args)
|
389
|
+
c
|
390
|
+
end
|
391
|
+
|
392
|
+
#
|
393
|
+
# call-seq:
|
394
|
+
# Curl::Easy.http_patch(url, data) {|c| ... }
|
395
|
+
# Curl::Easy.http_patch(url, "some=urlencoded%20form%20data&and=so%20on") => true
|
396
|
+
# Curl::Easy.http_patch(url, "some=urlencoded%20form%20data", "and=so%20on", ...) => true
|
397
|
+
# Curl::Easy.http_patch(url, "some=urlencoded%20form%20data", Curl::PostField, "and=so%20on", ...) => true
|
398
|
+
# Curl::Easy.http_patch(url, Curl::PostField, Curl::PostField ..., Curl::PostField) => true
|
399
|
+
#
|
400
|
+
# see easy.http_patch
|
401
|
+
#
|
402
|
+
def http_patch(*args)
|
403
|
+
url = args.shift
|
404
|
+
c = Curl::Easy.new(url)
|
382
405
|
yield c if block_given?
|
383
|
-
c.
|
406
|
+
c.http_patch(*args)
|
384
407
|
c
|
385
408
|
end
|
386
409
|
|
@@ -0,0 +1,32 @@
|
|
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
|
data/tests/tc_curl_easy.rb
CHANGED
@@ -765,20 +765,27 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
765
765
|
assert_equal 'GET', curl.body_str
|
766
766
|
end
|
767
767
|
|
768
|
-
def
|
768
|
+
def test_remote
|
769
769
|
curl = Curl::Easy.new(TestServlet.url)
|
770
770
|
curl.http_post([Curl::PostField.content('document_id', 5)])
|
771
771
|
assert_equal "POST\ndocument_id=5", curl.unescape(curl.body_str)
|
772
|
+
|
773
|
+
curl.http_put([Curl::PostField.content('document_id', 5)])
|
774
|
+
assert_equal "PUT\ndocument_id=5", curl.unescape(curl.body_str)
|
775
|
+
|
776
|
+
curl.http_patch([Curl::PostField.content('document_id', 5)])
|
777
|
+
assert_equal "PATCH\ndocument_id=5", curl.unescape(curl.body_str)
|
772
778
|
end
|
773
779
|
|
774
|
-
def
|
780
|
+
def test_remote_is_easy_handle
|
775
781
|
# see: http://pastie.org/560852 and
|
776
782
|
# http://groups.google.com/group/curb---ruby-libcurl-bindings/browse_thread/thread/216bb2d9b037f347?hl=en
|
777
|
-
[:post, :get, :head, :delete].each do |method|
|
783
|
+
[:post, :patch, :put, :get, :head, :delete].each do |method|
|
778
784
|
retries = 0
|
779
785
|
begin
|
780
786
|
count = 0
|
781
|
-
|
787
|
+
m = "http_#{method}".to_sym
|
788
|
+
Curl::Easy.send(m, TestServlet.url) do|c|
|
782
789
|
count += 1
|
783
790
|
assert_equal Curl::Easy, c.class
|
784
791
|
end
|
@@ -787,12 +794,14 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
787
794
|
retries+=1
|
788
795
|
retry if retries < 3
|
789
796
|
raise e
|
797
|
+
rescue ArgumentError => e
|
798
|
+
assert false, "#{m} - #{e.message}"
|
790
799
|
end
|
791
800
|
end
|
792
801
|
end
|
793
802
|
|
794
803
|
# see: https://github.com/rvanlieshout/curb/commit/8bcdefddc0162484681ebd1a92d52a642666a445
|
795
|
-
def
|
804
|
+
def test_multipart_array_remote
|
796
805
|
curl = Curl::Easy.new(TestServlet.url)
|
797
806
|
curl.multipart_form_post = true
|
798
807
|
fields = [
|
@@ -802,9 +811,23 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
802
811
|
curl.http_post(fields)
|
803
812
|
assert_match(/HTTP POST file upload/, curl.body_str)
|
804
813
|
assert_match(/Content-Disposition: form-data/, curl.body_str)
|
814
|
+
|
815
|
+
curl = Curl::Easy.new(TestServlet.url)
|
816
|
+
curl.multipart_form_post = true
|
817
|
+
fields = [
|
818
|
+
Curl::PostField.file('foo', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown'))),
|
819
|
+
Curl::PostField.file('bar', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown')))
|
820
|
+
]
|
821
|
+
curl.http_put(fields)
|
822
|
+
assert_match(/HTTP POST file upload/, curl.body_str)
|
823
|
+
assert_match(/Content-Disposition: form-data/, curl.body_str)
|
824
|
+
|
825
|
+
curl.http_patch(fields)
|
826
|
+
assert_match(/HTTP POST file upload/, curl.body_str)
|
827
|
+
assert_match(/Content-Disposition: form-data/, curl.body_str)
|
805
828
|
end
|
806
829
|
|
807
|
-
def
|
830
|
+
def test_with_body_remote
|
808
831
|
curl = Curl::Easy.new(TestServlet.url)
|
809
832
|
curl.post_body = 'foo=bar&encoded%20string=val'
|
810
833
|
|
@@ -812,23 +835,42 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
812
835
|
|
813
836
|
assert_equal "POST\nfoo=bar&encoded%20string=val", curl.body_str
|
814
837
|
assert_equal 'foo=bar&encoded%20string=val', curl.post_body
|
838
|
+
|
839
|
+
curl = Curl::Easy.new(TestServlet.url)
|
840
|
+
curl.put_data = 'foo=bar&encoded%20string=val'
|
841
|
+
|
842
|
+
curl.perform
|
843
|
+
|
844
|
+
assert_equal "PUT\nfoo=bar&encoded%20string=val", curl.body_str
|
815
845
|
end
|
816
846
|
|
817
|
-
def
|
847
|
+
def test_form_body_remote
|
818
848
|
curl = Curl::Easy.new(TestServlet.url)
|
819
849
|
curl.http_post('foo=bar', 'encoded%20string=val')
|
820
850
|
|
821
851
|
assert_equal "POST\nfoo=bar&encoded%20string=val", curl.body_str
|
822
852
|
assert_equal 'foo=bar&encoded%20string=val', curl.post_body
|
823
|
-
end
|
824
853
|
|
825
|
-
def test_post_multipart_file_remote
|
826
854
|
curl = Curl::Easy.new(TestServlet.url)
|
827
|
-
curl.
|
828
|
-
|
829
|
-
curl.
|
830
|
-
|
831
|
-
|
855
|
+
curl.http_put('foo=bar', 'encoded%20string=val')
|
856
|
+
|
857
|
+
assert_equal "PUT\nfoo=bar&encoded%20string=val", curl.body_str
|
858
|
+
|
859
|
+
curl = Curl::Easy.new(TestServlet.url)
|
860
|
+
curl.http_patch('foo=bar', 'encoded%20string=val')
|
861
|
+
|
862
|
+
assert_equal "PATCH\nfoo=bar&encoded%20string=val", curl.body_str
|
863
|
+
end
|
864
|
+
|
865
|
+
def test_multipart_file_remote
|
866
|
+
[:put, :post, :patch].each {|method|
|
867
|
+
curl = Curl::Easy.new(TestServlet.url)
|
868
|
+
curl.multipart_form_post = true
|
869
|
+
pf = Curl::PostField.file('readme', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown')))
|
870
|
+
curl.send("http_#{method}", pf)
|
871
|
+
assert_match(/HTTP POST file upload/, curl.body_str)
|
872
|
+
assert_match(/Content-Disposition: form-data/, curl.body_str)
|
873
|
+
}
|
832
874
|
end
|
833
875
|
|
834
876
|
def test_delete_remote
|
@@ -1065,6 +1107,12 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
1065
1107
|
assert_equal "PUT\nhello", curl.body_str
|
1066
1108
|
curl.http('COPY')
|
1067
1109
|
assert_equal 'COPY', curl.body_str
|
1110
|
+
|
1111
|
+
curl.http_patch
|
1112
|
+
assert_equal "PATCH\n", curl.body_str
|
1113
|
+
|
1114
|
+
curl.http_put
|
1115
|
+
assert_equal "PUT\n", curl.body_str
|
1068
1116
|
end
|
1069
1117
|
|
1070
1118
|
def test_easy_http_verbs_must_respond_to_str
|
data/tests/tc_curl_postfield.rb
CHANGED
@@ -58,12 +58,13 @@ class TestCurbCurlPostfield < Test::Unit::TestCase
|
|
58
58
|
|
59
59
|
def test_new_file_01
|
60
60
|
pf = Curl::PostField.file('foo', 'localname')
|
61
|
+
pf.content_type = 'text/super'
|
61
62
|
|
62
63
|
assert_equal 'foo', pf.name
|
63
64
|
assert_equal 'localname', pf.local_file
|
64
65
|
assert_equal 'localname', pf.remote_file
|
65
66
|
assert_nothing_raised { pf.to_s }
|
66
|
-
|
67
|
+
assert_equal 'text/super', pf.content_type
|
67
68
|
assert_nil pf.content
|
68
69
|
assert_nil pf.set_content_proc
|
69
70
|
end
|
metadata
CHANGED
@@ -1,14 +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.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ross Bamford
|
8
8
|
- Todd A. Fisher
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-02-
|
11
|
+
date: 2025-02-15 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Curb (probably CUrl-RuBy or something) provides Ruby-language bindings
|
14
14
|
for the libcurl(3), a fully-featured client-side URL transfer library. cURL and
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- tests/bug_follow_redirect_288.rb
|
53
53
|
- tests/bug_instance_post_differs_from_class_post.rb
|
54
54
|
- tests/bug_issue102.rb
|
55
|
+
- tests/bug_issue277.rb
|
55
56
|
- tests/bug_multi_segfault.rb
|
56
57
|
- tests/bug_postfields_crash.rb
|
57
58
|
- tests/bug_postfields_crash2.rb
|
@@ -78,7 +79,8 @@ files:
|
|
78
79
|
homepage: https://github.com/taf2/curb
|
79
80
|
licenses:
|
80
81
|
- Ruby
|
81
|
-
metadata:
|
82
|
+
metadata:
|
83
|
+
changelog_uri: https://github.com/taf2/curb/blob/master/ChangeLog.md
|
82
84
|
rdoc_options:
|
83
85
|
- "--main"
|
84
86
|
- README.markdown
|
@@ -108,6 +110,7 @@ test_files:
|
|
108
110
|
- tests/bug_follow_redirect_288.rb
|
109
111
|
- tests/bug_instance_post_differs_from_class_post.rb
|
110
112
|
- tests/bug_issue102.rb
|
113
|
+
- tests/bug_issue277.rb
|
111
114
|
- tests/bug_multi_segfault.rb
|
112
115
|
- tests/bug_postfields_crash.rb
|
113
116
|
- tests/bug_postfields_crash2.rb
|