curb 0.8.4 → 0.8.8
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 +7 -0
- data/README.markdown +240 -0
- data/Rakefile +2 -7
- data/ext/curb.c +20 -0
- data/ext/curb.h +5 -9
- data/ext/curb_easy.c +79 -7
- data/ext/curb_errors.c +27 -16
- data/ext/curb_errors.h +8 -5
- data/ext/curb_multi.c +18 -10
- data/ext/extconf.rb +10 -17
- data/lib/curl/easy.rb +71 -59
- data/lib/curl.rb +7 -1
- data/tests/bug_crash_on_progress.rb +41 -1
- data/tests/bug_issue102.rb +1 -1
- data/tests/helper.rb +6 -1
- data/tests/tc_curl_download.rb +1 -1
- data/tests/tc_curl_easy.rb +22 -4
- data/tests/tc_curl_multi.rb +1 -1
- metadata +21 -29
- data/README +0 -194
data/ext/curb_multi.c
CHANGED
|
@@ -4,13 +4,17 @@
|
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
6
|
#include "curb_config.h"
|
|
7
|
-
#
|
|
8
|
-
|
|
7
|
+
#include <ruby.h>
|
|
8
|
+
#ifdef HAVE_RUBY_ST_H
|
|
9
9
|
#include <ruby/st.h>
|
|
10
10
|
#else
|
|
11
|
-
#include <ruby.h>
|
|
12
11
|
#include <st.h>
|
|
13
12
|
#endif
|
|
13
|
+
|
|
14
|
+
#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
|
|
15
|
+
#include <ruby/thread.h>
|
|
16
|
+
#endif
|
|
17
|
+
|
|
14
18
|
#include "curb_easy.h"
|
|
15
19
|
#include "curb_errors.h"
|
|
16
20
|
#include "curb_postfield.h"
|
|
@@ -64,7 +68,7 @@ rb_hash_clear_i(VALUE key, VALUE value, VALUE dummy) {
|
|
|
64
68
|
|
|
65
69
|
static void curl_multi_free(ruby_curl_multi *rbcm) {
|
|
66
70
|
|
|
67
|
-
if (rbcm && !rbcm->requests == Qnil && rb_type(rbcm->requests) == T_HASH &&
|
|
71
|
+
if (rbcm && !rbcm->requests == Qnil && rb_type(rbcm->requests) == T_HASH && RHASH_SIZE(rbcm->requests) > 0) {
|
|
68
72
|
|
|
69
73
|
rb_hash_foreach( rbcm->requests, (int (*)())curl_multi_flush_easy, (VALUE)rbcm );
|
|
70
74
|
|
|
@@ -262,12 +266,9 @@ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
|
|
|
262
266
|
*/
|
|
263
267
|
VALUE ruby_curl_multi_remove(VALUE self, VALUE easy) {
|
|
264
268
|
ruby_curl_multi *rbcm;
|
|
265
|
-
ruby_curl_easy *rbce;
|
|
266
269
|
|
|
267
270
|
Data_Get_Struct(self, ruby_curl_multi, rbcm);
|
|
268
271
|
|
|
269
|
-
Data_Get_Struct(easy, ruby_curl_easy, rbce);
|
|
270
|
-
|
|
271
272
|
rb_curl_multi_remove(rbcm,easy);
|
|
272
273
|
|
|
273
274
|
return self;
|
|
@@ -471,7 +472,7 @@ void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
|
|
471
472
|
}
|
|
472
473
|
#endif
|
|
473
474
|
|
|
474
|
-
#
|
|
475
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
|
475
476
|
struct _select_set {
|
|
476
477
|
int maxfd;
|
|
477
478
|
fd_set *fdread, *fdwrite, *fdexcep;
|
|
@@ -511,7 +512,7 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
|
|
|
511
512
|
long timeout_milliseconds;
|
|
512
513
|
struct timeval tv = {0, 0};
|
|
513
514
|
VALUE block = Qnil;
|
|
514
|
-
#
|
|
515
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
|
515
516
|
struct _select_set fdset_args;
|
|
516
517
|
#endif
|
|
517
518
|
|
|
@@ -570,17 +571,24 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
|
|
|
570
571
|
create_crt_fd(&fdexcep, &crt_fdexcep);
|
|
571
572
|
#endif
|
|
572
573
|
|
|
573
|
-
#
|
|
574
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
|
574
575
|
fdset_args.maxfd = maxfd+1;
|
|
575
576
|
fdset_args.fdread = &fdread;
|
|
576
577
|
fdset_args.fdwrite = &fdwrite;
|
|
577
578
|
fdset_args.fdexcep = &fdexcep;
|
|
578
579
|
fdset_args.tv = &tv;
|
|
580
|
+
#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
|
|
581
|
+
rc = (int)(VALUE) rb_thread_call_without_gvl((void *(*)(void *))curb_select, &fdset_args, RUBY_UBF_IO, 0);
|
|
582
|
+
#elif HAVE_RB_THREAD_BLOCKING_REGION
|
|
579
583
|
rc = rb_thread_blocking_region(curb_select, &fdset_args, RUBY_UBF_IO, 0);
|
|
584
|
+
#elif HAVE_RB_THREAD_FD_SELECT
|
|
585
|
+
rc = rb_thread_fd_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
|
|
580
586
|
#else
|
|
581
587
|
rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
|
|
582
588
|
#endif
|
|
583
589
|
|
|
590
|
+
#endif
|
|
591
|
+
|
|
584
592
|
#ifdef _WIN32
|
|
585
593
|
cleanup_crt_fd(&fdread, &crt_fdread);
|
|
586
594
|
cleanup_crt_fd(&fdwrite, &crt_fdwrite);
|
data/ext/extconf.rb
CHANGED
|
@@ -59,6 +59,7 @@ def have_constant(name)
|
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
have_constant "curlinfo_appconnect_time"
|
|
62
63
|
have_constant "curlinfo_redirect_time"
|
|
63
64
|
have_constant "curlinfo_response_code"
|
|
64
65
|
have_constant "curlinfo_filetime"
|
|
@@ -79,6 +80,7 @@ have_constant "curl_version_sspi"
|
|
|
79
80
|
have_constant "curl_version_conv"
|
|
80
81
|
have_constant "curlproxy_http"
|
|
81
82
|
have_constant "curlproxy_socks4"
|
|
83
|
+
have_constant "curlproxy_socks4a"
|
|
82
84
|
have_constant "curlproxy_socks5"
|
|
83
85
|
have_constant "curlauth_basic"
|
|
84
86
|
have_constant "curlauth_digest"
|
|
@@ -351,6 +353,13 @@ have_constant "curle_not_built_in"
|
|
|
351
353
|
|
|
352
354
|
have_constant "curle_obsolete" # removed in 7.24 ?
|
|
353
355
|
|
|
356
|
+
# gssapi/spnego delegation related constants
|
|
357
|
+
have_constant "curlopt_gssapi_delegation"
|
|
358
|
+
have_constant "curlgssapi_delegation_policy_flag"
|
|
359
|
+
have_constant "curlgssapi_delegation_flag"
|
|
360
|
+
|
|
361
|
+
have_constant "CURLM_ADDED_ALREADY"
|
|
362
|
+
|
|
354
363
|
if try_compile('int main() { return 0; }','-Wall')
|
|
355
364
|
$CFLAGS << ' -Wall'
|
|
356
365
|
end
|
|
@@ -366,23 +375,6 @@ def test_for(name, const, src)
|
|
|
366
375
|
end
|
|
367
376
|
end
|
|
368
377
|
end
|
|
369
|
-
test_for("Ruby 1.9 Hash", "RUBY19_HASH", %{
|
|
370
|
-
#include <ruby.h>
|
|
371
|
-
int main() {
|
|
372
|
-
VALUE hash = rb_hash_new();
|
|
373
|
-
if( RHASH(hash)->ntbl->num_entries ) {
|
|
374
|
-
return 0;
|
|
375
|
-
}
|
|
376
|
-
return 1;
|
|
377
|
-
}
|
|
378
|
-
})
|
|
379
|
-
test_for("Ruby 1.9 st.h", "RUBY19_ST_H", %{
|
|
380
|
-
#include <ruby.h>
|
|
381
|
-
#include <ruby/st.h>
|
|
382
|
-
int main() {
|
|
383
|
-
return 0;
|
|
384
|
-
}
|
|
385
|
-
})
|
|
386
378
|
|
|
387
379
|
test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
|
|
388
380
|
#include <curl/curl.h>
|
|
@@ -394,6 +386,7 @@ test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
|
|
|
394
386
|
})
|
|
395
387
|
|
|
396
388
|
have_func('rb_thread_blocking_region')
|
|
389
|
+
have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
|
|
397
390
|
|
|
398
391
|
create_header('curb_config.h')
|
|
399
392
|
create_makefile('curb_core')
|
data/lib/curl/easy.rb
CHANGED
|
@@ -3,32 +3,44 @@ module Curl
|
|
|
3
3
|
|
|
4
4
|
alias post http_post
|
|
5
5
|
alias put http_put
|
|
6
|
+
alias body body_str
|
|
7
|
+
alias head header_str
|
|
8
|
+
|
|
9
|
+
class Error < Exception
|
|
10
|
+
attr_accessor :message, :code
|
|
11
|
+
def initialize(code, msg)
|
|
12
|
+
self.message = msg
|
|
13
|
+
self.code = code
|
|
14
|
+
end
|
|
15
|
+
end
|
|
6
16
|
|
|
7
17
|
#
|
|
8
18
|
# call-seq:
|
|
9
19
|
# easy.status => String
|
|
10
20
|
#
|
|
11
21
|
def status
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
while parts.size > 0 && parts.first != ''
|
|
16
|
-
status << parts.shift
|
|
17
|
-
end
|
|
18
|
-
status.join(' ')
|
|
22
|
+
# Matches the last HTTP Status - following the HTTP protocol specification 'Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF'
|
|
23
|
+
statuses = self.header_str.scan(/HTTP\/\d\.\d\s(\d+\s.+)\r\n/).map{ |match| match[0] }
|
|
24
|
+
statuses.last.strip
|
|
19
25
|
end
|
|
20
26
|
|
|
21
27
|
#
|
|
22
28
|
# call-seq:
|
|
23
29
|
# easy.set :sym|Fixnum, value
|
|
24
|
-
#
|
|
30
|
+
#
|
|
25
31
|
# set options on the curl easy handle see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
|
|
26
32
|
#
|
|
27
33
|
def set(opt,val)
|
|
28
34
|
if opt.is_a?(Symbol)
|
|
29
|
-
|
|
35
|
+
option = sym2curl(opt)
|
|
30
36
|
else
|
|
31
|
-
|
|
37
|
+
option = opt.to_i
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
begin
|
|
41
|
+
setopt(option, val)
|
|
42
|
+
rescue TypeError
|
|
43
|
+
raise TypeError, "Curb doesn't support setting #{opt} [##{option}] option"
|
|
32
44
|
end
|
|
33
45
|
end
|
|
34
46
|
|
|
@@ -56,8 +68,8 @@ module Curl
|
|
|
56
68
|
ret = self.multi.perform
|
|
57
69
|
|
|
58
70
|
if self.last_result != 0 && self.on_failure.nil?
|
|
59
|
-
error = Curl::Easy.error(self.last_result)
|
|
60
|
-
raise error.first
|
|
71
|
+
error = Curl::Easy.error(self.last_result)
|
|
72
|
+
raise error.first.new(error.last)
|
|
61
73
|
end
|
|
62
74
|
|
|
63
75
|
ret
|
|
@@ -81,54 +93,54 @@ module Curl
|
|
|
81
93
|
# easy.perform
|
|
82
94
|
#
|
|
83
95
|
def delete=(onoff)
|
|
84
|
-
set :customrequest, onoff ? '
|
|
96
|
+
set :customrequest, onoff ? 'DELETE' : nil
|
|
85
97
|
onoff
|
|
86
98
|
end
|
|
87
|
-
#
|
|
99
|
+
#
|
|
88
100
|
# call-seq:
|
|
89
|
-
#
|
|
101
|
+
#
|
|
90
102
|
# easy = Curl::Easy.new("url")
|
|
91
103
|
# easy.version = Curl::HTTP_1_1
|
|
92
104
|
# easy.version = Curl::HTTP_1_0
|
|
93
105
|
# easy.version = Curl::HTTP_NONE
|
|
94
|
-
#
|
|
106
|
+
#
|
|
95
107
|
def version=(http_version)
|
|
96
108
|
set :http_version, http_version
|
|
97
109
|
end
|
|
98
110
|
|
|
99
|
-
#
|
|
111
|
+
#
|
|
100
112
|
# call-seq:
|
|
101
113
|
# easy.url = "http://some.url/" => "http://some.url/"
|
|
102
|
-
#
|
|
114
|
+
#
|
|
103
115
|
# Set the URL for subsequent calls to +perform+. It is acceptable
|
|
104
116
|
# (and even recommended) to reuse Curl::Easy instances by reassigning
|
|
105
117
|
# the URL between calls to +perform+.
|
|
106
|
-
#
|
|
118
|
+
#
|
|
107
119
|
def url=(u)
|
|
108
120
|
set :url, u
|
|
109
121
|
end
|
|
110
122
|
|
|
111
|
-
#
|
|
123
|
+
#
|
|
112
124
|
# call-seq:
|
|
113
125
|
# easy.proxy_url = string => string
|
|
114
|
-
#
|
|
126
|
+
#
|
|
115
127
|
# Set the URL of the HTTP proxy to use for subsequent calls to +perform+.
|
|
116
128
|
# The URL should specify the the host name or dotted IP address. To specify
|
|
117
129
|
# port number in this string, append :[port] to the end of the host name.
|
|
118
130
|
# The proxy string may be prefixed with [protocol]:// since any such prefix
|
|
119
131
|
# will be ignored. The proxy's port number may optionally be specified with
|
|
120
132
|
# the separate option proxy_port .
|
|
121
|
-
#
|
|
133
|
+
#
|
|
122
134
|
# When you tell the library to use an HTTP proxy, libcurl will transparently
|
|
123
135
|
# convert operations to HTTP even if you specify an FTP URL etc. This may have
|
|
124
136
|
# an impact on what other features of the library you can use, such as
|
|
125
137
|
# FTP specifics that don't work unless you tunnel through the HTTP proxy. Such
|
|
126
138
|
# tunneling is activated with proxy_tunnel = true.
|
|
127
|
-
#
|
|
139
|
+
#
|
|
128
140
|
# libcurl respects the environment variables *http_proxy*, *ftp_proxy*,
|
|
129
141
|
# *all_proxy* etc, if any of those is set. The proxy_url option does however
|
|
130
142
|
# override any possibly set environment variables.
|
|
131
|
-
#
|
|
143
|
+
#
|
|
132
144
|
# Starting with libcurl 7.14.1, the proxy host string given in environment
|
|
133
145
|
# variables can be specified the exact same way as the proxy can be set with
|
|
134
146
|
# proxy_url, including protocol prefix (http://) and embedded user + password.
|
|
@@ -143,89 +155,89 @@ module Curl
|
|
|
143
155
|
self.ssl_verify_host_integer=value
|
|
144
156
|
end
|
|
145
157
|
|
|
146
|
-
#
|
|
158
|
+
#
|
|
147
159
|
# call-seq:
|
|
148
160
|
# easy.ssl_verify_host? => boolean
|
|
149
|
-
#
|
|
161
|
+
#
|
|
150
162
|
# Deprecated: call easy.ssl_verify_host instead
|
|
151
163
|
# can be one of [0,1,2]
|
|
152
|
-
#
|
|
164
|
+
#
|
|
153
165
|
# Determine whether this Curl instance will verify that the server cert
|
|
154
166
|
# is for the server it is known as.
|
|
155
|
-
#
|
|
167
|
+
#
|
|
156
168
|
def ssl_verify_host?
|
|
157
169
|
ssl_verify_host.nil? ? false : (ssl_verify_host > 0)
|
|
158
170
|
end
|
|
159
171
|
|
|
160
|
-
#
|
|
172
|
+
#
|
|
161
173
|
# call-seq:
|
|
162
174
|
# easy.interface = string => string
|
|
163
|
-
#
|
|
175
|
+
#
|
|
164
176
|
# Set the interface name to use as the outgoing network interface.
|
|
165
177
|
# The name can be an interface name, an IP address or a host name.
|
|
166
|
-
#
|
|
178
|
+
#
|
|
167
179
|
def interface=(value)
|
|
168
180
|
set :interface, value
|
|
169
181
|
end
|
|
170
182
|
|
|
171
|
-
#
|
|
183
|
+
#
|
|
172
184
|
# call-seq:
|
|
173
185
|
# easy.userpwd = string => string
|
|
174
|
-
#
|
|
186
|
+
#
|
|
175
187
|
# Set the username/password string to use for subsequent calls to +perform+.
|
|
176
188
|
# The supplied string should have the form "username:password"
|
|
177
|
-
#
|
|
189
|
+
#
|
|
178
190
|
def userpwd=(value)
|
|
179
191
|
set :userpwd, value
|
|
180
192
|
end
|
|
181
193
|
|
|
182
|
-
#
|
|
194
|
+
#
|
|
183
195
|
# call-seq:
|
|
184
196
|
# easy.proxypwd = string => string
|
|
185
|
-
#
|
|
197
|
+
#
|
|
186
198
|
# Set the username/password string to use for proxy connection during
|
|
187
199
|
# subsequent calls to +perform+. The supplied string should have the
|
|
188
200
|
# form "username:password"
|
|
189
|
-
#
|
|
201
|
+
#
|
|
190
202
|
def proxypwd=(value)
|
|
191
203
|
set :proxyuserpwd, value
|
|
192
204
|
end
|
|
193
205
|
|
|
194
|
-
#
|
|
206
|
+
#
|
|
195
207
|
# call-seq:
|
|
196
208
|
# easy.cookies = "name1=content1; name2=content2;" => string
|
|
197
|
-
#
|
|
209
|
+
#
|
|
198
210
|
# Set cookies to be sent by this Curl::Easy instance. The format of the string should
|
|
199
211
|
# be NAME=CONTENTS, where NAME is the cookie name and CONTENTS is what the cookie should contain.
|
|
200
212
|
# Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc.
|
|
201
|
-
#
|
|
213
|
+
#
|
|
202
214
|
def cookies=(value)
|
|
203
215
|
set :cookie, value
|
|
204
216
|
end
|
|
205
217
|
|
|
206
|
-
#
|
|
218
|
+
#
|
|
207
219
|
# call-seq:
|
|
208
220
|
# easy.cookiefile = string => string
|
|
209
|
-
#
|
|
221
|
+
#
|
|
210
222
|
# Set a file that contains cookies to be sent in subsequent requests by this Curl::Easy instance.
|
|
211
|
-
#
|
|
223
|
+
#
|
|
212
224
|
# *Note* that you must set enable_cookies true to enable the cookie
|
|
213
225
|
# engine, or this option will be ignored.
|
|
214
|
-
#
|
|
226
|
+
#
|
|
215
227
|
def cookiefile=(value)
|
|
216
228
|
set :cookiefile, value
|
|
217
229
|
end
|
|
218
230
|
|
|
219
|
-
#
|
|
231
|
+
#
|
|
220
232
|
# call-seq:
|
|
221
233
|
# easy.cookiejar = string => string
|
|
222
|
-
#
|
|
234
|
+
#
|
|
223
235
|
# Set a cookiejar file to use for this Curl::Easy instance.
|
|
224
236
|
# Cookies from the response will be written into this file.
|
|
225
|
-
#
|
|
237
|
+
#
|
|
226
238
|
# *Note* that you must set enable_cookies true to enable the cookie
|
|
227
239
|
# engine, or this option will be ignored.
|
|
228
|
-
#
|
|
240
|
+
#
|
|
229
241
|
def cookiejar=(value)
|
|
230
242
|
set :cookiejar, value
|
|
231
243
|
end
|
|
@@ -403,35 +415,35 @@ module Curl
|
|
|
403
415
|
c.http_delete
|
|
404
416
|
c
|
|
405
417
|
end
|
|
406
|
-
|
|
418
|
+
|
|
407
419
|
# call-seq:
|
|
408
420
|
# Curl::Easy.download(url, filename = url.split(/\?/).first.split(/\//).last) { |curl| ... }
|
|
409
|
-
#
|
|
421
|
+
#
|
|
410
422
|
# Stream the specified url (via perform) and save the data directly to the
|
|
411
|
-
# supplied filename (defaults to the last component of the URL path, which will
|
|
423
|
+
# supplied filename (defaults to the last component of the URL path, which will
|
|
412
424
|
# usually be the filename most simple urls).
|
|
413
|
-
#
|
|
425
|
+
#
|
|
414
426
|
# If a block is supplied, it will be passed the curl instance prior to the
|
|
415
427
|
# perform call.
|
|
416
|
-
#
|
|
428
|
+
#
|
|
417
429
|
# *Note* that the semantics of the on_body handler are subtly changed when using
|
|
418
|
-
# download, to account for the automatic routing of data to the specified file: The
|
|
430
|
+
# download, to account for the automatic routing of data to the specified file: The
|
|
419
431
|
# data string is passed to the handler *before* it is written
|
|
420
|
-
# to the file, allowing the handler to perform mutative operations where
|
|
432
|
+
# to the file, allowing the handler to perform mutative operations where
|
|
421
433
|
# necessary. As usual, the transfer will be aborted if the on_body handler
|
|
422
|
-
# returns a size that differs from the data chunk size - in this case, the
|
|
434
|
+
# returns a size that differs from the data chunk size - in this case, the
|
|
423
435
|
# offending chunk will *not* be written to the file, the file will be closed,
|
|
424
436
|
# and a Curl::Err::AbortedByCallbackError will be raised.
|
|
425
437
|
def download(url, filename = url.split(/\?/).first.split(/\//).last, &blk)
|
|
426
438
|
curl = Curl::Easy.new(url, &blk)
|
|
427
|
-
|
|
439
|
+
|
|
428
440
|
output = if filename.is_a? IO
|
|
429
441
|
filename.binmode if filename.respond_to?(:binmode)
|
|
430
442
|
filename
|
|
431
443
|
else
|
|
432
444
|
File.open(filename, 'wb')
|
|
433
445
|
end
|
|
434
|
-
|
|
446
|
+
|
|
435
447
|
begin
|
|
436
448
|
old_on_body = curl.on_body do |data|
|
|
437
449
|
result = old_on_body ? old_on_body.call(data) : data.length
|
|
@@ -442,7 +454,7 @@ module Curl
|
|
|
442
454
|
ensure
|
|
443
455
|
output.close rescue IOError
|
|
444
456
|
end
|
|
445
|
-
|
|
457
|
+
|
|
446
458
|
return curl
|
|
447
459
|
end
|
|
448
460
|
end
|
data/lib/curl.rb
CHANGED
|
@@ -2,12 +2,14 @@ require 'curb_core'
|
|
|
2
2
|
require 'curl/easy'
|
|
3
3
|
require 'curl/multi'
|
|
4
4
|
require 'uri'
|
|
5
|
+
require 'cgi'
|
|
5
6
|
|
|
6
7
|
# expose shortcut methods
|
|
7
8
|
module Curl
|
|
8
9
|
|
|
9
10
|
def self.http(verb, url, post_body=nil, put_data=nil, &block)
|
|
10
11
|
handle = Thread.current[:curb_curl] ||= Curl::Easy.new
|
|
12
|
+
handle.reset
|
|
11
13
|
handle.url = url
|
|
12
14
|
handle.post_body = post_body if post_body
|
|
13
15
|
handle.put_data = put_data if put_data
|
|
@@ -45,7 +47,7 @@ module Curl
|
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
def self.urlalize(url, params={})
|
|
48
|
-
query_str = params.map {|k,v| "#{URI.escape(k.to_s)}=#{
|
|
50
|
+
query_str = params.map {|k,v| "#{URI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
|
|
49
51
|
if url.match(/\?/)
|
|
50
52
|
"#{url}&#{query_str}"
|
|
51
53
|
elsif query_str.size > 0
|
|
@@ -59,4 +61,8 @@ module Curl
|
|
|
59
61
|
params.respond_to?(:map) ? URI.encode_www_form(params) : (params.respond_to?(:to_s) ? params.to_s : params)
|
|
60
62
|
end
|
|
61
63
|
|
|
64
|
+
def self.reset
|
|
65
|
+
Thread.current[:curb_curl] = Curl::Easy.new
|
|
66
|
+
end
|
|
67
|
+
|
|
62
68
|
end
|
|
@@ -5,7 +5,7 @@ class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
|
|
|
5
5
|
|
|
6
6
|
class BugCrashOnDebug < Test::Unit::TestCase
|
|
7
7
|
|
|
8
|
-
def
|
|
8
|
+
def test_on_progress_raise
|
|
9
9
|
server = WEBrick::HTTPServer.new( :Port => 9999 )
|
|
10
10
|
server.mount_proc("/test") do|req,res|
|
|
11
11
|
res.body = "hi"
|
|
@@ -30,4 +30,44 @@ class BugCrashOnDebug < Test::Unit::TestCase
|
|
|
30
30
|
ensure
|
|
31
31
|
server.shutdown
|
|
32
32
|
end
|
|
33
|
+
|
|
34
|
+
def test_on_progress_abort
|
|
35
|
+
server = WEBrick::HTTPServer.new( :Port => 9999 )
|
|
36
|
+
server.mount_proc("/test") do|req,res|
|
|
37
|
+
res.body = "hi"
|
|
38
|
+
res['Content-Type'] = "text/html"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
thread = Thread.new(server) do|srv|
|
|
42
|
+
srv.start
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# see: https://github.com/taf2/curb/issues/192,
|
|
46
|
+
# to pass:
|
|
47
|
+
#
|
|
48
|
+
# c = Curl::Easy.new('http://127.0.0.1:9999/test')
|
|
49
|
+
# c.on_progress do|x|
|
|
50
|
+
# puts "we're in the progress callback"
|
|
51
|
+
# false
|
|
52
|
+
# end
|
|
53
|
+
# c.perform
|
|
54
|
+
#
|
|
55
|
+
# notice no return keyword
|
|
56
|
+
#
|
|
57
|
+
c = Curl::Easy.new('http://127.0.0.1:9999/test')
|
|
58
|
+
c.on_progress do|x|
|
|
59
|
+
puts "we're in the progress callback"
|
|
60
|
+
return false
|
|
61
|
+
end
|
|
62
|
+
c.perform
|
|
63
|
+
|
|
64
|
+
assert false, "should not reach this point"
|
|
65
|
+
|
|
66
|
+
rescue => e
|
|
67
|
+
assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
|
|
68
|
+
c.close
|
|
69
|
+
ensure
|
|
70
|
+
server.shutdown
|
|
71
|
+
end
|
|
72
|
+
|
|
33
73
|
end
|
data/tests/bug_issue102.rb
CHANGED
data/tests/helper.rb
CHANGED
|
@@ -10,7 +10,12 @@ $:.unshift($LIBDIR)
|
|
|
10
10
|
$:.unshift($EXTDIR)
|
|
11
11
|
|
|
12
12
|
require 'curb'
|
|
13
|
-
|
|
13
|
+
begin
|
|
14
|
+
require 'test/unit'
|
|
15
|
+
rescue LoadError
|
|
16
|
+
gem 'test/unit'
|
|
17
|
+
require 'test/unit'
|
|
18
|
+
end
|
|
14
19
|
require 'fileutils'
|
|
15
20
|
|
|
16
21
|
$TEST_URL = "file://#{URI.escape(File.expand_path(__FILE__).tr('\\','/').tr(':','|'))}"
|
data/tests/tc_curl_download.rb
CHANGED
data/tests/tc_curl_easy.rb
CHANGED
|
@@ -4,6 +4,12 @@ class FooNoToS
|
|
|
4
4
|
end
|
|
5
5
|
|
|
6
6
|
class TestCurbCurlEasy < Test::Unit::TestCase
|
|
7
|
+
def test_global_reset
|
|
8
|
+
c = Curl.get($TEST_URL)
|
|
9
|
+
# in a Timeout block you should reset the thread current handle
|
|
10
|
+
Curl.reset
|
|
11
|
+
end
|
|
12
|
+
|
|
7
13
|
def test_threads
|
|
8
14
|
t = []
|
|
9
15
|
5.times do
|
|
@@ -11,7 +17,9 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
11
17
|
5.times do
|
|
12
18
|
c = Curl.get($TEST_URL)
|
|
13
19
|
assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
|
|
20
|
+
assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body)
|
|
14
21
|
assert_equal "", c.header_str
|
|
22
|
+
assert_equal "", c.head
|
|
15
23
|
end
|
|
16
24
|
end
|
|
17
25
|
end
|
|
@@ -22,6 +30,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
22
30
|
def test_class_perform_01
|
|
23
31
|
assert_instance_of Curl::Easy, c = Curl::Easy.perform($TEST_URL)
|
|
24
32
|
assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
|
|
33
|
+
assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body)
|
|
25
34
|
assert_equal "", c.header_str
|
|
26
35
|
end
|
|
27
36
|
|
|
@@ -642,8 +651,8 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
642
651
|
curl = Curl::Easy.new(TestServlet.url)
|
|
643
652
|
curl.multipart_form_post = true
|
|
644
653
|
fields = [
|
|
645
|
-
Curl::PostField.file('foo', File.expand_path(File.join(File.dirname(__FILE__),'..','README'))),
|
|
646
|
-
Curl::PostField.file('bar', File.expand_path(File.join(File.dirname(__FILE__),'..','README')))
|
|
654
|
+
Curl::PostField.file('foo', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown'))),
|
|
655
|
+
Curl::PostField.file('bar', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown')))
|
|
647
656
|
]
|
|
648
657
|
curl.http_post(fields)
|
|
649
658
|
assert_match /HTTP POST file upload/, curl.body_str
|
|
@@ -671,7 +680,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
671
680
|
def test_post_multipart_file_remote
|
|
672
681
|
curl = Curl::Easy.new(TestServlet.url)
|
|
673
682
|
curl.multipart_form_post = true
|
|
674
|
-
pf = Curl::PostField.file('readme', File.expand_path(File.join(File.dirname(__FILE__),'..','README')))
|
|
683
|
+
pf = Curl::PostField.file('readme', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown')))
|
|
675
684
|
curl.http_post(pf)
|
|
676
685
|
assert_match /HTTP POST file upload/, curl.body_str
|
|
677
686
|
assert_match /Content-Disposition: form-data/, curl.body_str
|
|
@@ -719,7 +728,9 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
719
728
|
assert curl.http_put("message")
|
|
720
729
|
assert_match /^PUT/, curl.body_str
|
|
721
730
|
assert_match /message$/, curl.body_str
|
|
731
|
+
assert_match /message$/, curl.body
|
|
722
732
|
assert_match /application\/json/, curl.header_str
|
|
733
|
+
assert_match /application\/json/, curl.head
|
|
723
734
|
end
|
|
724
735
|
|
|
725
736
|
def test_put_data
|
|
@@ -850,7 +861,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
850
861
|
end
|
|
851
862
|
|
|
852
863
|
def test_post_streaming
|
|
853
|
-
readme = File.expand_path(File.join(File.dirname(__FILE__),'..','README'))
|
|
864
|
+
readme = File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown'))
|
|
854
865
|
|
|
855
866
|
pf = Curl::PostField.file("filename", readme)
|
|
856
867
|
|
|
@@ -1017,6 +1028,13 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
|
1017
1028
|
end
|
|
1018
1029
|
end
|
|
1019
1030
|
|
|
1031
|
+
def test_set_unsupported_options
|
|
1032
|
+
curl = Curl::Easy.new
|
|
1033
|
+
assert_raises TypeError do
|
|
1034
|
+
curl.set(99999, 1)
|
|
1035
|
+
end
|
|
1036
|
+
end
|
|
1037
|
+
|
|
1020
1038
|
include TestServerMethods
|
|
1021
1039
|
|
|
1022
1040
|
def setup
|
data/tests/tc_curl_multi.rb
CHANGED
|
@@ -466,7 +466,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
|
466
466
|
m.add(c)
|
|
467
467
|
m.add(c)
|
|
468
468
|
rescue => e
|
|
469
|
-
|
|
469
|
+
assert Curl::Err::MultiBadEasyHandle == e.class || Curl::Err::MultiAddedAlready == e.class
|
|
470
470
|
end
|
|
471
471
|
|
|
472
472
|
def test_multi_default_timeout
|