curb 1.0.0 → 1.0.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 +4 -4
- data/README.markdown +42 -6
- data/Rakefile +9 -7
- data/ext/curb.c +9 -1
- data/ext/curb.h +3 -3
- data/ext/curb_easy.c +55 -41
- data/ext/curb_macros.h +12 -0
- data/ext/curb_multi.c +50 -24
- data/ext/curb_postfield.c +9 -7
- data/ext/curb_upload.c +1 -0
- data/ext/extconf.rb +2 -0
- data/lib/curl/easy.rb +5 -5
- data/lib/curl/multi.rb +8 -1
- data/lib/curl.rb +11 -3
- data/tests/bug_crash_on_debug.rb +14 -28
- data/tests/bug_crash_on_progress.rb +7 -31
- data/tests/bug_curb_easy_blocks_ruby_threads.rb +8 -13
- 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_issue277.rb +32 -0
- data/tests/bug_multi_segfault.rb +1 -0
- data/tests/bug_raise_on_callback.rb +29 -0
- data/tests/helper.rb +26 -0
- data/tests/tc_curl_easy.rb +12 -4
- data/tests/tc_curl_multi.rb +47 -7
- metadata +12 -6
data/ext/curb_multi.c
CHANGED
@@ -43,8 +43,25 @@ static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy);
|
|
43
43
|
static void rb_curl_multi_read_info(VALUE self, CURLM *mptr);
|
44
44
|
static void rb_curl_multi_run(VALUE self, CURLM *multi_handle, int *still_running);
|
45
45
|
|
46
|
-
static VALUE callback_exception(VALUE
|
47
|
-
|
46
|
+
static VALUE callback_exception(VALUE did_raise, VALUE exception) {
|
47
|
+
// TODO: we could have an option to enable exception reporting
|
48
|
+
/* VALUE ret = rb_funcall(exception, rb_intern("message"), 0);
|
49
|
+
VALUE trace = rb_funcall(exception, rb_intern("backtrace"), 0);
|
50
|
+
if (RB_TYPE_P(trace, T_ARRAY) && RARRAY_LEN(trace) > 0) {
|
51
|
+
printf("we got an exception: %s:%d\n", StringValueCStr(ret), RARRAY_LEN(trace));
|
52
|
+
VALUE sep = rb_str_new_cstr("\n");
|
53
|
+
VALUE trace_lines = rb_ary_join(trace, sep);
|
54
|
+
if (RB_TYPE_P(trace_lines, T_STRING)) {
|
55
|
+
printf("%s\n", StringValueCStr(trace_lines));
|
56
|
+
} else {
|
57
|
+
printf("trace is not a string??\n");
|
58
|
+
}
|
59
|
+
} else {
|
60
|
+
printf("we got an exception: %s\nno stack available\n", StringValueCStr(ret));
|
61
|
+
}
|
62
|
+
*/
|
63
|
+
rb_hash_aset(did_raise, rb_easy_hkey("error"), exception);
|
64
|
+
return exception;
|
48
65
|
}
|
49
66
|
|
50
67
|
void curl_multi_free(ruby_curl_multi *rbcm) {
|
@@ -64,7 +81,7 @@ static void ruby_curl_multi_init(ruby_curl_multi *rbcm) {
|
|
64
81
|
|
65
82
|
/*
|
66
83
|
* call-seq:
|
67
|
-
* Curl::Multi.new =>
|
84
|
+
* Curl::Multi.new => #<Curl::Easy...>
|
68
85
|
*
|
69
86
|
* Create a new Curl::Multi instance
|
70
87
|
*/
|
@@ -132,7 +149,7 @@ VALUE ruby_curl_multi_get_autoclose(VALUE klass) {
|
|
132
149
|
|
133
150
|
/*
|
134
151
|
* call-seq:
|
135
|
-
* multi.requests => [
|
152
|
+
* multi.requests => [#<Curl::Easy...>, ...]
|
136
153
|
*
|
137
154
|
* Returns an array containing all the active requests on this Curl::Multi object.
|
138
155
|
*/
|
@@ -274,7 +291,7 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
|
|
274
291
|
long response_code = -1;
|
275
292
|
VALUE easy;
|
276
293
|
ruby_curl_easy *rbce = NULL;
|
277
|
-
VALUE callargs
|
294
|
+
VALUE callargs;
|
278
295
|
|
279
296
|
CURLcode ecode = curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, (char**)&easy);
|
280
297
|
|
@@ -295,55 +312,62 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
|
|
295
312
|
raise_curl_easy_error_exception(ecode);
|
296
313
|
}
|
297
314
|
|
315
|
+
VALUE did_raise = rb_hash_new();
|
316
|
+
|
298
317
|
if (!rb_easy_nil("complete_proc")) {
|
299
318
|
callargs = rb_ary_new3(2, rb_easy_get("complete_proc"), easy);
|
300
319
|
rbce->callback_active = 1;
|
301
|
-
|
320
|
+
rb_rescue(call_status_handler1, callargs, callback_exception, did_raise);
|
302
321
|
rbce->callback_active = 0;
|
303
|
-
|
322
|
+
CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
|
304
323
|
}
|
305
324
|
|
325
|
+
#ifdef HAVE_CURLINFO_RESPONSE_CODE
|
306
326
|
curl_easy_getinfo(rbce->curl, CURLINFO_RESPONSE_CODE, &response_code);
|
327
|
+
#else
|
328
|
+
// old libcurl
|
329
|
+
curl_easy_getinfo(rbce->curl, CURLINFO_HTTP_CODE, &response_code);
|
330
|
+
#endif
|
331
|
+
long redirect_count;
|
332
|
+
curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_COUNT, &redirect_count);
|
307
333
|
|
308
334
|
if (result != 0) {
|
309
335
|
if (!rb_easy_nil("failure_proc")) {
|
310
336
|
callargs = rb_ary_new3(3, rb_easy_get("failure_proc"), easy, rb_curl_easy_error(result));
|
311
337
|
rbce->callback_active = 1;
|
312
|
-
|
338
|
+
rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
|
313
339
|
rbce->callback_active = 0;
|
314
|
-
|
340
|
+
CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
|
315
341
|
}
|
316
|
-
}
|
317
|
-
else if (!rb_easy_nil("success_proc") &&
|
342
|
+
} else if (!rb_easy_nil("success_proc") &&
|
318
343
|
((response_code >= 200 && response_code < 300) || response_code == 0)) {
|
319
344
|
/* NOTE: we allow response_code == 0, in the case of non http requests e.g. reading from disk */
|
320
345
|
callargs = rb_ary_new3(2, rb_easy_get("success_proc"), easy);
|
321
346
|
rbce->callback_active = 1;
|
322
|
-
|
347
|
+
rb_rescue(call_status_handler1, callargs, callback_exception, did_raise);
|
323
348
|
rbce->callback_active = 0;
|
324
|
-
|
325
|
-
|
326
|
-
else if (!rb_easy_nil("redirect_proc") &&
|
327
|
-
(response_code >= 300 && response_code < 400)) {
|
349
|
+
CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
|
350
|
+
|
351
|
+
} else if (!rb_easy_nil("redirect_proc") && ((response_code >= 300 && response_code < 400) || redirect_count > 0) ) {
|
328
352
|
rbce->callback_active = 1;
|
329
353
|
callargs = rb_ary_new3(3, rb_easy_get("redirect_proc"), easy, rb_curl_easy_error(result));
|
330
354
|
rbce->callback_active = 0;
|
331
|
-
|
332
|
-
|
333
|
-
else if (!rb_easy_nil("missing_proc") &&
|
355
|
+
rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
|
356
|
+
CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
|
357
|
+
} else if (!rb_easy_nil("missing_proc") &&
|
334
358
|
(response_code >= 400 && response_code < 500)) {
|
335
359
|
rbce->callback_active = 1;
|
336
360
|
callargs = rb_ary_new3(3, rb_easy_get("missing_proc"), easy, rb_curl_easy_error(result));
|
337
361
|
rbce->callback_active = 0;
|
338
|
-
|
339
|
-
|
340
|
-
else if (!rb_easy_nil("failure_proc") &&
|
362
|
+
rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
|
363
|
+
CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
|
364
|
+
} else if (!rb_easy_nil("failure_proc") &&
|
341
365
|
(response_code >= 500 && response_code <= 999)) {
|
342
366
|
callargs = rb_ary_new3(3, rb_easy_get("failure_proc"), easy, rb_curl_easy_error(result));
|
343
367
|
rbce->callback_active = 1;
|
344
|
-
|
368
|
+
rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
|
345
369
|
rbce->callback_active = 0;
|
346
|
-
|
370
|
+
CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
|
347
371
|
}
|
348
372
|
|
349
373
|
}
|
@@ -627,6 +651,8 @@ void init_curb_multi() {
|
|
627
651
|
idCall = rb_intern("call");
|
628
652
|
cCurlMulti = rb_define_class_under(mCurl, "Multi", rb_cObject);
|
629
653
|
|
654
|
+
rb_undef_alloc_func(cCurlMulti);
|
655
|
+
|
630
656
|
/* Class methods */
|
631
657
|
rb_define_singleton_method(cCurlMulti, "new", ruby_curl_multi_new, 0);
|
632
658
|
rb_define_singleton_method(cCurlMulti, "default_timeout=", ruby_curl_multi_set_default_timeout, 1);
|
data/ext/curb_postfield.c
CHANGED
@@ -195,9 +195,9 @@ void curl_postfield_free(ruby_curl_postfield *rbcpf) {
|
|
195
195
|
|
196
196
|
/*
|
197
197
|
* call-seq:
|
198
|
-
* Curl::PostField.content(name, content) =>
|
199
|
-
* Curl::PostField.content(name, content, content_type = nil) =>
|
200
|
-
* Curl::PostField.content(name, content_type = nil) { |field| ... } =>
|
198
|
+
* Curl::PostField.content(name, content) => #<Curl::PostField...>
|
199
|
+
* Curl::PostField.content(name, content, content_type = nil) => #<Curl::PostField...>
|
200
|
+
* Curl::PostField.content(name, content_type = nil) { |field| ... } => #<Curl::PostField...>
|
201
201
|
*
|
202
202
|
* Create a new Curl::PostField, supplying the field name, content,
|
203
203
|
* and, optionally, Content-type (curl will attempt to determine this if
|
@@ -241,9 +241,9 @@ static VALUE ruby_curl_postfield_new_content(int argc, VALUE *argv, VALUE klass)
|
|
241
241
|
|
242
242
|
/*
|
243
243
|
* call-seq:
|
244
|
-
* Curl::PostField.file(name, local_file_name) =>
|
245
|
-
* Curl::PostField.file(name, local_file_name, remote_file_name = local_file_name) =>
|
246
|
-
* Curl::PostField.file(name, remote_file_name) { |field| ... } =>
|
244
|
+
* Curl::PostField.file(name, local_file_name) => #<Curl::PostField...>
|
245
|
+
* Curl::PostField.file(name, local_file_name, remote_file_name = local_file_name) => #<Curl::PostField...>
|
246
|
+
* Curl::PostField.file(name, remote_file_name) { |field| ... } => #<Curl::PostField...>
|
247
247
|
*
|
248
248
|
* Create a new Curl::PostField for a file upload field, supplying the local filename
|
249
249
|
* to read from, and optionally the remote filename (defaults to the local name).
|
@@ -399,7 +399,7 @@ static VALUE ruby_curl_postfield_remote_file_get(VALUE self) {
|
|
399
399
|
|
400
400
|
/*
|
401
401
|
* call-seq:
|
402
|
-
* field.set_content_proc { |field| ... } =>
|
402
|
+
* field.set_content_proc { |field| ... } => <old proc>
|
403
403
|
*
|
404
404
|
* Set a content proc for this field. This proc will be called during the
|
405
405
|
* perform to supply the content for this field, overriding any setting
|
@@ -498,6 +498,8 @@ void init_curb_postfield() {
|
|
498
498
|
|
499
499
|
cCurlPostField = rb_define_class_under(mCurl, "PostField", rb_cObject);
|
500
500
|
|
501
|
+
rb_undef_alloc_func(cCurlPostField);
|
502
|
+
|
501
503
|
/* Class methods */
|
502
504
|
rb_define_singleton_method(cCurlPostField, "content", ruby_curl_postfield_new_content, -1);
|
503
505
|
rb_define_singleton_method(cCurlPostField, "file", ruby_curl_postfield_new_file, -1);
|
data/ext/curb_upload.c
CHANGED
@@ -72,6 +72,7 @@ VALUE ruby_curl_upload_offset_get(VALUE self) {
|
|
72
72
|
/* =================== INIT LIB =====================*/
|
73
73
|
void init_curb_upload() {
|
74
74
|
cCurlUpload = rb_define_class_under(mCurl, "Upload", rb_cObject);
|
75
|
+
rb_undef_alloc_func(cCurlUpload);
|
75
76
|
rb_define_singleton_method(cCurlUpload, "new", ruby_curl_upload_new, 0);
|
76
77
|
rb_define_method(cCurlUpload, "stream=", ruby_curl_upload_stream_set, 1);
|
77
78
|
rb_define_method(cCurlUpload, "stream", ruby_curl_upload_stream_get, 0);
|
data/ext/extconf.rb
CHANGED
data/lib/curl/easy.rb
CHANGED
@@ -21,7 +21,7 @@ module Curl
|
|
21
21
|
#
|
22
22
|
def status
|
23
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{
|
24
|
+
statuses = self.header_str.to_s.scan(/HTTP\/\d(\.\d)?\s(\d+\s.*)\r\n/).map {|match| match[1] }
|
25
25
|
statuses.last.strip if statuses.length > 0
|
26
26
|
end
|
27
27
|
|
@@ -321,7 +321,7 @@ module Curl
|
|
321
321
|
|
322
322
|
#
|
323
323
|
# call-seq:
|
324
|
-
# Curl::Easy.perform(url) { |easy| ... } =>
|
324
|
+
# Curl::Easy.perform(url) { |easy| ... } => #<Curl::Easy...>
|
325
325
|
#
|
326
326
|
# Convenience method that creates a new Curl::Easy instance with
|
327
327
|
# the specified URL and calls the general +perform+ method, before returning
|
@@ -339,7 +339,7 @@ module Curl
|
|
339
339
|
|
340
340
|
#
|
341
341
|
# call-seq:
|
342
|
-
# Curl::Easy.http_get(url) { |easy| ... } =>
|
342
|
+
# Curl::Easy.http_get(url) { |easy| ... } => #<Curl::Easy...>
|
343
343
|
#
|
344
344
|
# Convenience method that creates a new Curl::Easy instance with
|
345
345
|
# the specified URL and calls +http_get+, before returning the new instance.
|
@@ -356,7 +356,7 @@ module Curl
|
|
356
356
|
|
357
357
|
#
|
358
358
|
# call-seq:
|
359
|
-
# Curl::Easy.http_head(url) { |easy| ... } =>
|
359
|
+
# Curl::Easy.http_head(url) { |easy| ... } => #<Curl::Easy...>
|
360
360
|
#
|
361
361
|
# Convenience method that creates a new Curl::Easy instance with
|
362
362
|
# the specified URL and calls +http_head+, before returning the new instance.
|
@@ -410,7 +410,7 @@ module Curl
|
|
410
410
|
|
411
411
|
#
|
412
412
|
# call-seq:
|
413
|
-
# Curl::Easy.http_delete(url) { |easy| ... } =>
|
413
|
+
# Curl::Easy.http_delete(url) { |easy| ... } => #<Curl::Easy...>
|
414
414
|
#
|
415
415
|
# Convenience method that creates a new Curl::Easy instance with
|
416
416
|
# the specified URL and calls +http_delete+, before returning the new instance.
|
data/lib/curl/multi.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Curl
|
3
3
|
class Multi
|
4
|
+
class DownloadError < RuntimeError
|
5
|
+
attr_accessor :errors
|
6
|
+
end
|
4
7
|
class << self
|
5
8
|
# call-seq:
|
6
9
|
# Curl::Multi.get(['url1','url2','url3','url4','url5'], :follow_location => true) do|easy|
|
@@ -241,7 +244,11 @@ module Curl
|
|
241
244
|
errors << e
|
242
245
|
end
|
243
246
|
}
|
244
|
-
|
247
|
+
if errors.any?
|
248
|
+
de = Curl::Multi::DownloadError.new
|
249
|
+
de.errors = errors
|
250
|
+
raise de
|
251
|
+
end
|
245
252
|
end
|
246
253
|
end
|
247
254
|
|
data/lib/curl.rb
CHANGED
@@ -9,12 +9,20 @@ require 'cgi'
|
|
9
9
|
module Curl
|
10
10
|
|
11
11
|
def self.http(verb, url, post_body=nil, put_data=nil, &block)
|
12
|
-
|
13
|
-
|
12
|
+
if Thread.current[:curb_curl_yielding]
|
13
|
+
handle = Curl::Easy.new # we can't reuse this
|
14
|
+
else
|
15
|
+
handle = Thread.current[:curb_curl] ||= Curl::Easy.new
|
16
|
+
handle.reset
|
17
|
+
end
|
14
18
|
handle.url = url
|
15
19
|
handle.post_body = post_body if post_body
|
16
20
|
handle.put_data = put_data if put_data
|
17
|
-
|
21
|
+
if block_given?
|
22
|
+
Thread.current[:curb_curl_yielding] = true
|
23
|
+
yield handle
|
24
|
+
Thread.current[:curb_curl_yielding] = false
|
25
|
+
end
|
18
26
|
handle.http(verb)
|
19
27
|
handle
|
20
28
|
end
|
data/tests/bug_crash_on_debug.rb
CHANGED
@@ -1,37 +1,23 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
2
|
|
3
|
-
require 'webrick'
|
4
|
-
class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
|
5
|
-
class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
|
6
|
-
|
7
|
-
require 'curl'
|
8
|
-
|
9
3
|
class BugCrashOnDebug < Test::Unit::TestCase
|
4
|
+
include BugTestServerSetupTeardown
|
10
5
|
|
11
6
|
def test_on_debug
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
c.on_debug do|x|
|
24
|
-
puts x.inspect
|
25
|
-
raise "error" # this will get swallowed
|
7
|
+
c = Curl::Easy.new("http://127.0.0.1:#{@port}/test")
|
8
|
+
did_raise = false
|
9
|
+
did_call = false
|
10
|
+
begin
|
11
|
+
c.on_success do|x|
|
12
|
+
did_call = true
|
13
|
+
raise "error" # this will get swallowed
|
14
|
+
end
|
15
|
+
c.perform
|
16
|
+
rescue => e
|
17
|
+
did_raise = true
|
26
18
|
end
|
27
|
-
|
28
|
-
|
29
|
-
ensure
|
30
|
-
puts 'd'
|
31
|
-
server.shutdown
|
32
|
-
puts 'e'
|
33
|
-
puts thread.exit
|
34
|
-
puts 'f'
|
19
|
+
assert did_raise
|
20
|
+
assert did_call
|
35
21
|
end
|
36
22
|
|
37
23
|
end
|
@@ -1,22 +1,10 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
-
require 'webrick'
|
3
|
-
class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
|
4
|
-
class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
|
5
2
|
|
6
3
|
class BugCrashOnDebug < Test::Unit::TestCase
|
7
|
-
|
8
|
-
def test_on_progress_raise
|
9
|
-
server = WEBrick::HTTPServer.new( :Port => 9999 )
|
10
|
-
server.mount_proc("/test") do|req,res|
|
11
|
-
res.body = "hi"
|
12
|
-
res['Content-Type'] = "text/html"
|
13
|
-
end
|
4
|
+
include BugTestServerSetupTeardown
|
14
5
|
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
c = Curl::Easy.new('http://127.0.0.1:9999/test')
|
6
|
+
def test_on_progress_raise
|
7
|
+
c = Curl::Easy.new("http://127.0.0.1:#{@port}/test")
|
20
8
|
c.on_progress do|x|
|
21
9
|
raise "error"
|
22
10
|
end
|
@@ -27,21 +15,9 @@ class BugCrashOnDebug < Test::Unit::TestCase
|
|
27
15
|
rescue => e
|
28
16
|
assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
|
29
17
|
c.close
|
30
|
-
ensure
|
31
|
-
server.shutdown
|
32
18
|
end
|
33
19
|
|
34
20
|
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
21
|
# see: https://github.com/taf2/curb/issues/192,
|
46
22
|
# to pass:
|
47
23
|
#
|
@@ -54,20 +30,20 @@ class BugCrashOnDebug < Test::Unit::TestCase
|
|
54
30
|
#
|
55
31
|
# notice no return keyword
|
56
32
|
#
|
57
|
-
c = Curl::Easy.new(
|
33
|
+
c = Curl::Easy.new("http://127.0.0.1:#{@port}/test")
|
34
|
+
did_progress = false
|
58
35
|
c.on_progress do|x|
|
59
|
-
|
36
|
+
did_progress = true
|
60
37
|
return false
|
61
38
|
end
|
62
39
|
c.perform
|
40
|
+
assert did_progress
|
63
41
|
|
64
42
|
assert false, "should not reach this point"
|
65
43
|
|
66
44
|
rescue => e
|
67
45
|
assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
|
68
46
|
c.close
|
69
|
-
ensure
|
70
|
-
server.shutdown
|
71
47
|
end
|
72
48
|
|
73
49
|
end
|
@@ -1,21 +1,19 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
-
require 'webrick'
|
3
|
-
class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
|
4
|
-
class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
|
5
2
|
|
6
3
|
class BugTestInstancePostDiffersFromClassPost < Test::Unit::TestCase
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
include BugTestServerSetupTeardown
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@port = 9999
|
8
|
+
@response_proc = lambda do|res|
|
10
9
|
sleep 0.5
|
11
10
|
res.body = "hi"
|
12
11
|
res['Content-Type'] = "text/html"
|
13
12
|
end
|
13
|
+
super
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
srv.start
|
17
|
-
end
|
18
|
-
|
16
|
+
def test_bug
|
19
17
|
threads = []
|
20
18
|
timer = Time.now
|
21
19
|
|
@@ -45,8 +43,5 @@ class BugTestInstancePostDiffersFromClassPost < Test::Unit::TestCase
|
|
45
43
|
puts "requested in #{single_time}"
|
46
44
|
|
47
45
|
assert single_time > multi_time
|
48
|
-
|
49
|
-
server.shutdown
|
50
|
-
thread.join
|
51
46
|
end
|
52
47
|
end
|
@@ -22,26 +22,15 @@ end
|
|
22
22
|
Any insight you care to share would be helpful. Thanks.
|
23
23
|
=end
|
24
24
|
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
25
|
-
require 'webrick'
|
26
|
-
class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
|
27
|
-
class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
|
28
25
|
|
29
26
|
class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
|
30
|
-
|
31
|
-
server = WEBrick::HTTPServer.new( :Port => 9999 )
|
32
|
-
server.mount_proc("/test") do|req,res|
|
33
|
-
assert_equal '15', req['Content-Length']
|
34
|
-
res.body = "hi"
|
35
|
-
res['Content-Type'] = "text/html"
|
36
|
-
end
|
27
|
+
include BugTestServerSetupTeardown
|
37
28
|
|
38
|
-
|
39
|
-
srv.start
|
40
|
-
end
|
29
|
+
def test_bug_workaround
|
41
30
|
params = {:cat => "hat", :foo => "bar"}
|
42
31
|
|
43
32
|
post_body = params.map{|f,k| "#{Curl::Easy.new.escape(f)}=#{Curl::Easy.new.escape(k)}"}.join('&')
|
44
|
-
c = Curl::Easy.http_post("http://127.0.0.1
|
33
|
+
c = Curl::Easy.http_post("http://127.0.0.1:#{@port}/test",post_body) do |curl|
|
45
34
|
curl.headers["User-Agent"] = "Curl/Ruby"
|
46
35
|
curl.headers["X-Tender-Auth"] = "A Token"
|
47
36
|
curl.headers["Accept"] = "application/vnd.tender-v1+json"
|
@@ -50,23 +39,12 @@ class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
|
|
50
39
|
curl.enable_cookies = true
|
51
40
|
end
|
52
41
|
|
53
|
-
server.shutdown
|
54
|
-
thread.join
|
55
42
|
end
|
56
|
-
def test_bug
|
57
|
-
server = WEBrick::HTTPServer.new( :Port => 9999 )
|
58
|
-
server.mount_proc("/test") do|req,res|
|
59
|
-
assert_equal '15', req['Content-Length']
|
60
|
-
res.body = "hi"
|
61
|
-
res['Content-Type'] = "text/html"
|
62
|
-
end
|
63
43
|
|
64
|
-
|
65
|
-
srv.start
|
66
|
-
end
|
44
|
+
def test_bug
|
67
45
|
params = {:cat => "hat", :foo => "bar"}
|
68
46
|
|
69
|
-
c = Curl::Easy.http_post("http://127.0.0.1
|
47
|
+
c = Curl::Easy.http_post("http://127.0.0.1:#{@port}/test") do |curl|
|
70
48
|
curl.headers["User-Agent"] = "Curl/Ruby"
|
71
49
|
curl.headers["X-Tender-Auth"] = "A Token"
|
72
50
|
curl.headers["Accept"] = "application/vnd.tender-v1+json"
|
@@ -76,8 +54,6 @@ class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
|
|
76
54
|
curl.follow_location = true
|
77
55
|
curl.enable_cookies = true
|
78
56
|
end
|
79
|
-
|
80
|
-
server.shutdown
|
81
|
-
thread.join
|
82
57
|
end
|
58
|
+
|
83
59
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
+
|
3
|
+
class BugFollowRedirect288 < Test::Unit::TestCase
|
4
|
+
include BugTestServerSetupTeardown
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@port = 9999
|
8
|
+
super
|
9
|
+
@server.mount_proc("/redirect_to_test") do|req,res|
|
10
|
+
res.set_redirect(WEBrick::HTTPStatus::TemporaryRedirect, "/test")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_follow_redirect_with_no_redirect
|
15
|
+
|
16
|
+
c = Curl::Easy.new('http://127.0.0.1:9999/test')
|
17
|
+
did_call_redirect = false
|
18
|
+
c.on_redirect do|x|
|
19
|
+
did_call_redirect = true
|
20
|
+
end
|
21
|
+
c.perform
|
22
|
+
|
23
|
+
assert !did_call_redirect, "should reach this point redirect should not have been called"
|
24
|
+
|
25
|
+
c = Curl::Easy.new('http://127.0.0.1:9999/test')
|
26
|
+
did_call_redirect = false
|
27
|
+
c.on_redirect do|x|
|
28
|
+
did_call_redirect = true
|
29
|
+
end
|
30
|
+
c.follow_location = true
|
31
|
+
c.perform
|
32
|
+
|
33
|
+
assert_equal 0, c.redirect_count
|
34
|
+
assert !did_call_redirect, "should reach this point redirect should not have been called"
|
35
|
+
|
36
|
+
c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
|
37
|
+
did_call_redirect = false
|
38
|
+
c.on_redirect do|x|
|
39
|
+
did_call_redirect = true
|
40
|
+
end
|
41
|
+
c.perform
|
42
|
+
assert_equal 307, c.response_code
|
43
|
+
|
44
|
+
assert did_call_redirect, "we should have called on_redirect"
|
45
|
+
|
46
|
+
c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
|
47
|
+
did_call_redirect = false
|
48
|
+
c.follow_location = true
|
49
|
+
# NOTE: while this API is not supported by libcurl e.g. there is no redirect function callback in libcurl we could
|
50
|
+
# add support in ruby for this by executing this callback if redirect_count is greater than 0 at the end of a request in curb_multi.c
|
51
|
+
c.on_redirect do|x|
|
52
|
+
did_call_redirect = true
|
53
|
+
end
|
54
|
+
c.perform
|
55
|
+
assert_equal 1, c.redirect_count
|
56
|
+
assert_equal 200, c.response_code
|
57
|
+
|
58
|
+
assert did_call_redirect, "we should have called on_redirect"
|
59
|
+
|
60
|
+
c.url = 'http://127.0.0.1:9999/test'
|
61
|
+
c.perform
|
62
|
+
assert_equal 0, c.redirect_count
|
63
|
+
assert_equal 200, c.response_code
|
64
|
+
|
65
|
+
puts "checking for raise support"
|
66
|
+
did_raise = false
|
67
|
+
begin
|
68
|
+
c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
|
69
|
+
did_call_redirect = false
|
70
|
+
c.on_redirect do|x|
|
71
|
+
raise "raise"
|
72
|
+
did_call_redirect = true
|
73
|
+
end
|
74
|
+
c.perform
|
75
|
+
rescue => e
|
76
|
+
did_raise = true
|
77
|
+
end
|
78
|
+
assert_equal 307, c.response_code
|
79
|
+
assert did_raise
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -35,15 +35,13 @@ class BugTestInstancePostDiffersFromClassPost < Test::Unit::TestCase
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def do_test
|
38
|
-
c = Curl::Easy.http_post('https://www.google.com/accounts/ServiceLoginAuth',
|
39
|
-
Curl::PostField.content('ltmpl','m_blanco'))
|
38
|
+
c = Curl::Easy.http_post('https://www.google.com/accounts/ServiceLoginAuth', Curl::PostField.content('ltmpl','m_blanco'))
|
40
39
|
body_c, header_c = c.body_str, c.header_str
|
41
40
|
|
42
41
|
sleep 2
|
43
42
|
|
44
|
-
c.http_post('https://www.google.com/accounts/ServiceLoginAuth',
|
45
|
-
|
46
|
-
body_i, header_i = c.body_str, c.header_str
|
43
|
+
c.http_post('https://www.google.com/accounts/ServiceLoginAuth', Curl::PostField.content('ltmpl','m_blanco'))
|
44
|
+
body_i, header_i = c.body, c.head
|
47
45
|
|
48
46
|
# timestamps will differ, just check first bit. We wont get here if
|
49
47
|
# the bug bites anyway...
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
+
|
3
|
+
|
4
|
+
require 'curb'
|
5
|
+
|
6
|
+
class BugIssue102 < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def test_gc_closewait
|
9
|
+
100.times do
|
10
|
+
responses = {}
|
11
|
+
requests = ["http://www.google.co.uk/", "http://www.ruby-lang.org/"]
|
12
|
+
m = Curl::Multi.new
|
13
|
+
# add a few easy handles
|
14
|
+
requests.each do |url|
|
15
|
+
responses[url] = ""
|
16
|
+
c = Curl::Easy.new(url) do|curl|
|
17
|
+
curl.follow_location = true
|
18
|
+
curl.on_body{|data| responses[url] << data; data.size }
|
19
|
+
curl.on_success {|easy| #puts "success, add more easy handles"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
m.add(c)
|
23
|
+
end
|
24
|
+
|
25
|
+
m.perform do
|
26
|
+
#puts "idling... can do some work here"
|
27
|
+
end
|
28
|
+
GC.start
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|