curb 0.8.4 → 0.9.11
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 +277 -0
- data/Rakefile +29 -18
- data/ext/banned.h +32 -0
- data/ext/curb.c +161 -46
- data/ext/curb.h +14 -10
- data/ext/curb_easy.c +612 -97
- data/ext/curb_easy.h +6 -0
- data/ext/curb_errors.c +113 -16
- data/ext/curb_errors.h +8 -5
- data/ext/curb_macros.h +7 -7
- data/ext/curb_multi.c +175 -167
- data/ext/curb_multi.h +0 -1
- data/ext/curb_upload.c +2 -2
- data/ext/extconf.rb +52 -17
- data/lib/curb.rb +1 -0
- data/lib/curl/easy.rb +79 -59
- data/lib/curl/multi.rb +59 -20
- data/lib/curl.rb +15 -9
- data/tests/bug_crash_on_progress.rb +41 -1
- data/tests/bug_issue102.rb +1 -1
- data/tests/bug_issue277.rb +32 -0
- data/tests/helper.rb +102 -13
- data/tests/tc_curl.rb +31 -1
- data/tests/tc_curl_download.rb +4 -4
- data/tests/tc_curl_easy.rb +197 -42
- data/tests/tc_curl_easy_resolve.rb +16 -0
- data/tests/tc_curl_maxfilesize.rb +12 -0
- data/tests/tc_curl_multi.rb +82 -16
- data/tests/tc_curl_postfield.rb +29 -29
- data/tests/timeout.rb +10 -2
- metadata +51 -52
- data/README +0 -194
data/ext/extconf.rb
CHANGED
|
@@ -59,12 +59,17 @@ def have_constant(name)
|
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
have_constant "curlopt_tcp_keepalive"
|
|
63
|
+
have_constant "curlopt_tcp_keepidle"
|
|
64
|
+
have_constant "curlopt_tcp_keepintvl"
|
|
65
|
+
have_constant "curlinfo_appconnect_time"
|
|
62
66
|
have_constant "curlinfo_redirect_time"
|
|
63
67
|
have_constant "curlinfo_response_code"
|
|
64
68
|
have_constant "curlinfo_filetime"
|
|
65
69
|
have_constant "curlinfo_redirect_count"
|
|
66
70
|
have_constant "curlinfo_os_errno"
|
|
67
71
|
have_constant "curlinfo_num_connects"
|
|
72
|
+
have_constant "curlinfo_cookielist"
|
|
68
73
|
have_constant "curlinfo_ftp_entry_path"
|
|
69
74
|
have_constant "curl_version_ssl"
|
|
70
75
|
have_constant "curl_version_libz"
|
|
@@ -77,9 +82,12 @@ have_constant "curl_version_largefile"
|
|
|
77
82
|
have_constant "curl_version_idn"
|
|
78
83
|
have_constant "curl_version_sspi"
|
|
79
84
|
have_constant "curl_version_conv"
|
|
85
|
+
have_constant "curl_version_http2"
|
|
80
86
|
have_constant "curlproxy_http"
|
|
81
87
|
have_constant "curlproxy_socks4"
|
|
88
|
+
have_constant "curlproxy_socks4a"
|
|
82
89
|
have_constant "curlproxy_socks5"
|
|
90
|
+
have_constant "curlproxy_socks5_hostname"
|
|
83
91
|
have_constant "curlauth_basic"
|
|
84
92
|
have_constant "curlauth_digest"
|
|
85
93
|
have_constant "curlauth_gssnegotiate"
|
|
@@ -98,6 +106,12 @@ have_constant "curle_send_fail_rewind"
|
|
|
98
106
|
have_constant "curle_ssl_engine_initfailed"
|
|
99
107
|
have_constant "curle_login_denied"
|
|
100
108
|
|
|
109
|
+
# older than 7.10.0
|
|
110
|
+
have_constant "curlopt_nosignal"
|
|
111
|
+
|
|
112
|
+
# older than 7.16.0
|
|
113
|
+
have_constant "curlmopt_pipelining"
|
|
114
|
+
|
|
101
115
|
# older than 7.16.3
|
|
102
116
|
have_constant "curlmopt_maxconnects"
|
|
103
117
|
|
|
@@ -142,6 +156,8 @@ have_func("curl_multi_timeout")
|
|
|
142
156
|
have_func("curl_multi_fdset")
|
|
143
157
|
have_func("curl_multi_perform")
|
|
144
158
|
|
|
159
|
+
have_constant "curlopt_haproxyprotocol"
|
|
160
|
+
|
|
145
161
|
# constants
|
|
146
162
|
have_constant "curlopt_interleavefunction"
|
|
147
163
|
have_constant "curlopt_interleavedata"
|
|
@@ -206,6 +222,7 @@ have_constant "curlopt_httppost"
|
|
|
206
222
|
have_constant "curlopt_referer"
|
|
207
223
|
have_constant "curlopt_useragent"
|
|
208
224
|
have_constant "curlopt_httpheader"
|
|
225
|
+
have_constant "curlopt_proxyheader"
|
|
209
226
|
have_constant "curlopt_http200aliases"
|
|
210
227
|
have_constant "curlopt_cookie"
|
|
211
228
|
have_constant "curlopt_cookiefile"
|
|
@@ -318,6 +335,12 @@ have_constant "curl_sslversion_default"
|
|
|
318
335
|
have_constant :CURL_SSLVERSION_TLSv1
|
|
319
336
|
have_constant :CURL_SSLVERSION_SSLv2
|
|
320
337
|
have_constant :CURL_SSLVERSION_SSLv3
|
|
338
|
+
|
|
339
|
+
# Added in 7.34.0
|
|
340
|
+
have_constant :CURL_SSLVERSION_TLSv1_0
|
|
341
|
+
have_constant :CURL_SSLVERSION_TLSv1_1
|
|
342
|
+
have_constant :CURL_SSLVERSION_TLSv1_2
|
|
343
|
+
|
|
321
344
|
have_constant "curlopt_ssl_verifypeer"
|
|
322
345
|
have_constant "curlopt_cainfo"
|
|
323
346
|
have_constant "curlopt_issuercert"
|
|
@@ -351,6 +374,32 @@ have_constant "curle_not_built_in"
|
|
|
351
374
|
|
|
352
375
|
have_constant "curle_obsolete" # removed in 7.24 ?
|
|
353
376
|
|
|
377
|
+
have_constant "curle_ftp_pret_failed"
|
|
378
|
+
have_constant "curle_rtsp_cseq_error"
|
|
379
|
+
have_constant "curle_rtsp_session_error"
|
|
380
|
+
have_constant "curle_ftp_bad_file_list"
|
|
381
|
+
have_constant "curle_chunk_failed"
|
|
382
|
+
have_constant "curle_no_connection_available"
|
|
383
|
+
have_constant "curle_ssl_pinnedpubkeynotmatch"
|
|
384
|
+
have_constant "curle_ssl_invalidcertstatus"
|
|
385
|
+
have_constant "curle_http2_stream"
|
|
386
|
+
|
|
387
|
+
# gssapi/spnego delegation related constants
|
|
388
|
+
have_constant "curlopt_gssapi_delegation"
|
|
389
|
+
have_constant "curlgssapi_delegation_policy_flag"
|
|
390
|
+
have_constant "curlgssapi_delegation_flag"
|
|
391
|
+
|
|
392
|
+
have_constant "CURLM_ADDED_ALREADY"
|
|
393
|
+
|
|
394
|
+
# added in 7.40.0
|
|
395
|
+
have_constant "curlopt_unix_socket_path"
|
|
396
|
+
|
|
397
|
+
# added in 7.42.0
|
|
398
|
+
have_constant "curlopt_path_as_is"
|
|
399
|
+
|
|
400
|
+
# added in 7.43.0
|
|
401
|
+
have_constant "curlopt_pipewait"
|
|
402
|
+
|
|
354
403
|
if try_compile('int main() { return 0; }','-Wall')
|
|
355
404
|
$CFLAGS << ' -Wall'
|
|
356
405
|
end
|
|
@@ -366,23 +415,6 @@ def test_for(name, const, src)
|
|
|
366
415
|
end
|
|
367
416
|
end
|
|
368
417
|
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
418
|
|
|
387
419
|
test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
|
|
388
420
|
#include <curl/curl.h>
|
|
@@ -394,6 +426,9 @@ test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
|
|
|
394
426
|
})
|
|
395
427
|
|
|
396
428
|
have_func('rb_thread_blocking_region')
|
|
429
|
+
have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
|
|
430
|
+
have_header('ruby/io.h')
|
|
431
|
+
have_func('rb_io_stdio_file')
|
|
397
432
|
|
|
398
433
|
create_header('curb_config.h')
|
|
399
434
|
create_makefile('curb_core')
|
data/lib/curb.rb
CHANGED
data/lib/curl/easy.rb
CHANGED
|
@@ -1,34 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Curl
|
|
2
3
|
class Easy
|
|
3
4
|
|
|
4
5
|
alias post http_post
|
|
5
6
|
alias put http_put
|
|
7
|
+
alias body body_str
|
|
8
|
+
alias head header_str
|
|
9
|
+
|
|
10
|
+
class Error < StandardError
|
|
11
|
+
attr_accessor :message, :code
|
|
12
|
+
def initialize(code, msg)
|
|
13
|
+
self.message = msg
|
|
14
|
+
self.code = code
|
|
15
|
+
end
|
|
16
|
+
end
|
|
6
17
|
|
|
7
18
|
#
|
|
8
19
|
# call-seq:
|
|
9
20
|
# easy.status => String
|
|
10
21
|
#
|
|
11
22
|
def status
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
while parts.size > 0 && parts.first != ''
|
|
16
|
-
status << parts.shift
|
|
17
|
-
end
|
|
18
|
-
status.join(' ')
|
|
23
|
+
# Matches the last HTTP Status - following the HTTP protocol specification 'Status-Line = HTTP-Version SP Status-Code SP (Opt:)Reason-Phrase CRLF'
|
|
24
|
+
statuses = self.header_str.scan(/HTTP\/\d(\.\d)?\s(\d+\s.*)\r\n/).map{ |match| match[1] }
|
|
25
|
+
statuses.last.strip if statuses.length > 0
|
|
19
26
|
end
|
|
20
27
|
|
|
21
28
|
#
|
|
22
29
|
# call-seq:
|
|
23
30
|
# easy.set :sym|Fixnum, value
|
|
24
|
-
#
|
|
31
|
+
#
|
|
25
32
|
# set options on the curl easy handle see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
|
|
26
33
|
#
|
|
27
34
|
def set(opt,val)
|
|
28
35
|
if opt.is_a?(Symbol)
|
|
29
|
-
|
|
36
|
+
option = sym2curl(opt)
|
|
30
37
|
else
|
|
31
|
-
|
|
38
|
+
option = opt.to_i
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
begin
|
|
42
|
+
setopt(option, val)
|
|
43
|
+
rescue TypeError
|
|
44
|
+
raise TypeError, "Curb doesn't support setting #{opt} [##{option}] option"
|
|
32
45
|
end
|
|
33
46
|
end
|
|
34
47
|
|
|
@@ -54,10 +67,16 @@ module Curl
|
|
|
54
67
|
self.multi = Curl::Multi.new if self.multi.nil?
|
|
55
68
|
self.multi.add self
|
|
56
69
|
ret = self.multi.perform
|
|
70
|
+
self.multi.remove self
|
|
71
|
+
|
|
72
|
+
if Curl::Multi.autoclose
|
|
73
|
+
self.multi.close
|
|
74
|
+
self.multi = nil
|
|
75
|
+
end
|
|
57
76
|
|
|
58
77
|
if self.last_result != 0 && self.on_failure.nil?
|
|
59
|
-
error = Curl::Easy.error(self.last_result)
|
|
60
|
-
raise error.first
|
|
78
|
+
error = Curl::Easy.error(self.last_result)
|
|
79
|
+
raise error.first.new(self.head)
|
|
61
80
|
end
|
|
62
81
|
|
|
63
82
|
ret
|
|
@@ -81,54 +100,55 @@ module Curl
|
|
|
81
100
|
# easy.perform
|
|
82
101
|
#
|
|
83
102
|
def delete=(onoff)
|
|
84
|
-
set :customrequest, onoff ? '
|
|
103
|
+
set :customrequest, onoff ? 'DELETE' : nil
|
|
85
104
|
onoff
|
|
86
105
|
end
|
|
87
|
-
#
|
|
106
|
+
#
|
|
88
107
|
# call-seq:
|
|
89
|
-
#
|
|
108
|
+
#
|
|
90
109
|
# easy = Curl::Easy.new("url")
|
|
110
|
+
# easy.version = Curl::HTTP_2_0
|
|
91
111
|
# easy.version = Curl::HTTP_1_1
|
|
92
112
|
# easy.version = Curl::HTTP_1_0
|
|
93
113
|
# easy.version = Curl::HTTP_NONE
|
|
94
|
-
#
|
|
114
|
+
#
|
|
95
115
|
def version=(http_version)
|
|
96
116
|
set :http_version, http_version
|
|
97
117
|
end
|
|
98
118
|
|
|
99
|
-
#
|
|
119
|
+
#
|
|
100
120
|
# call-seq:
|
|
101
121
|
# easy.url = "http://some.url/" => "http://some.url/"
|
|
102
|
-
#
|
|
122
|
+
#
|
|
103
123
|
# Set the URL for subsequent calls to +perform+. It is acceptable
|
|
104
124
|
# (and even recommended) to reuse Curl::Easy instances by reassigning
|
|
105
125
|
# the URL between calls to +perform+.
|
|
106
|
-
#
|
|
126
|
+
#
|
|
107
127
|
def url=(u)
|
|
108
128
|
set :url, u
|
|
109
129
|
end
|
|
110
130
|
|
|
111
|
-
#
|
|
131
|
+
#
|
|
112
132
|
# call-seq:
|
|
113
133
|
# easy.proxy_url = string => string
|
|
114
|
-
#
|
|
134
|
+
#
|
|
115
135
|
# Set the URL of the HTTP proxy to use for subsequent calls to +perform+.
|
|
116
136
|
# The URL should specify the the host name or dotted IP address. To specify
|
|
117
137
|
# port number in this string, append :[port] to the end of the host name.
|
|
118
138
|
# The proxy string may be prefixed with [protocol]:// since any such prefix
|
|
119
139
|
# will be ignored. The proxy's port number may optionally be specified with
|
|
120
140
|
# the separate option proxy_port .
|
|
121
|
-
#
|
|
141
|
+
#
|
|
122
142
|
# When you tell the library to use an HTTP proxy, libcurl will transparently
|
|
123
143
|
# convert operations to HTTP even if you specify an FTP URL etc. This may have
|
|
124
144
|
# an impact on what other features of the library you can use, such as
|
|
125
145
|
# FTP specifics that don't work unless you tunnel through the HTTP proxy. Such
|
|
126
146
|
# tunneling is activated with proxy_tunnel = true.
|
|
127
|
-
#
|
|
147
|
+
#
|
|
128
148
|
# libcurl respects the environment variables *http_proxy*, *ftp_proxy*,
|
|
129
149
|
# *all_proxy* etc, if any of those is set. The proxy_url option does however
|
|
130
150
|
# override any possibly set environment variables.
|
|
131
|
-
#
|
|
151
|
+
#
|
|
132
152
|
# Starting with libcurl 7.14.1, the proxy host string given in environment
|
|
133
153
|
# variables can be specified the exact same way as the proxy can be set with
|
|
134
154
|
# proxy_url, including protocol prefix (http://) and embedded user + password.
|
|
@@ -143,89 +163,89 @@ module Curl
|
|
|
143
163
|
self.ssl_verify_host_integer=value
|
|
144
164
|
end
|
|
145
165
|
|
|
146
|
-
#
|
|
166
|
+
#
|
|
147
167
|
# call-seq:
|
|
148
168
|
# easy.ssl_verify_host? => boolean
|
|
149
|
-
#
|
|
169
|
+
#
|
|
150
170
|
# Deprecated: call easy.ssl_verify_host instead
|
|
151
171
|
# can be one of [0,1,2]
|
|
152
|
-
#
|
|
172
|
+
#
|
|
153
173
|
# Determine whether this Curl instance will verify that the server cert
|
|
154
174
|
# is for the server it is known as.
|
|
155
|
-
#
|
|
175
|
+
#
|
|
156
176
|
def ssl_verify_host?
|
|
157
177
|
ssl_verify_host.nil? ? false : (ssl_verify_host > 0)
|
|
158
178
|
end
|
|
159
179
|
|
|
160
|
-
#
|
|
180
|
+
#
|
|
161
181
|
# call-seq:
|
|
162
182
|
# easy.interface = string => string
|
|
163
|
-
#
|
|
183
|
+
#
|
|
164
184
|
# Set the interface name to use as the outgoing network interface.
|
|
165
185
|
# The name can be an interface name, an IP address or a host name.
|
|
166
|
-
#
|
|
186
|
+
#
|
|
167
187
|
def interface=(value)
|
|
168
188
|
set :interface, value
|
|
169
189
|
end
|
|
170
190
|
|
|
171
|
-
#
|
|
191
|
+
#
|
|
172
192
|
# call-seq:
|
|
173
193
|
# easy.userpwd = string => string
|
|
174
|
-
#
|
|
194
|
+
#
|
|
175
195
|
# Set the username/password string to use for subsequent calls to +perform+.
|
|
176
196
|
# The supplied string should have the form "username:password"
|
|
177
|
-
#
|
|
197
|
+
#
|
|
178
198
|
def userpwd=(value)
|
|
179
199
|
set :userpwd, value
|
|
180
200
|
end
|
|
181
201
|
|
|
182
|
-
#
|
|
202
|
+
#
|
|
183
203
|
# call-seq:
|
|
184
204
|
# easy.proxypwd = string => string
|
|
185
|
-
#
|
|
205
|
+
#
|
|
186
206
|
# Set the username/password string to use for proxy connection during
|
|
187
207
|
# subsequent calls to +perform+. The supplied string should have the
|
|
188
208
|
# form "username:password"
|
|
189
|
-
#
|
|
209
|
+
#
|
|
190
210
|
def proxypwd=(value)
|
|
191
211
|
set :proxyuserpwd, value
|
|
192
212
|
end
|
|
193
213
|
|
|
194
|
-
#
|
|
214
|
+
#
|
|
195
215
|
# call-seq:
|
|
196
216
|
# easy.cookies = "name1=content1; name2=content2;" => string
|
|
197
|
-
#
|
|
217
|
+
#
|
|
198
218
|
# Set cookies to be sent by this Curl::Easy instance. The format of the string should
|
|
199
219
|
# be NAME=CONTENTS, where NAME is the cookie name and CONTENTS is what the cookie should contain.
|
|
200
220
|
# Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc.
|
|
201
|
-
#
|
|
221
|
+
#
|
|
202
222
|
def cookies=(value)
|
|
203
223
|
set :cookie, value
|
|
204
224
|
end
|
|
205
225
|
|
|
206
|
-
#
|
|
226
|
+
#
|
|
207
227
|
# call-seq:
|
|
208
228
|
# easy.cookiefile = string => string
|
|
209
|
-
#
|
|
229
|
+
#
|
|
210
230
|
# Set a file that contains cookies to be sent in subsequent requests by this Curl::Easy instance.
|
|
211
|
-
#
|
|
231
|
+
#
|
|
212
232
|
# *Note* that you must set enable_cookies true to enable the cookie
|
|
213
233
|
# engine, or this option will be ignored.
|
|
214
|
-
#
|
|
234
|
+
#
|
|
215
235
|
def cookiefile=(value)
|
|
216
236
|
set :cookiefile, value
|
|
217
237
|
end
|
|
218
238
|
|
|
219
|
-
#
|
|
239
|
+
#
|
|
220
240
|
# call-seq:
|
|
221
241
|
# easy.cookiejar = string => string
|
|
222
|
-
#
|
|
242
|
+
#
|
|
223
243
|
# Set a cookiejar file to use for this Curl::Easy instance.
|
|
224
244
|
# Cookies from the response will be written into this file.
|
|
225
|
-
#
|
|
245
|
+
#
|
|
226
246
|
# *Note* that you must set enable_cookies true to enable the cookie
|
|
227
247
|
# engine, or this option will be ignored.
|
|
228
|
-
#
|
|
248
|
+
#
|
|
229
249
|
def cookiejar=(value)
|
|
230
250
|
set :cookiejar, value
|
|
231
251
|
end
|
|
@@ -403,35 +423,35 @@ module Curl
|
|
|
403
423
|
c.http_delete
|
|
404
424
|
c
|
|
405
425
|
end
|
|
406
|
-
|
|
426
|
+
|
|
407
427
|
# call-seq:
|
|
408
428
|
# Curl::Easy.download(url, filename = url.split(/\?/).first.split(/\//).last) { |curl| ... }
|
|
409
|
-
#
|
|
429
|
+
#
|
|
410
430
|
# 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
|
|
431
|
+
# supplied filename (defaults to the last component of the URL path, which will
|
|
412
432
|
# usually be the filename most simple urls).
|
|
413
|
-
#
|
|
433
|
+
#
|
|
414
434
|
# If a block is supplied, it will be passed the curl instance prior to the
|
|
415
435
|
# perform call.
|
|
416
|
-
#
|
|
436
|
+
#
|
|
417
437
|
# *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
|
|
438
|
+
# download, to account for the automatic routing of data to the specified file: The
|
|
419
439
|
# data string is passed to the handler *before* it is written
|
|
420
|
-
# to the file, allowing the handler to perform mutative operations where
|
|
440
|
+
# to the file, allowing the handler to perform mutative operations where
|
|
421
441
|
# 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
|
|
442
|
+
# returns a size that differs from the data chunk size - in this case, the
|
|
423
443
|
# offending chunk will *not* be written to the file, the file will be closed,
|
|
424
444
|
# and a Curl::Err::AbortedByCallbackError will be raised.
|
|
425
445
|
def download(url, filename = url.split(/\?/).first.split(/\//).last, &blk)
|
|
426
446
|
curl = Curl::Easy.new(url, &blk)
|
|
427
|
-
|
|
447
|
+
|
|
428
448
|
output = if filename.is_a? IO
|
|
429
449
|
filename.binmode if filename.respond_to?(:binmode)
|
|
430
450
|
filename
|
|
431
451
|
else
|
|
432
452
|
File.open(filename, 'wb')
|
|
433
453
|
end
|
|
434
|
-
|
|
454
|
+
|
|
435
455
|
begin
|
|
436
456
|
old_on_body = curl.on_body do |data|
|
|
437
457
|
result = old_on_body ? old_on_body.call(data) : data.length
|
|
@@ -442,7 +462,7 @@ module Curl
|
|
|
442
462
|
ensure
|
|
443
463
|
output.close rescue IOError
|
|
444
464
|
end
|
|
445
|
-
|
|
465
|
+
|
|
446
466
|
return curl
|
|
447
467
|
end
|
|
448
468
|
end
|
data/lib/curl/multi.rb
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Curl
|
|
2
|
-
|
|
3
3
|
class Multi
|
|
4
4
|
class << self
|
|
5
5
|
# call-seq:
|
|
6
|
-
# Curl::Multi.get('url1','url2','url3','url4','url5', :follow_location => true) do|easy|
|
|
6
|
+
# Curl::Multi.get(['url1','url2','url3','url4','url5'], :follow_location => true) do|easy|
|
|
7
7
|
# easy
|
|
8
8
|
# end
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# Blocking call to fetch multiple url's in parallel.
|
|
11
11
|
def get(urls, easy_options={}, multi_options={}, &blk)
|
|
12
12
|
url_confs = []
|
|
@@ -22,13 +22,13 @@ module Curl
|
|
|
22
22
|
# {:url => 'url2', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}},
|
|
23
23
|
# {:url => 'url3', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}}],
|
|
24
24
|
# { :follow_location => true, :multipart_form_post => true },
|
|
25
|
-
# {:pipeline =>
|
|
25
|
+
# {:pipeline => Curl::CURLPIPE_HTTP1}) do|easy|
|
|
26
26
|
# easy_handle_on_request_complete
|
|
27
27
|
# end
|
|
28
|
-
#
|
|
28
|
+
#
|
|
29
29
|
# Blocking call to POST multiple form's in parallel.
|
|
30
|
-
#
|
|
31
|
-
# urls_with_config: is a hash of url's pointing to the postfields to send
|
|
30
|
+
#
|
|
31
|
+
# urls_with_config: is a hash of url's pointing to the postfields to send
|
|
32
32
|
# easy_options: are a set of common options to set on all easy handles
|
|
33
33
|
# multi_options: options to set on the Curl::Multi handle
|
|
34
34
|
#
|
|
@@ -46,13 +46,13 @@ module Curl
|
|
|
46
46
|
# {:url => 'url2', :put_data => IO.read('filepath')},
|
|
47
47
|
# {:url => 'url3', :put_data => "maybe another string or socket?"],
|
|
48
48
|
# {:follow_location => true},
|
|
49
|
-
# {:pipeline =>
|
|
49
|
+
# {:pipeline => Curl::CURLPIPE_HTTP1}) do|easy|
|
|
50
50
|
# easy_handle_on_request_complete
|
|
51
51
|
# end
|
|
52
|
-
#
|
|
52
|
+
#
|
|
53
53
|
# Blocking call to POST multiple form's in parallel.
|
|
54
|
-
#
|
|
55
|
-
# urls_with_config: is a hash of url's pointing to the postfields to send
|
|
54
|
+
#
|
|
55
|
+
# urls_with_config: is a hash of url's pointing to the postfields to send
|
|
56
56
|
# easy_options: are a set of common options to set on all easy handles
|
|
57
57
|
# multi_options: options to set on the Curl::Multi handle
|
|
58
58
|
#
|
|
@@ -74,12 +74,12 @@ module Curl
|
|
|
74
74
|
# :follow_location => true, :max_redirects => 3 },
|
|
75
75
|
# { :url => 'url3', :method => :put, :put_data => File.open('file.txt','rb') },
|
|
76
76
|
# { :url => 'url4', :method => :head }
|
|
77
|
-
# ], {:pipeline =>
|
|
77
|
+
# ], {:pipeline => Curl::CURLPIPE_HTTP1})
|
|
78
78
|
#
|
|
79
79
|
# Blocking call to issue multiple HTTP requests with varying verb's.
|
|
80
80
|
#
|
|
81
81
|
# urls_with_config: is a hash of url's pointing to the easy handle options as well as the special option :method, that can by one of [:get, :post, :put, :delete, :head], when no verb is provided e.g. :method => nil -> GET is used
|
|
82
|
-
# multi_options: options for the multi handle
|
|
82
|
+
# multi_options: options for the multi handle
|
|
83
83
|
# blk: a callback, that yeilds when a handle is completed
|
|
84
84
|
#
|
|
85
85
|
def http(urls_with_config, multi_options={}, &blk)
|
|
@@ -92,7 +92,7 @@ module Curl
|
|
|
92
92
|
|
|
93
93
|
# configure the multi handle
|
|
94
94
|
multi_options.each { |k,v| m.send("#{k}=", v) }
|
|
95
|
-
callbacks = [:on_progress,:on_debug,:on_failure,:on_success,:on_body,:on_header]
|
|
95
|
+
callbacks = [:on_progress,:on_debug,:on_failure,:on_success,:on_redirect,:on_body,:on_header]
|
|
96
96
|
|
|
97
97
|
add_free_handle = proc do|conf, easy|
|
|
98
98
|
c = conf.dup # avoid being destructive to input
|
|
@@ -128,23 +128,23 @@ module Curl
|
|
|
128
128
|
|
|
129
129
|
# headers is a special key
|
|
130
130
|
headers.each {|k,v| easy.headers[k] = v } if headers
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
#
|
|
133
133
|
# use the remaining options as specific configuration to the easy handle
|
|
134
134
|
# bad options should raise an undefined method error
|
|
135
135
|
#
|
|
136
136
|
c.each { |k,v| easy.send("#{k}=",v) }
|
|
137
137
|
|
|
138
|
-
easy.on_complete {|curl
|
|
138
|
+
easy.on_complete {|curl|
|
|
139
139
|
free_handles << curl
|
|
140
|
-
blk.call(curl,
|
|
140
|
+
blk.call(curl,curl.response_code,method) if blk
|
|
141
141
|
}
|
|
142
142
|
m.add(easy)
|
|
143
143
|
end
|
|
144
144
|
|
|
145
145
|
max_connects.times do
|
|
146
146
|
conf = urls_with_config.pop
|
|
147
|
-
add_free_handle.call
|
|
147
|
+
add_free_handle.call(conf, nil) if conf
|
|
148
148
|
break if urls_with_config.empty?
|
|
149
149
|
end
|
|
150
150
|
|
|
@@ -153,7 +153,7 @@ module Curl
|
|
|
153
153
|
if urls_with_config.size > 0 && free_handles.size > 0
|
|
154
154
|
easy = free_handles.pop
|
|
155
155
|
conf = urls_with_config.pop
|
|
156
|
-
add_free_handle.call
|
|
156
|
+
add_free_handle.call(conf, easy) if conf
|
|
157
157
|
end
|
|
158
158
|
end
|
|
159
159
|
|
|
@@ -168,6 +168,7 @@ module Curl
|
|
|
168
168
|
end
|
|
169
169
|
free_handles = nil
|
|
170
170
|
end
|
|
171
|
+
|
|
171
172
|
end
|
|
172
173
|
|
|
173
174
|
# call-seq:
|
|
@@ -175,7 +176,7 @@ module Curl
|
|
|
175
176
|
# Curl::Multi.download(['http://example.com/p/a/t/h/file1.txt','http://example.com/p/a/t/h/file2.txt']){|c|}
|
|
176
177
|
#
|
|
177
178
|
# will create 2 new files file1.txt and file2.txt
|
|
178
|
-
#
|
|
179
|
+
#
|
|
179
180
|
# 2 files will be opened, and remain open until the call completes
|
|
180
181
|
#
|
|
181
182
|
# when using the :post or :put method, urls should be a hash, including the individual post fields per post
|
|
@@ -242,7 +243,45 @@ module Curl
|
|
|
242
243
|
}
|
|
243
244
|
raise errors unless errors.empty?
|
|
244
245
|
end
|
|
246
|
+
end
|
|
245
247
|
|
|
248
|
+
def cancel!
|
|
249
|
+
requests.each do |_,easy|
|
|
250
|
+
remove(easy)
|
|
251
|
+
end
|
|
246
252
|
end
|
|
253
|
+
|
|
254
|
+
def idle?
|
|
255
|
+
requests.empty?
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def requests
|
|
259
|
+
@requests ||= {}
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def add(easy)
|
|
263
|
+
return self if requests[easy.object_id]
|
|
264
|
+
requests[easy.object_id] = easy
|
|
265
|
+
_add(easy)
|
|
266
|
+
self
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def remove(easy)
|
|
270
|
+
return self if !requests[easy.object_id]
|
|
271
|
+
requests.delete(easy.object_id)
|
|
272
|
+
_remove(easy)
|
|
273
|
+
self
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def close
|
|
277
|
+
requests.values.each {|easy|
|
|
278
|
+
_remove(easy)
|
|
279
|
+
}
|
|
280
|
+
@requests = {}
|
|
281
|
+
_close
|
|
282
|
+
self
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
|
|
247
286
|
end
|
|
248
287
|
end
|
data/lib/curl.rb
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'curb_core'
|
|
2
3
|
require 'curl/easy'
|
|
3
4
|
require 'curl/multi'
|
|
4
5
|
require 'uri'
|
|
6
|
+
require 'cgi'
|
|
5
7
|
|
|
6
8
|
# expose shortcut methods
|
|
7
9
|
module Curl
|
|
8
|
-
|
|
10
|
+
|
|
9
11
|
def self.http(verb, url, post_body=nil, put_data=nil, &block)
|
|
10
12
|
handle = Thread.current[:curb_curl] ||= Curl::Easy.new
|
|
13
|
+
handle.reset
|
|
11
14
|
handle.url = url
|
|
12
15
|
handle.post_body = post_body if post_body
|
|
13
16
|
handle.put_data = put_data if put_data
|
|
@@ -45,18 +48,21 @@ module Curl
|
|
|
45
48
|
end
|
|
46
49
|
|
|
47
50
|
def self.urlalize(url, params={})
|
|
48
|
-
|
|
49
|
-
if
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
end
|
|
51
|
+
uri = URI(url)
|
|
52
|
+
# early return if we didn't specify any extra params
|
|
53
|
+
return uri.to_s if (params || {}).empty?
|
|
54
|
+
|
|
55
|
+
params_query = URI.encode_www_form(params || {})
|
|
56
|
+
uri.query = [uri.query.to_s, params_query].reject(&:empty?).join('&')
|
|
57
|
+
uri.to_s
|
|
56
58
|
end
|
|
57
59
|
|
|
58
60
|
def self.postalize(params={})
|
|
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
|