curb 1.2.2 → 1.3.2
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/Rakefile +22 -0
- data/ext/curb.c +282 -231
- data/ext/curb.h +3 -3
- data/ext/curb_easy.c +766 -299
- data/ext/curb_easy.h +5 -0
- data/ext/curb_errors.c +5 -5
- data/ext/curb_errors.h +1 -1
- data/ext/curb_macros.h +14 -14
- data/ext/curb_multi.c +612 -142
- data/ext/curb_multi.h +3 -1
- data/ext/curb_postfield.c +48 -21
- data/ext/curb_postfield.h +1 -0
- data/ext/curb_upload.c +32 -9
- data/ext/curb_upload.h +2 -0
- data/ext/extconf.rb +42 -1
- data/lib/curl/easy.rb +154 -13
- data/lib/curl/multi.rb +69 -9
- data/lib/curl.rb +193 -0
- data/tests/helper.rb +222 -36
- data/tests/leak_trace.rb +237 -0
- data/tests/tc_curl_download.rb +6 -2
- data/tests/tc_curl_easy.rb +509 -1
- data/tests/tc_curl_multi.rb +573 -59
- data/tests/tc_curl_native_coverage.rb +145 -0
- data/tests/tc_curl_postfield.rb +176 -0
- data/tests/tc_fiber_scheduler.rb +342 -7
- data/tests/tc_gc_compact.rb +178 -16
- data/tests/tc_test_server_methods.rb +110 -0
- metadata +10 -14
- data/tests/test_basic.rb +0 -29
- data/tests/test_fiber_debug.rb +0 -69
- data/tests/test_fiber_simple.rb +0 -65
- data/tests/test_real_url.rb +0 -65
- data/tests/test_simple_fiber.rb +0 -34
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
|
2
|
+
require 'tmpdir'
|
|
3
|
+
|
|
4
|
+
class TestServerMethodsWaitForServerReady < Test::Unit::TestCase
|
|
5
|
+
include TestServerMethods
|
|
6
|
+
|
|
7
|
+
def server_startup_timeout
|
|
8
|
+
0.05
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def unused_port
|
|
12
|
+
server = TCPServer.new('127.0.0.1', 0)
|
|
13
|
+
port = server.addr[1]
|
|
14
|
+
server.close
|
|
15
|
+
port
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_wait_for_server_ready_returns_false_when_thread_dies
|
|
19
|
+
thread = Thread.new {}
|
|
20
|
+
thread.join
|
|
21
|
+
|
|
22
|
+
started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
23
|
+
assert_equal false, wait_for_server_ready(unused_port, thread: thread)
|
|
24
|
+
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - started
|
|
25
|
+
|
|
26
|
+
assert_operator elapsed, :<, 0.5
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_wait_for_server_ready_times_out_when_server_never_starts
|
|
30
|
+
error = assert_raise(RuntimeError) do
|
|
31
|
+
wait_for_server_ready(unused_port)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
assert_match(/Failed to startup test server/, error.message)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class TestServerMethodsLockHandling < Test::Unit::TestCase
|
|
39
|
+
include TestServerMethods
|
|
40
|
+
|
|
41
|
+
def setup
|
|
42
|
+
@lock_dir = Dir.mktmpdir('curb-server-lock')
|
|
43
|
+
@__port = unused_port
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def teardown
|
|
47
|
+
super
|
|
48
|
+
FileUtils.remove_entry(@lock_dir) if @lock_dir && File.exist?(@lock_dir)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def server_startup_timeout
|
|
52
|
+
0.05
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def locked_file
|
|
56
|
+
File.join(@lock_dir, "server_lock-#{@__port}")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def unused_port
|
|
60
|
+
server = TCPServer.new('127.0.0.1', 0)
|
|
61
|
+
port = server.addr[1]
|
|
62
|
+
server.close
|
|
63
|
+
port
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_clear_stale_server_lock_removes_legacy_lock_when_server_is_down
|
|
67
|
+
File.write(locked_file, 'locked')
|
|
68
|
+
|
|
69
|
+
clear_stale_server_lock(@__port)
|
|
70
|
+
|
|
71
|
+
assert_equal false, File.exist?(locked_file)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_clear_stale_server_lock_removes_dead_pid_lock_when_server_is_down
|
|
75
|
+
File.write(locked_file, "999999\n")
|
|
76
|
+
|
|
77
|
+
clear_stale_server_lock(@__port)
|
|
78
|
+
|
|
79
|
+
assert_equal false, File.exist?(locked_file)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_clear_stale_server_lock_keeps_live_pid_lock_during_startup_window
|
|
83
|
+
write_server_lock(Process.pid)
|
|
84
|
+
|
|
85
|
+
clear_stale_server_lock(@__port)
|
|
86
|
+
|
|
87
|
+
assert_equal true, File.exist?(locked_file)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_clear_stale_server_lock_removes_non_responding_live_pid_lock_after_timeout
|
|
91
|
+
write_server_lock(Process.pid)
|
|
92
|
+
stale_time = Time.now - 1
|
|
93
|
+
File.utime(stale_time, stale_time, locked_file)
|
|
94
|
+
|
|
95
|
+
clear_stale_server_lock(@__port)
|
|
96
|
+
|
|
97
|
+
assert_equal false, File.exist?(locked_file)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def test_stop_test_server_removes_owned_lock_and_shuts_listener_down
|
|
101
|
+
server_setup(@__port)
|
|
102
|
+
assert_equal true, File.exist?(locked_file)
|
|
103
|
+
assert_equal true, server_responding?(@__port)
|
|
104
|
+
|
|
105
|
+
stop_test_server
|
|
106
|
+
|
|
107
|
+
assert_equal false, File.exist?(locked_file)
|
|
108
|
+
assert_equal false, server_responding?(@__port)
|
|
109
|
+
end
|
|
110
|
+
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.
|
|
4
|
+
version: 1.3.2
|
|
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:
|
|
11
|
+
date: 2026-04-23 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
|
|
@@ -62,6 +62,7 @@ files:
|
|
|
62
62
|
- tests/bug_require_last_or_segfault.rb
|
|
63
63
|
- tests/bugtests.rb
|
|
64
64
|
- tests/helper.rb
|
|
65
|
+
- tests/leak_trace.rb
|
|
65
66
|
- tests/mem_check.rb
|
|
66
67
|
- tests/require_last_or_segfault_script.rb
|
|
67
68
|
- tests/signals.rb
|
|
@@ -74,16 +75,13 @@ files:
|
|
|
74
75
|
- tests/tc_curl_easy_setopt.rb
|
|
75
76
|
- tests/tc_curl_maxfilesize.rb
|
|
76
77
|
- tests/tc_curl_multi.rb
|
|
78
|
+
- tests/tc_curl_native_coverage.rb
|
|
77
79
|
- tests/tc_curl_postfield.rb
|
|
78
80
|
- tests/tc_curl_protocols.rb
|
|
79
81
|
- tests/tc_fiber_scheduler.rb
|
|
80
82
|
- tests/tc_ftp_options.rb
|
|
81
83
|
- tests/tc_gc_compact.rb
|
|
82
|
-
- tests/
|
|
83
|
-
- tests/test_fiber_debug.rb
|
|
84
|
-
- tests/test_fiber_simple.rb
|
|
85
|
-
- tests/test_real_url.rb
|
|
86
|
-
- tests/test_simple_fiber.rb
|
|
84
|
+
- tests/tc_test_server_methods.rb
|
|
87
85
|
- tests/timeout.rb
|
|
88
86
|
- tests/timeout_server.rb
|
|
89
87
|
- tests/unittests.rb
|
|
@@ -102,14 +100,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
102
100
|
requirements:
|
|
103
101
|
- - ">="
|
|
104
102
|
- !ruby/object:Gem::Version
|
|
105
|
-
version: '
|
|
103
|
+
version: '2.2'
|
|
106
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
105
|
requirements:
|
|
108
106
|
- - ">="
|
|
109
107
|
- !ruby/object:Gem::Version
|
|
110
108
|
version: '0'
|
|
111
109
|
requirements: []
|
|
112
|
-
rubygems_version:
|
|
110
|
+
rubygems_version: 4.0.6
|
|
113
111
|
specification_version: 4
|
|
114
112
|
summary: Ruby libcurl bindings
|
|
115
113
|
test_files:
|
|
@@ -131,6 +129,7 @@ test_files:
|
|
|
131
129
|
- tests/bug_require_last_or_segfault.rb
|
|
132
130
|
- tests/bugtests.rb
|
|
133
131
|
- tests/helper.rb
|
|
132
|
+
- tests/leak_trace.rb
|
|
134
133
|
- tests/mem_check.rb
|
|
135
134
|
- tests/require_last_or_segfault_script.rb
|
|
136
135
|
- tests/signals.rb
|
|
@@ -143,16 +142,13 @@ test_files:
|
|
|
143
142
|
- tests/tc_curl_easy_setopt.rb
|
|
144
143
|
- tests/tc_curl_maxfilesize.rb
|
|
145
144
|
- tests/tc_curl_multi.rb
|
|
145
|
+
- tests/tc_curl_native_coverage.rb
|
|
146
146
|
- tests/tc_curl_postfield.rb
|
|
147
147
|
- tests/tc_curl_protocols.rb
|
|
148
148
|
- tests/tc_fiber_scheduler.rb
|
|
149
149
|
- tests/tc_ftp_options.rb
|
|
150
150
|
- tests/tc_gc_compact.rb
|
|
151
|
-
- tests/
|
|
152
|
-
- tests/test_fiber_debug.rb
|
|
153
|
-
- tests/test_fiber_simple.rb
|
|
154
|
-
- tests/test_real_url.rb
|
|
155
|
-
- tests/test_simple_fiber.rb
|
|
151
|
+
- tests/tc_test_server_methods.rb
|
|
156
152
|
- tests/timeout.rb
|
|
157
153
|
- tests/timeout_server.rb
|
|
158
154
|
- tests/unittests.rb
|
data/tests/test_basic.rb
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
|
2
|
-
|
|
3
|
-
class TestBasic < Test::Unit::TestCase
|
|
4
|
-
include TestServerMethods
|
|
5
|
-
|
|
6
|
-
def setup
|
|
7
|
-
server_setup
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def test_basic_request
|
|
11
|
-
puts "\n=== Testing basic request ==="
|
|
12
|
-
easy = Curl::Easy.new(TestServlet.url)
|
|
13
|
-
easy.perform
|
|
14
|
-
puts "Response code: #{easy.response_code}"
|
|
15
|
-
puts "Body (first 100 chars): #{easy.body_str[0..100]}"
|
|
16
|
-
assert_equal 200, easy.response_code
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def test_slow_request
|
|
20
|
-
puts "\n=== Testing slow request ==="
|
|
21
|
-
url = TestServlet.url_to("/slow?seconds=0.1")
|
|
22
|
-
puts "URL: #{url}"
|
|
23
|
-
easy = Curl::Easy.new(url)
|
|
24
|
-
easy.perform
|
|
25
|
-
puts "Response code: #{easy.response_code}"
|
|
26
|
-
puts "Body: #{easy.body_str}"
|
|
27
|
-
assert_equal 200, easy.response_code
|
|
28
|
-
end
|
|
29
|
-
end
|
data/tests/test_fiber_debug.rb
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
|
2
|
-
require 'async'
|
|
3
|
-
|
|
4
|
-
class TestFiberDebug < Test::Unit::TestCase
|
|
5
|
-
include TestServerMethods
|
|
6
|
-
|
|
7
|
-
def setup
|
|
8
|
-
server_setup
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def test_simple_fiber_request
|
|
12
|
-
puts "\n=== Starting simple fiber request test ==="
|
|
13
|
-
|
|
14
|
-
run_async do |task|
|
|
15
|
-
puts "Inside Async block"
|
|
16
|
-
puts "Fiber scheduler available: #{Curl::Multi.fiber_scheduler_available?}"
|
|
17
|
-
|
|
18
|
-
multi = Curl::Multi.new
|
|
19
|
-
easy = Curl::Easy.new(TestServlet.url)
|
|
20
|
-
easy.on_complete { |curl| puts "Request completed: #{curl.response_code}" }
|
|
21
|
-
|
|
22
|
-
multi.add(easy)
|
|
23
|
-
puts "Added easy handle to multi"
|
|
24
|
-
|
|
25
|
-
# Perform without block first
|
|
26
|
-
puts "Calling perform..."
|
|
27
|
-
multi.perform
|
|
28
|
-
puts "Perform completed"
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
puts "Test completed"
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def test_fiber_with_block
|
|
35
|
-
puts "\n=== Starting fiber with block test ==="
|
|
36
|
-
|
|
37
|
-
run_async do |task|
|
|
38
|
-
puts "Inside Async block"
|
|
39
|
-
|
|
40
|
-
multi = Curl::Multi.new
|
|
41
|
-
easy = Curl::Easy.new(TestServlet.url_to("/slow?seconds=0.1"))
|
|
42
|
-
easy.on_complete { |curl| puts "Request completed: #{curl.response_code}" }
|
|
43
|
-
|
|
44
|
-
multi.add(easy)
|
|
45
|
-
|
|
46
|
-
block_calls = 0
|
|
47
|
-
multi.perform do
|
|
48
|
-
block_calls += 1
|
|
49
|
-
puts "Block called: #{block_calls}"
|
|
50
|
-
if block_calls < 5 # Limit iterations to prevent infinite loop
|
|
51
|
-
Async::Task.yield
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
puts "Perform completed, block called #{block_calls} times"
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
puts "Test completed"
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
private
|
|
62
|
-
def run_async(&block)
|
|
63
|
-
if defined?(Async) && Async.respond_to?(:run)
|
|
64
|
-
Async.run(&block)
|
|
65
|
-
else
|
|
66
|
-
Async(&block)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
data/tests/test_fiber_simple.rb
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
|
2
|
-
require 'async'
|
|
3
|
-
|
|
4
|
-
class TestFiberSimple < Test::Unit::TestCase
|
|
5
|
-
include TestServerMethods
|
|
6
|
-
|
|
7
|
-
def setup
|
|
8
|
-
server_setup
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def test_simple_concurrent
|
|
12
|
-
puts "\n=== Testing simple concurrent requests ==="
|
|
13
|
-
|
|
14
|
-
results = []
|
|
15
|
-
|
|
16
|
-
if Async.respond_to?(:run)
|
|
17
|
-
Async.run do |task|
|
|
18
|
-
puts "Fiber scheduler available: #{Curl::Multi.fiber_scheduler_available?}"
|
|
19
|
-
|
|
20
|
-
multi = Curl::Multi.new
|
|
21
|
-
|
|
22
|
-
# Add 3 requests
|
|
23
|
-
3.times do |i|
|
|
24
|
-
easy = Curl::Easy.new(TestServlet.url_to("/slow?seconds=0.2&id=#{i}"))
|
|
25
|
-
easy.on_complete { |curl|
|
|
26
|
-
results << { id: i, code: curl.response_code }
|
|
27
|
-
puts "Request #{i} completed"
|
|
28
|
-
}
|
|
29
|
-
multi.add(easy)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
puts "Starting perform..."
|
|
33
|
-
start_time = Time.now
|
|
34
|
-
multi.perform # No block
|
|
35
|
-
elapsed = Time.now - start_time
|
|
36
|
-
puts "Perform completed in #{elapsed.round(2)}s"
|
|
37
|
-
end
|
|
38
|
-
else
|
|
39
|
-
Async do |task|
|
|
40
|
-
puts "Fiber scheduler available: #{Curl::Multi.fiber_scheduler_available?}"
|
|
41
|
-
|
|
42
|
-
multi = Curl::Multi.new
|
|
43
|
-
|
|
44
|
-
# Add 3 requests
|
|
45
|
-
3.times do |i|
|
|
46
|
-
easy = Curl::Easy.new(TestServlet.url_to("/slow?seconds=0.2&id=#{i}"))
|
|
47
|
-
easy.on_complete { |curl|
|
|
48
|
-
results << { id: i, code: curl.response_code }
|
|
49
|
-
puts "Request #{i} completed"
|
|
50
|
-
}
|
|
51
|
-
multi.add(easy)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
puts "Starting perform..."
|
|
55
|
-
start_time = Time.now
|
|
56
|
-
multi.perform # No block
|
|
57
|
-
elapsed = Time.now - start_time
|
|
58
|
-
puts "Perform completed in #{elapsed.round(2)}s"
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
assert_equal 3, results.size
|
|
63
|
-
results.each { |r| assert_equal 200, r[:code] }
|
|
64
|
-
end
|
|
65
|
-
end
|
data/tests/test_real_url.rb
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), '../lib/curb'))
|
|
2
|
-
require 'async'
|
|
3
|
-
|
|
4
|
-
puts "Testing fiber scheduler with real URLs..."
|
|
5
|
-
|
|
6
|
-
# Test without fiber scheduler
|
|
7
|
-
puts "\n1. Without fiber scheduler:"
|
|
8
|
-
start = Time.now
|
|
9
|
-
multi = Curl::Multi.new
|
|
10
|
-
|
|
11
|
-
easies = []
|
|
12
|
-
3.times do |i|
|
|
13
|
-
easy = Curl::Easy.new("https://httpbin.org/delay/1")
|
|
14
|
-
easy.on_complete { |curl| puts "Request #{i} completed: #{curl.response_code}" }
|
|
15
|
-
multi.add(easy)
|
|
16
|
-
easies << easy
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
multi.perform
|
|
20
|
-
elapsed = Time.now - start
|
|
21
|
-
puts "Total time: #{elapsed.round(2)}s"
|
|
22
|
-
|
|
23
|
-
# Test with fiber scheduler
|
|
24
|
-
puts "\n2. With fiber scheduler:"
|
|
25
|
-
if Async.respond_to?(:run)
|
|
26
|
-
Async.run do
|
|
27
|
-
puts "Fiber scheduler available: #{Curl::Multi.fiber_scheduler_available?}"
|
|
28
|
-
|
|
29
|
-
start = Time.now
|
|
30
|
-
multi = Curl::Multi.new
|
|
31
|
-
|
|
32
|
-
easies = []
|
|
33
|
-
3.times do |i|
|
|
34
|
-
easy = Curl::Easy.new("https://httpbin.org/delay/1")
|
|
35
|
-
easy.on_complete { |curl| puts "Request #{i} completed: #{curl.response_code}" }
|
|
36
|
-
multi.add(easy)
|
|
37
|
-
easies << easy
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
multi.perform
|
|
41
|
-
elapsed = Time.now - start
|
|
42
|
-
puts "Total time: #{elapsed.round(2)}s"
|
|
43
|
-
end
|
|
44
|
-
else
|
|
45
|
-
Async do
|
|
46
|
-
puts "Fiber scheduler available: #{Curl::Multi.fiber_scheduler_available?}"
|
|
47
|
-
|
|
48
|
-
start = Time.now
|
|
49
|
-
multi = Curl::Multi.new
|
|
50
|
-
|
|
51
|
-
easies = []
|
|
52
|
-
3.times do |i|
|
|
53
|
-
easy = Curl::Easy.new("https://httpbin.org/delay/1")
|
|
54
|
-
easy.on_complete { |curl| puts "Request #{i} completed: #{curl.response_code}" }
|
|
55
|
-
multi.add(easy)
|
|
56
|
-
easies << easy
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
multi.perform
|
|
60
|
-
elapsed = Time.now - start
|
|
61
|
-
puts "Total time: #{elapsed.round(2)}s"
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
puts "\nDone!"
|
data/tests/test_simple_fiber.rb
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), '../lib/curb'))
|
|
2
|
-
require 'async'
|
|
3
|
-
|
|
4
|
-
puts "Testing simple fiber scheduler..."
|
|
5
|
-
|
|
6
|
-
if Async.respond_to?(:run)
|
|
7
|
-
Async.run do
|
|
8
|
-
puts "Fiber scheduler available: #{Curl::Multi.fiber_scheduler_available?}"
|
|
9
|
-
|
|
10
|
-
multi = Curl::Multi.new
|
|
11
|
-
easy = Curl::Easy.new("https://httpbin.org/delay/1")
|
|
12
|
-
easy.on_complete { |curl| puts "Request completed: #{curl.response_code}" }
|
|
13
|
-
|
|
14
|
-
multi.add(easy)
|
|
15
|
-
puts "Starting perform..."
|
|
16
|
-
multi.perform
|
|
17
|
-
puts "Perform completed"
|
|
18
|
-
end
|
|
19
|
-
else
|
|
20
|
-
Async do
|
|
21
|
-
puts "Fiber scheduler available: #{Curl::Multi.fiber_scheduler_available?}"
|
|
22
|
-
|
|
23
|
-
multi = Curl::Multi.new
|
|
24
|
-
easy = Curl::Easy.new("https://httpbin.org/delay/1")
|
|
25
|
-
easy.on_complete { |curl| puts "Request completed: #{curl.response_code}" }
|
|
26
|
-
|
|
27
|
-
multi.add(easy)
|
|
28
|
-
puts "Starting perform..."
|
|
29
|
-
multi.perform
|
|
30
|
-
puts "Perform completed"
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
puts "Done!"
|