curb 1.0.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dce5f49b09bacccf705e3d25ba29031dd4fc82c2721860eef02bb4a8af2dd0e2
4
- data.tar.gz: 9456ed69688f2236bdd17f338e26faaf46b91f0fd4e51b3a48d5551ff8fdc433
3
+ metadata.gz: b338d766fda8dfadab0c602cdad4a9f15a529bb495725b15ca5def63a9d8390a
4
+ data.tar.gz: 5b074f1154e3da7ce37eee89e6e5a577a2c09202b6baee72afd2098eac986bd7
5
5
  SHA512:
6
- metadata.gz: df6ab81576ef567878331724c1600c59ff923be34d3a71bd31d07e4999880743e73c31a502bab8aaece54099fd5142bf954dbf004fffd38f0e6698750e3f9682
7
- data.tar.gz: 5b7b867979da88d328e9f71a4a6eb7183430de26902311cb8678b443a6c53cf50aa62952f277bc2c2821bafc2af48c0e28067f7dce512ff7c2912b195bc27ad5
6
+ metadata.gz: 59a25fdf7add62512432495a89d6c8832513ecbc94bb14e7e5720abbfbfea24e0ae52c77fe10497871c6683f39e6988ff184088318e06a14848ab764db38bea2
7
+ data.tar.gz: 4fc8fb4b8111f102107cabc002f1b1a11d2f73e9b66d188ebaf3027a803c90868184c751a3448639bf23ca62eace0a227769aff716a4ba0a8a39b23888346097
data/README.markdown CHANGED
@@ -1,11 +1,12 @@
1
- # Curb - Libcurl bindings for Ruby [![Build Status](https://travis-ci.org/taf2/curb.svg?branch=master)](https://travis-ci.org/taf2/curb)
1
+ # Curb - Libcurl bindings for Ruby
2
2
 
