curb 0.8.4 → 1.3.5
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.md +522 -0
- data/Rakefile +79 -26
- data/ext/banned.h +32 -0
- data/ext/curb.c +549 -230
- data/ext/curb.h +19 -10
- data/ext/curb_easy.c +1935 -366
- data/ext/curb_easy.h +16 -0
- data/ext/curb_errors.c +115 -18
- data/ext/curb_errors.h +8 -5
- data/ext/curb_macros.h +33 -21
- data/ext/curb_multi.c +1858 -272
- data/ext/curb_multi.h +10 -3
- data/ext/curb_postfield.c +149 -77
- data/ext/curb_postfield.h +1 -0
- data/ext/curb_upload.c +38 -11
- data/ext/curb_upload.h +2 -0
- data/ext/extconf.rb +353 -35
- data/lib/curb.rb +1 -0
- data/lib/curl/easy.rb +314 -78
- data/lib/curl/multi.rb +134 -28
- data/lib/curl.rb +217 -11
- data/tests/bug_crash_on_debug.rb +14 -28
- data/tests/bug_crash_on_progress.rb +32 -16
- data/tests/bug_curb_easy_blocks_ruby_threads.rb +10 -15
- data/tests/bug_curb_easy_post_with_string_no_content_length_header.rb +6 -30
- data/tests/bug_follow_redirect_288.rb +83 -0
- data/tests/bug_instance_post_differs_from_class_post.rb +3 -5
- data/tests/bug_issue102.rb +1 -1
- data/tests/bug_issue_noproxy.rb +56 -0
- data/tests/bug_issue_post_redirect.rb +93 -0
- data/tests/bug_issue_spnego.rb +41 -0
- data/tests/bug_multi_segfault.rb +1 -0
- data/tests/bug_raise_on_callback.rb +30 -0
- data/tests/helper.rb +400 -44
- data/tests/leak_trace.rb +237 -0
- data/tests/mem_check.rb +3 -0
- data/tests/tc_curl.rb +31 -1
- data/tests/tc_curl_download.rb +12 -7
- data/tests/tc_curl_easy.rb +911 -63
- data/tests/tc_curl_easy_cookielist.rb +277 -0
- data/tests/tc_curl_easy_request_target.rb +41 -0
- data/tests/tc_curl_easy_resolve.rb +48 -0
- data/tests/tc_curl_maxfilesize.rb +12 -0
- data/tests/tc_curl_multi.rb +855 -53
- data/tests/tc_curl_native_coverage.rb +145 -0
- data/tests/tc_curl_postfield.rb +207 -30
- data/tests/tc_curl_protocols.rb +37 -0
- data/tests/tc_fiber_scheduler.rb +543 -0
- data/tests/tc_ftp_options.rb +39 -0
- data/tests/tc_gc_compact.rb +223 -0
- data/tests/tc_test_server_methods.rb +110 -0
- data/tests/timeout.rb +30 -6
- metadata +59 -36
- data/README +0 -194
data/lib/curl/easy.rb
CHANGED
|
@@ -1,34 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Curl
|
|
2
3
|
class Easy
|
|
4
|
+
class << self
|
|
5
|
+
def deferred_multi_close_mutex
|
|
6
|
+
@deferred_multi_close_mutex ||= Mutex.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def deferred_multi_closes
|
|
10
|
+
deferred_multi_close_mutex.synchronize do
|
|
11
|
+
(@deferred_multi_closes ||= []).dup
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def release_deferred_multi_close(multi, easy)
|
|
16
|
+
if easy && multi.requests[easy.object_id]
|
|
17
|
+
begin
|
|
18
|
+
multi.remove(easy)
|
|
19
|
+
rescue StandardError
|
|
20
|
+
# Deferred cleanup only applies to implicit single-easy multis, so
|
|
21
|
+
# clear any stale Ruby bookkeeping and continue closing the handle.
|
|
22
|
+
multi.instance_variable_set(:@requests, {})
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
multi.instance_variable_set(:@requests, {})
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
multi.instance_variable_set(:@deferred_close, false)
|
|
29
|
+
multi._close
|
|
30
|
+
true
|
|
31
|
+
rescue StandardError
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def defer_multi_close(multi, easy, owner: Thread.current)
|
|
36
|
+
deferred_multi_close_mutex.synchronize do
|
|
37
|
+
@deferred_multi_closes ||= []
|
|
38
|
+
return if @deferred_multi_closes.any? { |entry| entry[:multi].equal?(multi) }
|
|
39
|
+
|
|
40
|
+
multi.instance_variable_set(:@deferred_close, true)
|
|
41
|
+
@deferred_multi_closes << { multi: multi, easy: easy, owner: owner }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def flush_deferred_multi_closes(all_threads: false)
|
|
46
|
+
pending = deferred_multi_close_mutex.synchronize do
|
|
47
|
+
@deferred_multi_closes ||= []
|
|
48
|
+
|
|
49
|
+
if all_threads
|
|
50
|
+
@deferred_multi_closes.shift(@deferred_multi_closes.length)
|
|
51
|
+
else
|
|
52
|
+
owner = Thread.current
|
|
53
|
+
remaining = []
|
|
54
|
+
current = []
|
|
55
|
+
|
|
56
|
+
@deferred_multi_closes.each do |entry|
|
|
57
|
+
if entry[:owner].equal?(owner)
|
|
58
|
+
current << entry
|
|
59
|
+
else
|
|
60
|
+
remaining << entry
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
@deferred_multi_closes = remaining
|
|
65
|
+
current
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
pending.each do |entry|
|
|
70
|
+
multi = entry[:multi]
|
|
71
|
+
easy = entry[:easy]
|
|
72
|
+
|
|
73
|
+
unless release_deferred_multi_close(multi, easy)
|
|
74
|
+
defer_multi_close(multi, easy, owner: entry[:owner])
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
3
79
|
|
|
80
|
+
at_exit do
|
|
81
|
+
flush_deferred_multi_closes(all_threads: true)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
alias_method :_curb_native_close, :close
|
|
85
|
+
alias_method :_curb_native_multi_set, :multi=
|
|
86
|
+
|
|
87
|
+
def close
|
|
88
|
+
previous_multi = self.multi
|
|
89
|
+
result = _curb_native_close
|
|
90
|
+
previous_multi.__send__(:__unregister_idle_easy_reference, self) if previous_multi
|
|
91
|
+
result
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def multi=(multi)
|
|
95
|
+
previous_multi = self.multi
|
|
96
|
+
return multi if previous_multi.equal?(multi)
|
|
97
|
+
|
|
98
|
+
result = _curb_native_multi_set(multi)
|
|
99
|
+
previous_multi.__send__(:__unregister_idle_easy_reference, self) if previous_multi
|
|
100
|
+
multi.__send__(:__register_idle_easy_reference, self) if multi
|
|
101
|
+
result
|
|
102
|
+
end
|
|
103
|
+
|
|
4
104
|
alias post http_post
|
|
5
105
|
alias put http_put
|
|
106
|
+
alias body body_str
|
|
107
|
+
alias head header_str
|
|
108
|
+
|
|
109
|
+
class Error < StandardError
|
|
110
|
+
attr_accessor :message, :code
|
|
111
|
+
def initialize(code, msg)
|
|
112
|
+
self.message = msg
|
|
113
|
+
self.code = code
|
|
114
|
+
end
|
|
115
|
+
end
|
|
6
116
|
|
|
7
117
|
#
|
|
8
118
|
# call-seq:
|
|
9
119
|
# easy.status => String
|
|
10
120
|
#
|
|
11
121
|
def status
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
while parts.size > 0 && parts.first != ''
|
|
16
|
-
status << parts.shift
|
|
17
|
-
end
|
|
18
|
-
status.join(' ')
|
|
122
|
+
# Matches the last HTTP Status - following the HTTP protocol specification 'Status-Line = HTTP-Version SP Status-Code SP (Opt:)Reason-Phrase CRLF'
|
|
123
|
+
statuses = self.header_str.to_s.scan(/HTTP\/\d(\.\d)?\s(\d+\s.*)\r\n/).map {|match| match[1] }
|
|
124
|
+
statuses.last.strip if statuses.length > 0
|
|
19
125
|
end
|
|
20
126
|
|
|
21
127
|
#
|
|
22
128
|
# call-seq:
|
|
23
129
|
# easy.set :sym|Fixnum, value
|
|
24
|
-
#
|
|
130
|
+
#
|
|
25
131
|
# set options on the curl easy handle see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
|
|
26
132
|
#
|
|
27
133
|
def set(opt,val)
|
|
28
134
|
if opt.is_a?(Symbol)
|
|
29
|
-
|
|
135
|
+
option = sym2curl(opt)
|
|
30
136
|
else
|
|
31
|
-
|
|
137
|
+
option = opt.to_i
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
begin
|
|
141
|
+
setopt(option, val)
|
|
142
|
+
rescue TypeError
|
|
143
|
+
raise TypeError, "Curb doesn't support setting #{opt} [##{option}] option"
|
|
32
144
|
end
|
|
33
145
|
end
|
|
34
146
|
|
|
@@ -51,13 +163,57 @@ module Curl
|
|
|
51
163
|
# the configured HTTP Verb.
|
|
52
164
|
#
|
|
53
165
|
def perform
|
|
54
|
-
self.
|
|
55
|
-
|
|
56
|
-
|
|
166
|
+
self.class.flush_deferred_multi_closes
|
|
167
|
+
|
|
168
|
+
if Curl.scheduler_active? && self.multi.nil?
|
|
169
|
+
ret = Curl.perform_with_scheduler(self)
|
|
170
|
+
else
|
|
171
|
+
multi = self.multi
|
|
172
|
+
created_multi = multi.nil?
|
|
173
|
+
raised = false
|
|
174
|
+
|
|
175
|
+
if created_multi
|
|
176
|
+
multi = Curl::Multi.new
|
|
177
|
+
self.multi = multi
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
begin
|
|
181
|
+
multi.add(self)
|
|
182
|
+
ret = multi.perform
|
|
183
|
+
multi.remove(self) if self.multi == multi
|
|
184
|
+
rescue Exception
|
|
185
|
+
raised = true
|
|
186
|
+
raise
|
|
187
|
+
ensure
|
|
188
|
+
if created_multi
|
|
189
|
+
if raised
|
|
190
|
+
unless self.class.release_deferred_multi_close(multi, self)
|
|
191
|
+
self.class.defer_multi_close(multi, self)
|
|
192
|
+
end
|
|
193
|
+
self.multi = nil if self.multi == multi
|
|
194
|
+
elsif Curl::Multi.autoclose
|
|
195
|
+
multi.__send__(:_autoclose)
|
|
196
|
+
self.multi = nil if self.multi == multi
|
|
197
|
+
else
|
|
198
|
+
self.multi = multi
|
|
199
|
+
end
|
|
200
|
+
elsif Curl::Multi.autoclose
|
|
201
|
+
multi.__send__(:_autoclose)
|
|
202
|
+
self.multi = nil if self.multi == multi
|
|
203
|
+
else
|
|
204
|
+
self.multi = multi
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
if (callback_error = _take_callback_error)
|
|
210
|
+
raise callback_error
|
|
211
|
+
end
|
|
57
212
|
|
|
58
213
|
if self.last_result != 0 && self.on_failure.nil?
|
|
59
|
-
|
|
60
|
-
|
|
214
|
+
err_class, err_summary = Curl::Easy.error(self.last_result)
|
|
215
|
+
err_detail = self.last_error
|
|
216
|
+
raise err_class.new([err_summary, err_detail].compact.join(": "))
|
|
61
217
|
end
|
|
62
218
|
|
|
63
219
|
ret
|
|
@@ -65,6 +221,7 @@ module Curl
|
|
|
65
221
|
|
|
66
222
|
#
|
|
67
223
|
# call-seq:
|
|
224
|
+
|
|
68
225
|
#
|
|
69
226
|
# easy = Curl::Easy.new
|
|
70
227
|
# easy.nosignal = true
|
|
@@ -81,54 +238,59 @@ module Curl
|
|
|
81
238
|
# easy.perform
|
|
82
239
|
#
|
|
83
240
|
def delete=(onoff)
|
|
84
|
-
set :customrequest, onoff ? '
|
|
241
|
+
set :customrequest, onoff ? 'DELETE' : nil
|
|
85
242
|
onoff
|
|
86
243
|
end
|
|
87
|
-
#
|
|
244
|
+
#
|
|
88
245
|
# call-seq:
|
|
89
|
-
#
|
|
246
|
+
#
|
|
90
247
|
# easy = Curl::Easy.new("url")
|
|
91
|
-
# easy.version = Curl::
|
|
92
|
-
# easy.
|
|
93
|
-
# easy.
|
|
94
|
-
#
|
|
248
|
+
# easy.version = Curl::HTTP_2_0
|
|
249
|
+
# easy.http_version = Curl::HTTP_1_1
|
|
250
|
+
# easy.http_version = Curl::HTTP_1_0
|
|
251
|
+
# easy.http_version = Curl::HTTP_NONE
|
|
252
|
+
#
|
|
95
253
|
def version=(http_version)
|
|
96
|
-
|
|
254
|
+
self.http_version = http_version
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def version
|
|
258
|
+
http_version
|
|
97
259
|
end
|
|
98
260
|
|
|
99
|
-
#
|
|
261
|
+
#
|
|
100
262
|
# call-seq:
|
|
101
263
|
# easy.url = "http://some.url/" => "http://some.url/"
|
|
102
|
-
#
|
|
264
|
+
#
|
|
103
265
|
# Set the URL for subsequent calls to +perform+. It is acceptable
|
|
104
266
|
# (and even recommended) to reuse Curl::Easy instances by reassigning
|
|
105
267
|
# the URL between calls to +perform+.
|
|
106
|
-
#
|
|
268
|
+
#
|
|
107
269
|
def url=(u)
|
|
108
270
|
set :url, u
|
|
109
271
|
end
|
|
110
272
|
|
|
111
|
-
#
|
|
273
|
+
#
|
|
112
274
|
# call-seq:
|
|
113
275
|
# easy.proxy_url = string => string
|
|
114
|
-
#
|
|
276
|
+
#
|
|
115
277
|
# Set the URL of the HTTP proxy to use for subsequent calls to +perform+.
|
|
116
278
|
# The URL should specify the the host name or dotted IP address. To specify
|
|
117
279
|
# port number in this string, append :[port] to the end of the host name.
|
|
118
280
|
# The proxy string may be prefixed with [protocol]:// since any such prefix
|
|
119
281
|
# will be ignored. The proxy's port number may optionally be specified with
|
|
120
282
|
# the separate option proxy_port .
|
|
121
|
-
#
|
|
283
|
+
#
|
|
122
284
|
# When you tell the library to use an HTTP proxy, libcurl will transparently
|
|
123
285
|
# convert operations to HTTP even if you specify an FTP URL etc. This may have
|
|
124
286
|
# an impact on what other features of the library you can use, such as
|
|
125
287
|
# FTP specifics that don't work unless you tunnel through the HTTP proxy. Such
|
|
126
288
|
# tunneling is activated with proxy_tunnel = true.
|
|
127
|
-
#
|
|
289
|
+
#
|
|
128
290
|
# libcurl respects the environment variables *http_proxy*, *ftp_proxy*,
|
|
129
291
|
# *all_proxy* etc, if any of those is set. The proxy_url option does however
|
|
130
292
|
# override any possibly set environment variables.
|
|
131
|
-
#
|
|
293
|
+
#
|
|
132
294
|
# Starting with libcurl 7.14.1, the proxy host string given in environment
|
|
133
295
|
# variables can be specified the exact same way as the proxy can be set with
|
|
134
296
|
# proxy_url, including protocol prefix (http://) and embedded user + password.
|
|
@@ -137,99 +299,150 @@ module Curl
|
|
|
137
299
|
set :proxy, url
|
|
138
300
|
end
|
|
139
301
|
|
|
302
|
+
#
|
|
303
|
+
# call-seq:
|
|
304
|
+
# easy.request_target = string => string
|
|
305
|
+
#
|
|
306
|
+
# Set the request-target used in the HTTP request line (libcurl CURLOPT_REQUEST_TARGET).
|
|
307
|
+
# Useful for absolute-form request targets (e.g., when speaking to proxies) or
|
|
308
|
+
# special targets like "*" (OPTIONS *). Requires libcurl with CURLOPT_REQUEST_TARGET support.
|
|
309
|
+
#
|
|
310
|
+
def request_target=(value)
|
|
311
|
+
if Curl.const_defined?(:CURLOPT_REQUEST_TARGET)
|
|
312
|
+
set :request_target, value
|
|
313
|
+
else
|
|
314
|
+
raise NotImplementedError, "CURLOPT_REQUEST_TARGET is not supported by this libcurl"
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
140
318
|
def ssl_verify_host=(value)
|
|
141
319
|
value = 1 if value.class == TrueClass
|
|
142
320
|
value = 0 if value.class == FalseClass
|
|
143
321
|
self.ssl_verify_host_integer=value
|
|
144
322
|
end
|
|
145
323
|
|
|
146
|
-
#
|
|
324
|
+
#
|
|
147
325
|
# call-seq:
|
|
148
326
|
# easy.ssl_verify_host? => boolean
|
|
149
|
-
#
|
|
327
|
+
#
|
|
150
328
|
# Deprecated: call easy.ssl_verify_host instead
|
|
151
329
|
# can be one of [0,1,2]
|
|
152
|
-
#
|
|
330
|
+
#
|
|
153
331
|
# Determine whether this Curl instance will verify that the server cert
|
|
154
332
|
# is for the server it is known as.
|
|
155
|
-
#
|
|
333
|
+
#
|
|
156
334
|
def ssl_verify_host?
|
|
157
335
|
ssl_verify_host.nil? ? false : (ssl_verify_host > 0)
|
|
158
336
|
end
|
|
159
337
|
|
|
160
|
-
#
|
|
338
|
+
#
|
|
161
339
|
# call-seq:
|
|
162
340
|
# easy.interface = string => string
|
|
163
|
-
#
|
|
341
|
+
#
|
|
164
342
|
# Set the interface name to use as the outgoing network interface.
|
|
165
343
|
# The name can be an interface name, an IP address or a host name.
|
|
166
|
-
#
|
|
344
|
+
#
|
|
167
345
|
def interface=(value)
|
|
168
346
|
set :interface, value
|
|
169
347
|
end
|
|
170
348
|
|
|
171
|
-
#
|
|
349
|
+
#
|
|
172
350
|
# call-seq:
|
|
173
351
|
# easy.userpwd = string => string
|
|
174
|
-
#
|
|
352
|
+
#
|
|
175
353
|
# Set the username/password string to use for subsequent calls to +perform+.
|
|
176
354
|
# The supplied string should have the form "username:password"
|
|
177
|
-
#
|
|
355
|
+
#
|
|
178
356
|
def userpwd=(value)
|
|
179
357
|
set :userpwd, value
|
|
180
358
|
end
|
|
181
359
|
|
|
182
|
-
#
|
|
360
|
+
#
|
|
183
361
|
# call-seq:
|
|
184
362
|
# easy.proxypwd = string => string
|
|
185
|
-
#
|
|
363
|
+
#
|
|
186
364
|
# Set the username/password string to use for proxy connection during
|
|
187
365
|
# subsequent calls to +perform+. The supplied string should have the
|
|
188
366
|
# form "username:password"
|
|
189
|
-
#
|
|
367
|
+
#
|
|
190
368
|
def proxypwd=(value)
|
|
191
369
|
set :proxyuserpwd, value
|
|
192
370
|
end
|
|
193
371
|
|
|
194
|
-
#
|
|
372
|
+
#
|
|
195
373
|
# call-seq:
|
|
196
374
|
# easy.cookies = "name1=content1; name2=content2;" => string
|
|
197
|
-
#
|
|
198
|
-
# Set
|
|
199
|
-
# be NAME=CONTENTS, where NAME is the cookie name and
|
|
200
|
-
# Set multiple cookies in one string like this:
|
|
201
|
-
#
|
|
375
|
+
#
|
|
376
|
+
# Set the manual Cookie request header for this Curl::Easy instance.
|
|
377
|
+
# The format of the string should be NAME=CONTENTS, where NAME is the cookie name and
|
|
378
|
+
# CONTENTS is what the cookie should contain. Set multiple cookies in one string like this:
|
|
379
|
+
# "name1=content1; name2=content2;".
|
|
380
|
+
#
|
|
381
|
+
# Notes:
|
|
382
|
+
# - This only affects the outgoing Cookie header (libcurl CURLOPT_COOKIE) and does NOT
|
|
383
|
+
# alter the internal libcurl cookie engine (which stores cookies from Set-Cookie).
|
|
384
|
+
# - To change cookies stored in the engine, use {#cookielist} / {#cookielist=} or
|
|
385
|
+
# {#set} with :cookielist.
|
|
386
|
+
# - To clear a previously set manual Cookie header, assign an empty string ('').
|
|
387
|
+
# Assigning +nil+ has no effect in current curb versions.
|
|
388
|
+
#
|
|
202
389
|
def cookies=(value)
|
|
203
390
|
set :cookie, value
|
|
204
391
|
end
|
|
205
392
|
|
|
206
|
-
#
|
|
393
|
+
#
|
|
207
394
|
# call-seq:
|
|
208
395
|
# easy.cookiefile = string => string
|
|
209
|
-
#
|
|
396
|
+
#
|
|
210
397
|
# Set a file that contains cookies to be sent in subsequent requests by this Curl::Easy instance.
|
|
211
|
-
#
|
|
398
|
+
#
|
|
212
399
|
# *Note* that you must set enable_cookies true to enable the cookie
|
|
213
400
|
# engine, or this option will be ignored.
|
|
214
|
-
#
|
|
401
|
+
#
|
|
402
|
+
# Note: assigning +nil+ has no effect; pass a path string to use a cookie file.
|
|
403
|
+
#
|
|
215
404
|
def cookiefile=(value)
|
|
216
405
|
set :cookiefile, value
|
|
217
406
|
end
|
|
218
407
|
|
|
219
|
-
#
|
|
408
|
+
#
|
|
220
409
|
# call-seq:
|
|
221
410
|
# easy.cookiejar = string => string
|
|
222
|
-
#
|
|
223
|
-
# Set a cookiejar file to use for this Curl::Easy instance.
|
|
224
|
-
#
|
|
225
|
-
#
|
|
411
|
+
#
|
|
412
|
+
# Set a cookiejar file to use for this Curl::Easy instance. Cookies from the response
|
|
413
|
+
# will be written into this file.
|
|
414
|
+
#
|
|
226
415
|
# *Note* that you must set enable_cookies true to enable the cookie
|
|
227
416
|
# engine, or this option will be ignored.
|
|
228
|
-
#
|
|
417
|
+
#
|
|
418
|
+
# Note: assigning +nil+ has no effect; pass a path string to persist cookies to a file.
|
|
419
|
+
#
|
|
229
420
|
def cookiejar=(value)
|
|
230
421
|
set :cookiejar, value
|
|
231
422
|
end
|
|
232
423
|
|
|
424
|
+
#
|
|
425
|
+
# call-seq:
|
|
426
|
+
# easy.cookielist = string => string
|
|
427
|
+
#
|
|
428
|
+
# Modify cookies in libcurl's internal cookie engine (CURLOPT_COOKIELIST).
|
|
429
|
+
# Accepts a Set-Cookie style string, one or more lines in Netscape cookie file format,
|
|
430
|
+
# or one of the special commands: "ALL" (clear), "SESS" (remove session cookies),
|
|
431
|
+
# "FLUSH" (write to jar), "RELOAD" (reload from file).
|
|
432
|
+
#
|
|
433
|
+
# Examples:
|
|
434
|
+
# easy.cookielist = "Set-Cookie: session=42; Domain=example.com; Path=/;"
|
|
435
|
+
# easy.cookielist = [
|
|
436
|
+
# ['.example.com', 'TRUE', '/', 'FALSE', 0, 'c1', 'v1'].join("\t"),
|
|
437
|
+
# ['.example.com', 'TRUE', '/', 'FALSE', 0, 'c2', 'v2'].join("\t"),
|
|
438
|
+
# ''
|
|
439
|
+
# ].join("\n")
|
|
440
|
+
# easy.cookielist = 'ALL' # clear all cookies in the engine
|
|
441
|
+
#
|
|
442
|
+
def cookielist=(value)
|
|
443
|
+
set :cookielist, value
|
|
444
|
+
end
|
|
445
|
+
|
|
233
446
|
#
|
|
234
447
|
# call-seq:
|
|
235
448
|
# easy = Curl::Easy.new("url") do|c|
|
|
@@ -300,7 +513,7 @@ module Curl
|
|
|
300
513
|
|
|
301
514
|
#
|
|
302
515
|
# call-seq:
|
|
303
|
-
# Curl::Easy.perform(url) { |easy| ... } =>
|
|
516
|
+
# Curl::Easy.perform(url) { |easy| ... } => #<Curl::Easy...>
|
|
304
517
|
#
|
|
305
518
|
# Convenience method that creates a new Curl::Easy instance with
|
|
306
519
|
# the specified URL and calls the general +perform+ method, before returning
|
|
@@ -318,7 +531,7 @@ module Curl
|
|
|
318
531
|
|
|
319
532
|
#
|
|
320
533
|
# call-seq:
|
|
321
|
-
# Curl::Easy.http_get(url) { |easy| ... } =>
|
|
534
|
+
# Curl::Easy.http_get(url) { |easy| ... } => #<Curl::Easy...>
|
|
322
535
|
#
|
|
323
536
|
# Convenience method that creates a new Curl::Easy instance with
|
|
324
537
|
# the specified URL and calls +http_get+, before returning the new instance.
|
|
@@ -335,7 +548,7 @@ module Curl
|
|
|
335
548
|
|
|
336
549
|
#
|
|
337
550
|
# call-seq:
|
|
338
|
-
# Curl::Easy.http_head(url) { |easy| ... } =>
|
|
551
|
+
# Curl::Easy.http_head(url) { |easy| ... } => #<Curl::Easy...>
|
|
339
552
|
#
|
|
340
553
|
# Convenience method that creates a new Curl::Easy instance with
|
|
341
554
|
# the specified URL and calls +http_head+, before returning the new instance.
|
|
@@ -353,13 +566,36 @@ module Curl
|
|
|
353
566
|
#
|
|
354
567
|
# call-seq:
|
|
355
568
|
# Curl::Easy.http_put(url, data) {|c| ... }
|
|
569
|
+
# Curl::Easy.http_put(url, "some=urlencoded%20form%20data&and=so%20on") => true
|
|
570
|
+
# Curl::Easy.http_put(url, "some=urlencoded%20form%20data", "and=so%20on", ...) => true
|
|
571
|
+
# Curl::Easy.http_put(url, "some=urlencoded%20form%20data", Curl::PostField, "and=so%20on", ...) => true
|
|
572
|
+
# Curl::Easy.http_put(url, Curl::PostField, Curl::PostField ..., Curl::PostField) => true
|
|
356
573
|
#
|
|
357
574
|
# see easy.http_put
|
|
358
575
|
#
|
|
359
|
-
def http_put(
|
|
360
|
-
|
|
576
|
+
def http_put(*args)
|
|
577
|
+
url = args.shift
|
|
578
|
+
c = Curl::Easy.new(url)
|
|
361
579
|
yield c if block_given?
|
|
362
|
-
c.http_put
|
|
580
|
+
c.http_put(*args)
|
|
581
|
+
c
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
#
|
|
585
|
+
# call-seq:
|
|
586
|
+
# Curl::Easy.http_patch(url, data) {|c| ... }
|
|
587
|
+
# Curl::Easy.http_patch(url, "some=urlencoded%20form%20data&and=so%20on") => true
|
|
588
|
+
# Curl::Easy.http_patch(url, "some=urlencoded%20form%20data", "and=so%20on", ...) => true
|
|
589
|
+
# Curl::Easy.http_patch(url, "some=urlencoded%20form%20data", Curl::PostField, "and=so%20on", ...) => true
|
|
590
|
+
# Curl::Easy.http_patch(url, Curl::PostField, Curl::PostField ..., Curl::PostField) => true
|
|
591
|
+
#
|
|
592
|
+
# see easy.http_patch
|
|
593
|
+
#
|
|
594
|
+
def http_patch(*args)
|
|
595
|
+
url = args.shift
|
|
596
|
+
c = Curl::Easy.new(url)
|
|
597
|
+
yield c if block_given?
|
|
598
|
+
c.http_patch(*args)
|
|
363
599
|
c
|
|
364
600
|
end
|
|
365
601
|
|
|
@@ -389,7 +625,7 @@ module Curl
|
|
|
389
625
|
|
|
390
626
|
#
|
|
391
627
|
# call-seq:
|
|
392
|
-
# Curl::Easy.http_delete(url) { |easy| ... } =>
|
|
628
|
+
# Curl::Easy.http_delete(url) { |easy| ... } => #<Curl::Easy...>
|
|
393
629
|
#
|
|
394
630
|
# Convenience method that creates a new Curl::Easy instance with
|
|
395
631
|
# the specified URL and calls +http_delete+, before returning the new instance.
|
|
@@ -403,35 +639,35 @@ module Curl
|
|
|
403
639
|
c.http_delete
|
|
404
640
|
c
|
|
405
641
|
end
|
|
406
|
-
|
|
642
|
+
|
|
407
643
|
# call-seq:
|
|
408
644
|
# Curl::Easy.download(url, filename = url.split(/\?/).first.split(/\//).last) { |curl| ... }
|
|
409
|
-
#
|
|
645
|
+
#
|
|
410
646
|
# 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
|
|
647
|
+
# supplied filename (defaults to the last component of the URL path, which will
|
|
412
648
|
# usually be the filename most simple urls).
|
|
413
|
-
#
|
|
649
|
+
#
|
|
414
650
|
# If a block is supplied, it will be passed the curl instance prior to the
|
|
415
651
|
# perform call.
|
|
416
|
-
#
|
|
652
|
+
#
|
|
417
653
|
# *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
|
|
654
|
+
# download, to account for the automatic routing of data to the specified file: The
|
|
419
655
|
# data string is passed to the handler *before* it is written
|
|
420
|
-
# to the file, allowing the handler to perform mutative operations where
|
|
656
|
+
# to the file, allowing the handler to perform mutative operations where
|
|
421
657
|
# 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
|
|
658
|
+
# returns a size that differs from the data chunk size - in this case, the
|
|
423
659
|
# offending chunk will *not* be written to the file, the file will be closed,
|
|
424
660
|
# and a Curl::Err::AbortedByCallbackError will be raised.
|
|
425
661
|
def download(url, filename = url.split(/\?/).first.split(/\//).last, &blk)
|
|
426
662
|
curl = Curl::Easy.new(url, &blk)
|
|
427
|
-
|
|
663
|
+
|
|
428
664
|
output = if filename.is_a? IO
|
|
429
665
|
filename.binmode if filename.respond_to?(:binmode)
|
|
430
666
|
filename
|
|
431
667
|
else
|
|
432
668
|
File.open(filename, 'wb')
|
|
433
669
|
end
|
|
434
|
-
|
|
670
|
+
|
|
435
671
|
begin
|
|
436
672
|
old_on_body = curl.on_body do |data|
|
|
437
673
|
result = old_on_body ? old_on_body.call(data) : data.length
|
|
@@ -442,7 +678,7 @@ module Curl
|
|
|
442
678
|
ensure
|
|
443
679
|
output.close rescue IOError
|
|
444
680
|
end
|
|
445
|
-
|
|
681
|
+
|
|
446
682
|
return curl
|
|
447
683
|
end
|
|
448
684
|
end
|