3
+ * [CI Build Status](https://github.com/taf2/curb/actions/workflows/CI.yml)
3
4
  * [rubydoc rdoc](http://www.rubydoc.info/github/taf2/curb/)
4
5
  * [github project](http://github.com/taf2/curb/tree/master)
5
6
 
6
7
  Curb (probably CUrl-RuBy or something) provides Ruby-language bindings for the
7
8
  libcurl(3), a fully-featured client-side URL transfer library.
8
- cURL and libcurl live at [http://curl.haxx.se/](http://curl.haxx.se/) .
9
+ cURL and libcurl live at [https://curl.se/libcurl/](https://curl.se/libcurl/) .
9
10
 
10
11
  Curb is a work-in-progress, and currently only supports libcurl's `easy` and `multi` modes.
11
12
 
@@ -14,9 +15,31 @@ Curb is a work-in-progress, and currently only supports libcurl's `easy` and `mu
14
15
  Curb is copyright (c)2006 Ross Bamford, and released under the terms of the
15
16
  Ruby license. See the LICENSE file for the gory details.
16
17
 
18
+ ## Easy mode
19
+
20
+ Get stuff
21
+ ```
22
+ res = Curl.get("https://www.google.com/")
23
+ puts res.response_code
24
+ puts res.header_str
25
+ puts res.body
26
+ ```
27
+
28
+ Post stuff
29
+ ```
30
+ res = Curl.post("https://your-server.com/endpoint", {post: "this"}.to_json) {|http|
31
+ http.headers["Content-Type"] = "application/json"
32
+ }
33
+ puts res.response_code
34
+ puts res.header_str
35
+ puts res.body
36
+ ```
37
+
38
+
39
+
17
40
  ## You will need
18
41
 
19
- * A working Ruby installation (`1.8.7+` will work but `2.1+` preferred)
42
+ * A working Ruby installation (`2.0.0+` will work but `2.1+` preferred) (it's possible it still works with 1.8.7 but you'd have to tell me if not...)
20
43
  * A working libcurl development installation
21
44
  (Ideally one of the versions listed in the compatibility chart below that maps to your `curb` version)
22
45
  * A sane build environment (e.g. gcc, make)
@@ -29,7 +52,8 @@ tested and reported to work across a variety of platforms / rubies)
29
52
 
30
53
  | Gem Version | Release Date | libcurl versions |
31
54
  | ----------- | ----------- | ---------------- |
32
- | 0.9.8 | Jan 2019 | 7.58 - 7.63 |
55
+ | 1.0.0 | Jan 2022 | 7.58 - 7.81 |
56
+ | 0.9.8 | Jan 2019 | 7.58 - 7.81 |
33
57
  | 0.9.7 | Nov 2018 | 7.56 - 7.60 |
34
58
  | 0.9.6 | May 2018 | 7.51 - 7.59 |
35
59
  | 0.9.5 | May 2018 | 7.51 - 7.59 |
@@ -43,7 +67,7 @@ tested and reported to work across a variety of platforms / rubies)
43
67
  $ gem install curb
44
68
 
45
69
  On Windows, make sure you're using the [DevKit](http://rubyinstaller.org/downloads/) and
46
- the [development version of libcurl](http://curl.haxx.se/gknw.net/7.39.0/dist-w32/curl-7.39.0-devel-mingw32.zip). Unzip, then run this in your command
70
+ the [development version of libcurl](http://curl.se/gknw.net/7.39.0/dist-w32/curl-7.39.0-devel-mingw32.zip). Unzip, then run this in your command
47
71
  line (alter paths to your curl location, but remember to use forward slashes):
48
72
 
49
73
  gem install curb --platform=ruby -- --with-curl-lib=C:/curl-7.39.0-devel-mingw32/lib --with-curl-include=C:/curl-7.39.0-devel-mingw32/include
data/Rakefile CHANGED
@@ -10,13 +10,6 @@ CLOBBER.include '**/*.log'
10
10
  CLOBBER.include '**/Makefile'
11
11
  CLOBBER.include '**/extconf.h'
12
12
 
13
- # Not available for really old rubies, but that's ok.
14
- begin
15
- require 'pry'
16
- rescue LoadError
17
- puts "Failed to load pry."
18
- end
19
-
20
13
  # Load support ruby and rake files (in this order)
21
14
  Dir.glob('tasks/*.rb').each { |r| load r}
22
15
  Dir.glob('tasks/*.rake').each { |r| load r}
data/ext/curb.c CHANGED
@@ -235,12 +235,16 @@ static VALUE ruby_curl_http2_q(VALUE mod) {
235
235
  #endif
236
236
  }
237
237
 
238
+ static void finalize_curb_core(VALUE data) {
239
+ curl_global_cleanup();
240
+ }
241
+
238
242
  void Init_curb_core() {
239
- // TODO we need to call curl_global_cleanup at exit!
240
243
  curl_version_info_data *ver;
241
244
  VALUE curlver, curllongver, curlvernum;
242
245
 
243
246
  curl_global_init(CURL_GLOBAL_ALL);
247
+ rb_set_end_proc(finalize_curb_core, Qnil);
244
248
  ver = curl_version_info(CURLVERSION_NOW);
245
249
 
246
250
  mCurl = rb_define_module("Curl");
@@ -1072,6 +1076,10 @@ void Init_curb_core() {
1072
1076
  CURB_DEFINE(CURLOPT_HAPROXYPROTOCOL);
1073
1077
  #endif
1074
1078
 
1079
+ #if HAVE_CURLOPT_PROXY_SSL_VERIFYHOST
1080
+ CURB_DEFINE(CURLOPT_PROXY_SSL_VERIFYHOST);
1081
+ #endif
1082
+
1075
1083
  #if HAVE_CURLPROTO_RTMPTE
1076
1084
  CURB_DEFINE(CURLPROTO_RTMPTE);
1077
1085
  #endif
data/ext/curb.h CHANGED
@@ -28,11 +28,11 @@
28
28
  #include "curb_macros.h"
29
29
 
30
30
  // These should be managed from the Rake 'release' task.
31
- #define CURB_VERSION "1.0.0"
32
- #define CURB_VER_NUM 1000
31
+ #define CURB_VERSION "1.0.2"
32
+ #define CURB_VER_NUM 1002
33
33
  #define CURB_VER_MAJ 1
34
34
  #define CURB_VER_MIN 0
35
- #define CURB_VER_MIC 0
35
+ #define CURB_VER_MIC 2
36
36
  #define CURB_VER_PATCH 0
37
37
 
38
38
 
data/ext/curb_easy.c CHANGED
@@ -329,9 +329,9 @@ static VALUE ruby_curl_easy_allocate(VALUE klass) {
329
329
 
330
330
  /*
331
331
  * call-seq:
332
- * Curl::Easy.new => #<Curl::Easy...>
333
- * Curl::Easy.new(url = nil) => #<Curl::Easy...>
334
- * Curl::Easy.new(url = nil) { |self| ... } => #<Curl::Easy...>
332
+ * Curl::Easy.new => #<Curl::Easy...>
333
+ * Curl::Easy.new(url = nil) => #<Curl::Easy...>
334
+ * Curl::Easy.new(url = nil) { |self| ... } => #<Curl::Easy...>
335
335
  *
336
336
  * Initialize a new Curl::Easy instance, optionally supplying the URL.
337
337
  * The block form allows further configuration to be supplied before
@@ -376,8 +376,8 @@ static VALUE ruby_curl_easy_initialize(int argc, VALUE *argv, VALUE self) {
376
376
 
377
377
  /*
378
378
  * call-seq:
379
- * easy.clone => #&lt;easy clone&gt;
380
- * easy.dup => #&lt;easy clone&gt;
379
+ * easy.clone => <easy clone>
380
+ * easy.dup => <easy clone>
381
381
  *
382
382
  * Clone this Curl::Easy instance, creating a new instance.
383
383
  * This method duplicates the underlying CURL* handle.
@@ -957,7 +957,7 @@ static VALUE ruby_curl_easy_ftp_commands_set(VALUE self, VALUE ftp_commands) {
957
957
  }
958
958
 
959
959
  /*
960
- * call-seq
960
+ * call-seq:
961
961
  * easy.ftp_commands => array or nil
962
962
  */
963
963
  static VALUE ruby_curl_easy_ftp_commands_get(VALUE self) {
@@ -976,7 +976,7 @@ static VALUE ruby_curl_easy_resolve_set(VALUE self, VALUE resolve) {
976
976
  }
977
977
 
978
978
  /*
979
- * call-seq
979
+ * call-seq:
980
980
  * easy.resolve => array or nil
981
981
  */
982
982
  static VALUE ruby_curl_easy_resolve_get(VALUE self) {
@@ -1595,7 +1595,7 @@ static VALUE ruby_curl_easy_ftp_filemethod_set(VALUE self, VALUE ftp_filemethod)
1595
1595
  }
1596
1596
 
1597
1597
  /*
1598
- * call-seq
1598
+ * call-seq:
1599
1599
  * easy.ftp_filemethod => fixnum
1600
1600
  *
1601
1601
  * Get the configuration for how libcurl will reach files on the server.
@@ -1967,7 +1967,7 @@ static VALUE ruby_curl_easy_resolve_mode_set(VALUE self, VALUE resolve_mode) {
1967
1967
 
1968
1968
  /*
1969
1969
  * call-seq:
1970
- * easy.on_body { |body_data| ... } => &lt;old handler&gt;
1970
+ * easy.on_body { |body_data| ... } => <old handler>
1971
1971
  *
1972
1972
  * Assign or remove the +on_body+ handler for this Curl::Easy instance.
1973
1973
  * To remove a previously-supplied handler, call this method with no
@@ -1986,7 +1986,7 @@ static VALUE ruby_curl_easy_on_body_set(int argc, VALUE *argv, VALUE self) {
1986
1986
 
1987
1987
  /*
1988
1988
  * call-seq:
1989
- * easy.on_success { |easy| ... } => &lt;old handler&gt;
1989
+ * easy.on_success { |easy| ... } => <old handler>
1990
1990
  *
1991
1991
  * Assign or remove the +on_success+ handler for this Curl::Easy instance.
1992
1992
  * To remove a previously-supplied handler, call this method with no
@@ -2001,7 +2001,7 @@ static VALUE ruby_curl_easy_on_success_set(int argc, VALUE *argv, VALUE self) {
2001
2001
 
2002
2002
  /*
2003
2003
  * call-seq:
2004
- * easy.on_failure {|easy,code| ... } => &lt;old handler&gt;
2004
+ * easy.on_failure {|easy,code| ... } => <old handler>
2005
2005
  *
2006
2006
  * Assign or remove the +on_failure+ handler for this Curl::Easy instance.
2007
2007
  * To remove a previously-supplied handler, call this method with no
@@ -2016,7 +2016,7 @@ static VALUE ruby_curl_easy_on_failure_set(int argc, VALUE *argv, VALUE self) {
2016
2016
 
2017
2017
  /*
2018
2018
  * call-seq:
2019
- * easy.on_missing {|easy,code| ... } => &lt;old handler;&gt;
2019
+ * easy.on_missing {|easy,code| ... } => <old handler;>
2020
2020
  *
2021
2021
  * Assign or remove the on_missing handler for this Curl::Easy instance.
2022
2022
  * To remove a previously-supplied handler, call this method with no attached
@@ -2031,7 +2031,7 @@ static VALUE ruby_curl_easy_on_missing_set(int argc, VALUE *argv, VALUE self) {
2031
2031
 
2032
2032
  /*
2033
2033
  * call-seq:
2034
- * easy.on_redirect {|easy,code| ... } => &lt;old handler;&gt;
2034
+ * easy.on_redirect {|easy,code| ... } => <old handler;>
2035
2035
  *
2036
2036
  * Assign or remove the on_redirect handler for this Curl::Easy instance.
2037
2037
  * To remove a previously-supplied handler, call this method with no attached
@@ -2046,7 +2046,7 @@ static VALUE ruby_curl_easy_on_redirect_set(int argc, VALUE *argv, VALUE self) {
2046
2046
 
2047
2047
  /*
2048
2048
  * call-seq:
2049
- * easy.on_complete {|easy| ... } => &lt;old handler&gt;
2049
+ * easy.on_complete {|easy| ... } => <old handler>
2050
2050
  *
2051
2051
  * Assign or remove the +on_complete+ handler for this Curl::Easy instance.
2052
2052
  * To remove a previously-supplied handler, call this method with no
@@ -2060,7 +2060,7 @@ static VALUE ruby_curl_easy_on_complete_set(int argc, VALUE *argv, VALUE self) {
2060
2060
 
2061
2061
  /*
2062
2062
  * call-seq:
2063
- * easy.on_header { |header_data| ... } => &lt;old handler&gt;
2063
+ * easy.on_header { |header_data| ... } => <old handler>
2064
2064
  *
2065
2065
  * Assign or remove the +on_header+ handler for this Curl::Easy instance.
2066
2066
  * To remove a previously-supplied handler, call this method with no
@@ -2076,7 +2076,7 @@ static VALUE ruby_curl_easy_on_header_set(int argc, VALUE *argv, VALUE self) {
2076
2076
 
2077
2077
  /*
2078
2078
  * call-seq:
2079
- * easy.on_progress { |dl_total, dl_now, ul_total, ul_now| ... } => &lt;old handler&gt;
2079
+ * easy.on_progress { |dl_total, dl_now, ul_total, ul_now| ... } => <old handler>
2080
2080
  *
2081
2081
  * Assign or remove the +on_progress+ handler for this Curl::Easy instance.
2082
2082
  * To remove a previously-supplied handler, call this method with no
@@ -2097,7 +2097,7 @@ static VALUE ruby_curl_easy_on_progress_set(int argc, VALUE *argv, VALUE self) {
2097
2097
 
2098
2098
  /*
2099
2099
  * call-seq:
2100
- * easy.on_debug { |type, data| ... } => &lt;old handler&gt;
2100
+ * easy.on_debug { |type, data| ... } => <old handler>
2101
2101
  *
2102
2102
  * Assign or remove the +on_debug+ handler for this Curl::Easy instance.
2103
2103
  * To remove a previously-supplied handler, call this method with no
@@ -2136,11 +2136,14 @@ static VALUE cb_each_http_header(VALUE header, VALUE wrap) {
2136
2136
 
2137
2137
  name = rb_obj_as_string(rb_ary_entry(header, 0));
2138
2138
  value = rb_obj_as_string(rb_ary_entry(header, 1));
2139
-
2140
- // This is a bit inefficient, but we don't want to be modifying
2141
- // the actual values in the original hash.
2142
- header_str = rb_str_plus(name, rb_str_new2(": "));
2143
- header_str = rb_str_plus(header_str, value);
2139
+ if (rb_str_strlen(value) == 0) { // removing the header e.g. Accept: with nothing trailing should remove it see: https://curl.se/libcurl/c/CURLOPT_HTTPHEADER.html
2140
+ header_str = rb_str_plus(name, rb_str_new2(":"));
2141
+ } else {
2142
+ // This is a bit inefficient, but we don't want to be modifying
2143
+ // the actual values in the original hash.
2144
+ header_str = rb_str_plus(name, rb_str_new2(": "));
2145
+ header_str = rb_str_plus(header_str, value);
2146
+ }
2144
2147
  } else {
2145
2148
  header_str = rb_obj_as_string(header);
2146
2149
  }
@@ -2775,6 +2778,10 @@ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
2775
2778
  * your own body handler, this string will be empty.
2776
2779
  */
2777
2780
  static VALUE ruby_curl_easy_body_str_get(VALUE self) {
2781
+ /*
2782
+ TODO: can we force_encoding on the return here if we see charset=utf-8 in the content-type header?
2783
+ Content-Type: application/json; charset=utf-8
2784
+ */
2778
2785
  CURB_OBJECT_HGETTER(ruby_curl_easy, body_data);
2779
2786
  }
2780
2787
 
@@ -3646,6 +3653,11 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3646
3653
  case CURLOPT_SSL_SESSIONID_CACHE:
3647
3654
  curl_easy_setopt(rbce->curl, CURLOPT_SSL_SESSIONID_CACHE, NUM2LONG(val));
3648
3655
  break;
3656
+ #endif
3657
+ #if HAVE_CURLOPT_PROXY_SSL_VERIFYHOST
3658
+ case CURLOPT_PROXY_SSL_VERIFYHOST:
3659
+ curl_easy_setopt(rbce->curl, CURLOPT_PROXY_SSL_VERIFYHOST, NUM2LONG(val));
3660
+ break;
3649
3661
  #endif
3650
3662
  default:
3651
3663
  rb_raise(rb_eTypeError, "Curb unsupported option");
@@ -3763,6 +3775,7 @@ static VALUE ruby_curl_easy_error_message(VALUE klass, VALUE code) {
3763
3775
  }
3764
3776
 
3765
3777
  /* =================== INIT LIB =====================*/
3778
+ // TODO: https://bugs.ruby-lang.org/issues/18007
3766
3779
  void init_curb_easy() {
3767
3780
  idCall = rb_intern("call");
3768
3781
  idJoin = rb_intern("join");
data/ext/curb_macros.h CHANGED
@@ -156,4 +156,10 @@
156
156
  #define CURB_DEFINE(name) \
157
157
  rb_define_const(mCurl, #name, LONG2NUM(name))
158
158
 
159
+ #define CURB_RB_CALLBACK_RAISE(context) \
160
+ VALUE exception = rb_errinfo(); \
161
+ const char *msg = rb_respond_to(exception,rb_intern("message")) ? RSTRING_PTR(rb_funcall(exception, rb_intern("message"), 0)) : ""; \
162
+ rb_set_errinfo(Qnil); \
163
+ rb_raise(eCurlErrAbortedByCallback, "Operation was aborted by an application callback[%s]:\"%s\"", context, msg);
164
+
159
165
  #endif
data/ext/curb_multi.c CHANGED
@@ -43,10 +43,6 @@ 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 unused) {
47
- return Qfalse;
48
- }
49
-
50
46
  void curl_multi_free(ruby_curl_multi *rbcm) {
51
47
  curl_multi_cleanup(rbcm->handle);
52
48
  free(rbcm);
@@ -64,7 +60,7 @@ static void ruby_curl_multi_init(ruby_curl_multi *rbcm) {
64
60
 
65
61
  /*
66
62
  * call-seq:
67
- * Curl::Multi.new => #&lt;Curl::Easy...&gt;
63
+ * Curl::Multi.new => #<Curl::Easy...>
68
64
  *
69
65
  * Create a new Curl::Multi instance
70
66
  */
@@ -132,7 +128,7 @@ VALUE ruby_curl_multi_get_autoclose(VALUE klass) {
132
128
 
133
129
  /*
134
130
  * call-seq:
135
- * multi.requests => [#&lt;Curl::Easy...&gt;, ...]
131
+ * multi.requests => [#<Curl::Easy...>, ...]
136
132
  *
137
133
  * Returns an array containing all the active requests on this Curl::Multi object.
138
134
  */
@@ -274,7 +270,7 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
274
270
  long response_code = -1;
275
271
  VALUE easy;
276
272
  ruby_curl_easy *rbce = NULL;
277
- VALUE callargs, val = Qtrue;
273
+ VALUE callargs;
278
274
 
279
275
  CURLcode ecode = curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, (char**)&easy);
280
276
 
@@ -295,55 +291,73 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
295
291
  raise_curl_easy_error_exception(ecode);
296
292
  }
297
293
 
294
+ int status;
295
+
298
296
  if (!rb_easy_nil("complete_proc")) {
299
297
  callargs = rb_ary_new3(2, rb_easy_get("complete_proc"), easy);
300
298
  rbce->callback_active = 1;
301
- val = rb_rescue(call_status_handler1, callargs, callback_exception, Qnil);
299
+ rb_protect(call_status_handler1, callargs, &status);
302
300
  rbce->callback_active = 0;
303
- //rb_funcall( rb_easy_get("complete_proc"), idCall, 1, easy );
301
+ if (status) {
302
+ CURB_RB_CALLBACK_RAISE("complete")
303
+ }
304
304
  }
305
305
 
306
+ #ifdef HAVE_CURLINFO_RESPONSE_CODE
306
307
  curl_easy_getinfo(rbce->curl, CURLINFO_RESPONSE_CODE, &response_code);
308
+ #else
309
+ // old libcurl
310
+ curl_easy_getinfo(rbce->curl, CURLINFO_HTTP_CODE, &response_code);
311
+ #endif
312
+ long redirect_count;
313
+ curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_COUNT, &redirect_count);
307
314
 
308
315
  if (result != 0) {
309
316
  if (!rb_easy_nil("failure_proc")) {
310
317
  callargs = rb_ary_new3(3, rb_easy_get("failure_proc"), easy, rb_curl_easy_error(result));
311
318
  rbce->callback_active = 1;
312
- val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
319
+ rb_protect(call_status_handler2, callargs, &status);
313
320
  rbce->callback_active = 0;
314
- //rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
321
+ if (status) {
322
+ CURB_RB_CALLBACK_RAISE("failure")
323
+ }
315
324
  }
316
- }
317
- else if (!rb_easy_nil("success_proc") &&
325
+ } else if (!rb_easy_nil("success_proc") &&
318
326
  ((response_code >= 200 && response_code < 300) || response_code == 0)) {
319
327
  /* NOTE: we allow response_code == 0, in the case of non http requests e.g. reading from disk */
320
328
  callargs = rb_ary_new3(2, rb_easy_get("success_proc"), easy);
321
329
  rbce->callback_active = 1;
322
- val = rb_rescue(call_status_handler1, callargs, callback_exception, Qnil);
330
+ rb_protect(call_status_handler1, callargs, &status);
323
331
  rbce->callback_active = 0;
324
- //rb_funcall( rb_easy_get("success_proc"), idCall, 1, easy );
325
- }
326
- else if (!rb_easy_nil("redirect_proc") &&
327
- (response_code >= 300 && response_code < 400)) {
332
+ if (status) {
333
+ CURB_RB_CALLBACK_RAISE("success")
334
+ }
335
+ } else if (!rb_easy_nil("redirect_proc") && ((response_code >= 300 && response_code < 400) || redirect_count > 0) ) {
328
336
  rbce->callback_active = 1;
329
337
  callargs = rb_ary_new3(3, rb_easy_get("redirect_proc"), easy, rb_curl_easy_error(result));
330
338
  rbce->callback_active = 0;
331
- val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
332
- }
333
- else if (!rb_easy_nil("missing_proc") &&
339
+ rb_protect(call_status_handler2, callargs, &status);
340
+ if (status) {
341
+ CURB_RB_CALLBACK_RAISE("redirect")
342
+ }
343
+ } else if (!rb_easy_nil("missing_proc") &&
334
344
  (response_code >= 400 && response_code < 500)) {
335
345
  rbce->callback_active = 1;
336
346
  callargs = rb_ary_new3(3, rb_easy_get("missing_proc"), easy, rb_curl_easy_error(result));
337
347
  rbce->callback_active = 0;
338
- val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
339
- }
340
- else if (!rb_easy_nil("failure_proc") &&
348
+ rb_protect(call_status_handler2, callargs, &status);
349
+ if (status) {
350
+ CURB_RB_CALLBACK_RAISE("missing")
351
+ }
352
+ } else if (!rb_easy_nil("failure_proc") &&
341
353
  (response_code >= 500 && response_code <= 999)) {
342
354
  callargs = rb_ary_new3(3, rb_easy_get("failure_proc"), easy, rb_curl_easy_error(result));
343
355
  rbce->callback_active = 1;
344
- val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
356
+ rb_protect(call_status_handler2, callargs, &status);
345
357
  rbce->callback_active = 0;
346
- //rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
358
+ if (status) {
359
+ CURB_RB_CALLBACK_RAISE("failure")
360
+ }
347
361
  }
348
362
 
349
363
  }
@@ -627,6 +641,8 @@ void init_curb_multi() {
627
641
  idCall = rb_intern("call");
628
642
  cCurlMulti = rb_define_class_under(mCurl, "Multi", rb_cObject);
629
643
 
644
+ rb_undef_alloc_func(cCurlMulti);
645
+
630
646
  /* Class methods */
631
647
  rb_define_singleton_method(cCurlMulti, "new", ruby_curl_multi_new, 0);
632
648
  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) => #&lt;Curl::PostField...&gt;
199
- * Curl::PostField.content(name, content, content_type = nil) => #&lt;Curl::PostField...&gt;
200
- * Curl::PostField.content(name, content_type = nil) { |field| ... } => #&lt;Curl::PostField...&gt;
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) => #&lt;Curl::PostField...&gt;
245
- * Curl::PostField.file(name, local_file_name, remote_file_name = local_file_name) => #&lt;Curl::PostField...&gt;
246
- * Curl::PostField.file(name, remote_file_name) { |field| ... } => #&lt;Curl::PostField...&gt;
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| ... } => &lt;old proc&gt;
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
@@ -405,6 +405,8 @@ have_constant "curlopt_path_as_is"
405
405
  # added in 7.43.0
406
406
  have_constant "curlopt_pipewait"
407
407
 
408
+ have_constant "curlopt_proxy_ssl_verifyhost"
409
+
408
410
  # protocol constants
409
411
  have_constant "curlproto_all"
410
412
  have_constant "curlproto_dict"
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{ |match| match[1] }
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| ... } => #&lt;Curl::Easy...&gt;
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| ... } => #&lt;Curl::Easy...&gt;
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| ... } => #&lt;Curl::Easy...&gt;
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| ... } => #&lt;Curl::Easy...&gt;
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.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
- handle = Thread.current[:curb_curl] ||= Curl::Easy.new
13
- handle.reset
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
- yield handle if block_given?
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
@@ -20,11 +20,21 @@ class BugCrashOnDebug < Test::Unit::TestCase
20
20
  end
21
21
  puts 'b'
22
22
  c = Curl::Easy.new('http://127.0.0.1:9999/test')
23
- c.on_debug do|x|
24
- puts x.inspect
25
- raise "error" # this will get swallowed
23
+ did_raise = false
24
+ did_call = false
25
+ begin
26
+ c.on_success do|x|
27
+ puts x.inspect
28
+ did_call = true
29
+ raise "error" # this will get swallowed
30
+ end
31
+ c.perform
32
+ rescue => e
33
+ did_raise = true
26
34
  end
27
- c.perform
35
+ puts c.response_code
36
+ assert did_raise
37
+ assert did_call
28
38
  puts 'c'
29
39
  ensure
30
40
  puts 'd'
@@ -28,7 +28,8 @@ class BugCrashOnDebug < Test::Unit::TestCase
28
28
  assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
29
29
  c.close
30
30
  ensure
31
- server.shutdown
31
+ server&.shutdown
32
+ thread&.exit
32
33
  end
33
34
 
34
35
  def test_on_progress_abort
@@ -67,7 +68,8 @@ class BugCrashOnDebug < Test::Unit::TestCase
67
68
  assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
68
69
  c.close
69
70
  ensure
70
- server.shutdown
71
+ server&.shutdown
72
+ thread&.exit
71
73
  end
72
74
 
73
75
  end
@@ -0,0 +1,91 @@
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
+
6
+ class BugFollowRedirect288 < Test::Unit::TestCase
7
+ def test_follow_redirect_with_no_redirect
8
+ server = WEBrick::HTTPServer.new( :Port => 9999 )
9
+ server.mount_proc("/test") do|req,res|
10
+ res.body = "hi"
11
+ res['Content-Type'] = "text/html"
12
+ end
13
+ server.mount_proc("/redirect_to_test") do|req,res|
14
+ res.set_redirect(WEBrick::HTTPStatus::TemporaryRedirect, "/test")
15
+ end
16
+
17
+ thread = Thread.new(server) do|srv|
18
+ srv.start
19
+ end
20
+
21
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
22
+ did_call_redirect = false
23
+ c.on_redirect do|x|
24
+ did_call_redirect = true
25
+ end
26
+ c.perform
27
+
28
+ assert !did_call_redirect, "should reach this point redirect should not have been called"
29
+
30
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
31
+ did_call_redirect = false
32
+ c.on_redirect do|x|
33
+ did_call_redirect = true
34
+ end
35
+ c.follow_location = true
36
+ c.perform
37
+
38
+ assert_equal 0, c.redirect_count
39
+ assert !did_call_redirect, "should reach this point redirect should not have been called"
40
+
41
+ c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
42
+ did_call_redirect = false
43
+ c.on_redirect do|x|
44
+ did_call_redirect = true
45
+ end
46
+ c.perform
47
+ assert_equal 307, c.response_code
48
+
49
+ assert did_call_redirect, "we should have called on_redirect"
50
+
51
+ c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
52
+ did_call_redirect = false
53
+ c.follow_location = true
54
+ # NOTE: while this API is not supported by libcurl e.g. there is no redirect function callback in libcurl we could
55
+ # 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
56
+ c.on_redirect do|x|
57
+ did_call_redirect = true
58
+ end
59
+ c.perform
60
+ assert_equal 1, c.redirect_count
61
+ assert_equal 200, c.response_code
62
+
63
+ assert did_call_redirect, "we should have called on_redirect"
64
+
65
+ c.url = 'http://127.0.0.1:9999/test'
66
+ c.perform
67
+ assert_equal 0, c.redirect_count
68
+ assert_equal 200, c.response_code
69
+
70
+ did_raise = false
71
+ begin
72
+ c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
73
+ did_call_redirect = false
74
+ c.on_redirect do|x|
75
+ raise "raise"
76
+ did_call_redirect = true
77
+ end
78
+ c.perform
79
+ rescue => e
80
+ did_raise = true
81
+ end
82
+ assert did_raise
83
+ assert_equal 307, c.response_code
84
+
85
+ ensure
86
+ server.stop
87
+ thread.join
88
+
89
+ end
90
+
91
+ end
@@ -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
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
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
+ class BugRaiseOnCallback < Test::Unit::TestCase
10
+
11
+ def test_on_complte
12
+ server = WEBrick::HTTPServer.new( :Port => 9999 )
13
+ server.mount_proc("/test") do|req,res|
14
+ res.body = "hi"
15
+ res['Content-Type'] = "text/html"
16
+ end
17
+ thread = Thread.new(server) do|srv|
18
+ srv.start
19
+ end
20
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
21
+ did_raise = false
22
+ begin
23
+ c.on_complete do|x|
24
+ assert_equal 'http://127.0.0.1:9999/test', x.url
25
+ raise "error complete" # this will get swallowed
26
+ end
27
+ c.perform
28
+ rescue => e
29
+ did_raise = true
30
+ end
31
+ assert did_raise, "we want to raise an exception if the ruby callbacks raise"
32
+
33
+ ensure
34
+ server.shutdown
35
+ thread.exit
36
+ end
37
+
38
+ end
39
+
40
+ #test_on_debug
@@ -10,6 +10,14 @@ class TestCurbCurlEasy < Test::Unit::TestCase
10
10
  Curl.reset
11
11
  end
12
12
 
13
+ def test_nested_easy_methods
14
+ easy = Curl.get(TestServlet.url) {|http|
15
+ res = Curl.get(TestServlet.url + '/not_here')
16
+ assert_equal 404, res.response_code
17
+ }
18
+ assert_equal 200, easy.response_code
19
+ end
20
+
13
21
  def test_curlopt_stderr_with_file
14
22
  # does not work with Tempfile directly
15
23
  path = Tempfile.new('curb_test_curlopt_stderr').path
@@ -713,9 +721,9 @@ class TestCurbCurlEasy < Test::Unit::TestCase
713
721
  on_success_called = false
714
722
  curl.on_success {|c|
715
723
  on_success_called = true
716
- assert_not_nil c.body_str
717
- assert_equal "", c.header_str
718
- assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
724
+ assert_not_nil c.body
725
+ assert_match /Content-Length: 7714/, c.head
726
+ assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body)
719
727
  }
720
728
  curl.perform
721
729
  assert on_success_called, "Success handler not called"
@@ -1139,7 +1147,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
1139
1147
  c = Curl::Easy.new($TEST_URL)
1140
1148
  c.on_success {|x| raise "error" }
1141
1149
  c.perform
1142
- rescue => e
1150
+ rescue Curl::Err::AbortedByCallbackError => e
1143
1151
  assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
1144
1152
  c.close
1145
1153
  end
@@ -74,7 +74,9 @@ class TestCurbCurlMulti < Test::Unit::TestCase
74
74
  assert did_complete
75
75
  after_open = open_fds.call
76
76
  #puts "after_open: #{after_open} before_open: #{before_open.inspect}"
77
- assert_equal 1, (after_open - before_open), "with max connections set to 1 at this point the connection to google should still be open"
77
+ # ruby process may keep a connection alive
78
+ assert (after_open - before_open) < 3, "with max connections set to 1 at this point the connection to google should still be open"
79
+ assert (after_open - before_open) > 0, "with max connections set to 1 at this point the connection to google should still be open"
78
80
  multi.close
79
81
 
80
82
  after_open = open_fds.call
@@ -480,7 +482,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
480
482
  { :url => TestServlet.url, :method => :get }
481
483
  ]
482
484
  Curl::Multi.http(urls, {:pipeline => true}) do|easy, code, method|
483
- assert_equal nil, code
485
+ assert_equal 200, code
484
486
  case method
485
487
  when :post
486
488
  assert_match(/POST/, easy.body_str)
@@ -494,20 +496,20 @@ class TestCurbCurlMulti < Test::Unit::TestCase
494
496
  end
495
497
 
496
498
  def test_multi_easy_http_with_max_connects
497
- urls = [
499
+ urls = [
498
500
  { :url => TestServlet.url + '?q=1', :method => :get },
499
501
  { :url => TestServlet.url + '?q=2', :method => :get },
500
502
  { :url => TestServlet.url + '?q=3', :method => :get }
501
503
  ]
502
504
  Curl::Multi.http(urls, {:pipeline => true, :max_connects => 1}) do|easy, code, method|
503
- assert_equal nil, code
505
+ assert_equal 200, code
504
506
  case method
505
507
  when :post
506
- assert_match(/POST/, easy.body_str)
508
+ assert_match(/POST/, easy.body)
507
509
  when :get
508
- assert_match(/GET/, easy.body_str)
510
+ assert_match(/GET/, easy.body)
509
511
  when :put
510
- assert_match(/PUT/, easy.body_str)
512
+ assert_match(/PUT/, easy.body)
511
513
  end
512
514
  end
513
515
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ross Bamford
8
8
  - Todd A. Fisher
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-01-14 00:00:00.000000000 Z
12
+ date: 2022-12-28 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Curb (probably CUrl-RuBy or something) provides Ruby-language bindings
15
15
  for the libcurl(3), a fully-featured client-side URL transfer library. cURL and
@@ -50,11 +50,14 @@ files:
50
50
  - tests/bug_crash_on_progress.rb
51
51
  - tests/bug_curb_easy_blocks_ruby_threads.rb
52
52
  - tests/bug_curb_easy_post_with_string_no_content_length_header.rb
53
+ - tests/bug_follow_redirect_288.rb
53
54
  - tests/bug_instance_post_differs_from_class_post.rb
54
55
  - tests/bug_issue102.rb
56
+ - tests/bug_issue277.rb
55
57
  - tests/bug_multi_segfault.rb
56
58
  - tests/bug_postfields_crash.rb
57
59
  - tests/bug_postfields_crash2.rb
60
+ - tests/bug_raise_on_callback.rb
58
61
  - tests/bug_require_last_or_segfault.rb
59
62
  - tests/bugtests.rb
60
63
  - tests/helper.rb
@@ -77,7 +80,7 @@ homepage: https://github.com/taf2/curb
77
80
  licenses:
78
81
  - MIT
79
82
  metadata: {}
80
- post_install_message:
83
+ post_install_message:
81
84
  rdoc_options:
82
85
  - "--main"
83
86
  - README.markdown
@@ -95,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
98
  - !ruby/object:Gem::Version
96
99
  version: '0'
97
100
  requirements: []
98
- rubygems_version: 3.3.3
99
- signing_key:
101
+ rubygems_version: 3.2.33
102
+ signing_key:
100
103
  specification_version: 4
101
104
  summary: Ruby libcurl bindings
102
105
  test_files:
@@ -105,11 +108,14 @@ test_files:
105
108
  - tests/bug_crash_on_progress.rb
106
109
  - tests/bug_curb_easy_blocks_ruby_threads.rb
107
110
  - tests/bug_curb_easy_post_with_string_no_content_length_header.rb
111
+ - tests/bug_follow_redirect_288.rb
108
112
  - tests/bug_instance_post_differs_from_class_post.rb
109
113
  - tests/bug_issue102.rb
114
+ - tests/bug_issue277.rb
110
115
  - tests/bug_multi_segfault.rb
111
116
  - tests/bug_postfields_crash.rb
112
117
  - tests/bug_postfields_crash2.rb
118
+ - tests/bug_raise_on_callback.rb
113
119
  - tests/bug_require_last_or_segfault.rb
114
120
  - tests/bugtests.rb
115
121
  - tests/helper.rb