curb 1.0.7 → 1.0.8

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: 805549f6e3fe9190d76c507fa67bf6f6e2a6bbe65bde611cb3aeee6c78cad51f
4
- data.tar.gz: 7f6cab9c618e4535e7ff46b48d11bb5f307158d850b95bd560432dfeb9ea3144
3
+ metadata.gz: 26faca47e47561b5ab762a32f58e2771db9a39c2482152fa1116a7082a27de91
4
+ data.tar.gz: a138509513b023f12537a1bff7fa11e6ef563cc5c59af860b73f119705ee1023
5
5
  SHA512:
6
- metadata.gz: 98f411070f4c3ef1646de29052a2c9a37e7aa2c9009102a7f4e483d1d1188d8bbdae50647e6dd4c8c7439120619e22df5f8c90bba6e1a088e2762cc29109c63d
7
- data.tar.gz: bb8ad84d03972d1e42ce61622060019edc4d6286bab9ab459d2fe9e8ccd3cdc04490a8ba58715fd4efa30e3babf82ac96afce3f5b80fddd1d0bd4d47b197a5f1
6
+ metadata.gz: 4686d9ad528ba0f1931c95fa95d25266c8ffcc2214c3a5f527e437f30977f94bde4a48b38d27ad6342cc868c620e2fd4bd214baeae435725a1746d0c93a22aef
7
+ data.tar.gz: 2e4ba49a5906448e0ad381dad6017cf01140166ee78f1b025b9245cc79c6ff20b37ffd18abc61a56289e8bdeee0750a68f3d84369da36d360f7a61775da10566
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.7"
32
- #define CURB_VER_NUM 1007
31
+ #define CURB_VERSION "1.0.8"
32
+ #define CURB_VER_NUM 1008
33
33
  #define CURB_VER_MAJ 1
34
34
  #define CURB_VER_MIN 0
35
- #define CURB_VER_MIC 7
35
+ #define CURB_VER_MIC 8
36
36
  #define CURB_VER_PATCH 0
37
37
 
38
38
 
data/ext/curb_easy.c CHANGED
@@ -2758,6 +2758,88 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
2758
2758
  }
2759
2759
  }
2760
2760
 
2761
+ /*
2762
+ * call-seq:
2763
+ * easy.http_patch("url=encoded%20form%20data;and=so%20on") => true
2764
+ * easy.http_patch("url=encoded%20form%20data", "and=so%20on", ...) => true
2765
+ * easy.http_patch("url=encoded%20form%20data", Curl::PostField, "and=so%20on", ...) => true
2766
+ * easy.http_patch(Curl::PostField, Curl::PostField ..., Curl::PostField) => true
2767
+ *
2768
+ * PATCH the specified formdata to the currently configured URL using
2769
+ * the current options set for this Curl::Easy instance. This method
2770
+ * always returns true, or raises an exception (defined under
2771
+ * Curl::Err) on error.
2772
+ *
2773
+ * When multipart_form_post is true the multipart logic is used; otherwise,
2774
+ * the arguments are joined into a raw PATCH body.
2775
+ */
2776
+ static VALUE ruby_curl_easy_perform_patch(int argc, VALUE *argv, VALUE self) {
2777
+ ruby_curl_easy *rbce;
2778
+ CURL *curl;
2779
+ int i;
2780
+ VALUE args_ary;
2781
+
2782
+ rb_scan_args(argc, argv, "*", &args_ary);
2783
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2784
+ curl = rbce->curl;
2785
+
2786
+ /* Clear the error buffer */
2787
+ memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
2788
+
2789
+ /* Set the custom HTTP method to PATCH */
2790
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
2791
+
2792
+ if (rbce->multipart_form_post) {
2793
+ VALUE ret;
2794
+ struct curl_httppost *first = NULL, *last = NULL;
2795
+
2796
+ /* Build the multipart form (same logic as for POST) */
2797
+ for (i = 0; i < argc; i++) {
2798
+ if (rb_obj_is_instance_of(argv[i], cCurlPostField)) {
2799
+ append_to_form(argv[i], &first, &last);
2800
+ } else if (rb_type(argv[i]) == T_ARRAY) {
2801
+ long j, argv_len = RARRAY_LEN(argv[i]);
2802
+ for (j = 0; j < argv_len; ++j) {
2803
+ if (rb_obj_is_instance_of(rb_ary_entry(argv[i], j), cCurlPostField)) {
2804
+ append_to_form(rb_ary_entry(argv[i], j), &first, &last);
2805
+ } else {
2806
+ rb_raise(eCurlErrInvalidPostField,
2807
+ "You must use PostFields only with multipart form posts");
2808
+ return Qnil;
2809
+ }
2810
+ }
2811
+ } else {
2812
+ rb_raise(eCurlErrInvalidPostField,
2813
+ "You must use PostFields only with multipart form posts");
2814
+ return Qnil;
2815
+ }
2816
+ }
2817
+ /* Disable the POST flag */
2818
+ curl_easy_setopt(curl, CURLOPT_POST, 0);
2819
+ /* Use the built multipart form as the request body */
2820
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, first);
2821
+ ret = rb_funcall(self, rb_intern("perform"), 0);
2822
+ curl_formfree(first);
2823
+ return ret;
2824
+ } else {
2825
+ /* Join arguments into a raw PATCH body */
2826
+ VALUE patch_body = rb_funcall(args_ary, idJoin, 1, rbstrAmp);
2827
+ if (patch_body == Qnil) {
2828
+ rb_raise(eCurlErrError, "Failed to join arguments");
2829
+ return Qnil;
2830
+ } else {
2831
+ if (rb_type(patch_body) == T_STRING && RSTRING_LEN(patch_body) > 0) {
2832
+ ruby_curl_easy_post_body_set(self, patch_body);
2833
+ }
2834
+ /* If postdata_buffer is still nil, set it so that the PATCH header is enabled */
2835
+ if (rb_easy_nil("postdata_buffer")) {
2836
+ ruby_curl_easy_post_body_set(self, patch_body);
2837
+ }
2838
+ return rb_funcall(self, rb_intern("perform"), 0);
2839
+ }
2840
+ }
2841
+ }
2842
+
2761
2843
  /*
2762
2844
  * call-seq:
2763
2845
  * easy.http_put(data) => true
@@ -2766,18 +2848,70 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
2766
2848
  * current options set for this Curl::Easy instance. This method always
2767
2849
  * returns true, or raises an exception (defined under Curl::Err) on error.
2768
2850
  */
2769
- static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
2851
+ static VALUE ruby_curl_easy_perform_put(int argc, VALUE *argv, VALUE self) {
2770
2852
  ruby_curl_easy *rbce;
2771
2853
  CURL *curl;
2854
+ VALUE args_ary;
2855
+ int i;
2772
2856
 
2857
+ rb_scan_args(argc, argv, "*", &args_ary);
2773
2858
  Data_Get_Struct(self, ruby_curl_easy, rbce);
2774
2859
  curl = rbce->curl;
2775
2860
 
2776
2861
  memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
2862
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
2777
2863
 
2778
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2779
- ruby_curl_easy_put_data_set(self, data);
2780
-
2864
+ /* New: if no arguments were provided, treat as an empty PUT */
2865
+ if (RARRAY_LEN(args_ary) == 0) {
2866
+ /* Option 1: explicitly set an empty body */
2867
+ ruby_curl_easy_put_data_set(self, rb_str_new2(""));
2868
+ }
2869
+ /* If a single argument is given and it is a String or responds to read, use legacy behavior */
2870
+ else if (RARRAY_LEN(args_ary) == 1 &&
2871
+ (rb_type(rb_ary_entry(args_ary, 0)) == T_STRING ||
2872
+ rb_respond_to(rb_ary_entry(args_ary, 0), rb_intern("read")))) {
2873
+ ruby_curl_easy_put_data_set(self, rb_ary_entry(args_ary, 0));
2874
+ }
2875
+ /* Otherwise, if multipart_form_post is true, use multipart logic */
2876
+ else if (rbce->multipart_form_post) {
2877
+ VALUE ret;
2878
+ struct curl_httppost *first = NULL, *last = NULL;
2879
+ for (i = 0; i < RARRAY_LEN(args_ary); i++) {
2880
+ VALUE field = rb_ary_entry(args_ary, i);
2881
+ if (rb_obj_is_instance_of(field, cCurlPostField)) {
2882
+ append_to_form(field, &first, &last);
2883
+ } else if (rb_type(field) == T_ARRAY) {
2884
+ long j;
2885
+ for (j = 0; j < RARRAY_LEN(field); j++) {
2886
+ VALUE subfield = rb_ary_entry(field, j);
2887
+ if (rb_obj_is_instance_of(subfield, cCurlPostField)) {
2888
+ append_to_form(subfield, &first, &last);
2889
+ } else {
2890
+ rb_raise(eCurlErrInvalidPostField,
2891
+ "You must use PostFields only with multipart form posts");
2892
+ }
2893
+ }
2894
+ } else {
2895
+ rb_raise(eCurlErrInvalidPostField,
2896
+ "You must use PostFields only with multipart form posts");
2897
+ }
2898
+ }
2899
+ curl_easy_setopt(curl, CURLOPT_POST, 0);
2900
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, first);
2901
+ /* Set the method explicitly to PUT */
2902
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
2903
+ ret = rb_funcall(self, rb_intern("perform"), 0);
2904
+ curl_formfree(first);
2905
+ return ret;
2906
+ }
2907
+ /* Fallback: join all arguments */
2908
+ else {
2909
+ VALUE post_body = rb_funcall(args_ary, idJoin, 1, rbstrAmp);
2910
+ if (post_body != Qnil && rb_type(post_body) == T_STRING &&
2911
+ RSTRING_LEN(post_body) > 0) {
2912
+ ruby_curl_easy_put_data_set(self, post_body);
2913
+ }
2914
+ }
2781
2915
  return rb_funcall(self, rb_intern("perform"), 0);
2782
2916
  }
2783
2917
 
@@ -3946,7 +4080,8 @@ void init_curb_easy() {
3946
4080
 
3947
4081
  rb_define_method(cCurlEasy, "http", ruby_curl_easy_perform_verb, 1);
3948
4082
  rb_define_method(cCurlEasy, "http_post", ruby_curl_easy_perform_post, -1);
3949
- rb_define_method(cCurlEasy, "http_put", ruby_curl_easy_perform_put, 1);
4083
+ rb_define_method(cCurlEasy, "http_put", ruby_curl_easy_perform_put, -1);
4084
+ rb_define_method(cCurlEasy, "http_patch", ruby_curl_easy_perform_patch, -1);
3950
4085
 
3951
4086
  /* Post-perform info methods */
3952
4087
  rb_define_method(cCurlEasy, "body_str", ruby_curl_easy_body_str_get, 0);
data/lib/curl/easy.rb CHANGED
@@ -374,13 +374,36 @@ module Curl
374
374
  #
375
375
  # call-seq:
376
376
  # Curl::Easy.http_put(url, data) {|c| ... }
377
+ # Curl::Easy.http_put(url, "some=urlencoded%20form%20data&and=so%20on") => true
378
+ # Curl::Easy.http_put(url, "some=urlencoded%20form%20data", "and=so%20on", ...) => true
379
+ # Curl::Easy.http_put(url, "some=urlencoded%20form%20data", Curl::PostField, "and=so%20on", ...) => true
380
+ # Curl::Easy.http_put(url, Curl::PostField, Curl::PostField ..., Curl::PostField) => true
377
381
  #
378
382
  # see easy.http_put
379
383
  #
380
- def http_put(url, data)
381
- c = Curl::Easy.new url
384
+ def http_put(*args)
385
+ url = args.shift
386
+ c = Curl::Easy.new(url)
387
+ yield c if block_given?
388
+ c.http_put(*args)
389
+ c
390
+ end
391
+
392
+ #
393
+ # call-seq:
394
+ # Curl::Easy.http_patch(url, data) {|c| ... }
395
+ # Curl::Easy.http_patch(url, "some=urlencoded%20form%20data&and=so%20on") => true
396
+ # Curl::Easy.http_patch(url, "some=urlencoded%20form%20data", "and=so%20on", ...) => true
397
+ # Curl::Easy.http_patch(url, "some=urlencoded%20form%20data", Curl::PostField, "and=so%20on", ...) => true
398
+ # Curl::Easy.http_patch(url, Curl::PostField, Curl::PostField ..., Curl::PostField) => true
399
+ #
400
+ # see easy.http_patch
401
+ #
402
+ def http_patch(*args)
403
+ url = args.shift
404
+ c = Curl::Easy.new(url)
382
405
  yield c if block_given?
383
- c.http_put data
406
+ c.http_patch(*args)
384
407
  c
385
408
  end
386
409
 
@@ -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
@@ -765,20 +765,27 @@ class TestCurbCurlEasy < Test::Unit::TestCase
765
765
  assert_equal 'GET', curl.body_str
766
766
  end
767
767
 
768
- def test_post_remote
768
+ def test_remote
769
769
  curl = Curl::Easy.new(TestServlet.url)
770
770
  curl.http_post([Curl::PostField.content('document_id', 5)])
771
771
  assert_equal "POST\ndocument_id=5", curl.unescape(curl.body_str)
772
+
773
+ curl.http_put([Curl::PostField.content('document_id', 5)])
774
+ assert_equal "PUT\ndocument_id=5", curl.unescape(curl.body_str)
775
+
776
+ curl.http_patch([Curl::PostField.content('document_id', 5)])
777
+ assert_equal "PATCH\ndocument_id=5", curl.unescape(curl.body_str)
772
778
  end
773
779
 
774
- def test_post_remote_is_easy_handle
780
+ def test_remote_is_easy_handle
775
781
  # see: http://pastie.org/560852 and
776
782
  # http://groups.google.com/group/curb---ruby-libcurl-bindings/browse_thread/thread/216bb2d9b037f347?hl=en
777
- [:post, :get, :head, :delete].each do |method|
783
+ [:post, :patch, :put, :get, :head, :delete].each do |method|
778
784
  retries = 0
779
785
  begin
780
786
  count = 0
781
- Curl::Easy.send("http_#{method}", TestServlet.url) do|c|
787
+ m = "http_#{method}".to_sym
788
+ Curl::Easy.send(m, TestServlet.url) do|c|
782
789
  count += 1
783
790
  assert_equal Curl::Easy, c.class
784
791
  end
@@ -787,12 +794,14 @@ class TestCurbCurlEasy < Test::Unit::TestCase
787
794
  retries+=1
788
795
  retry if retries < 3
789
796
  raise e
797
+ rescue ArgumentError => e
798
+ assert false, "#{m} - #{e.message}"
790
799
  end
791
800
  end
792
801
  end
793
802
 
794
803
  # see: https://github.com/rvanlieshout/curb/commit/8bcdefddc0162484681ebd1a92d52a642666a445
795
- def test_post_multipart_array_remote
804
+ def test_multipart_array_remote
796
805
  curl = Curl::Easy.new(TestServlet.url)
797
806
  curl.multipart_form_post = true
798
807
  fields = [
@@ -802,9 +811,23 @@ class TestCurbCurlEasy < Test::Unit::TestCase
802
811
  curl.http_post(fields)
803
812
  assert_match(/HTTP POST file upload/, curl.body_str)
804
813
  assert_match(/Content-Disposition: form-data/, curl.body_str)
814
+
815
+ curl = Curl::Easy.new(TestServlet.url)
816
+ curl.multipart_form_post = true
817
+ fields = [
818
+ Curl::PostField.file('foo', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown'))),
819
+ Curl::PostField.file('bar', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown')))
820
+ ]
821
+ curl.http_put(fields)
822
+ assert_match(/HTTP POST file upload/, curl.body_str)
823
+ assert_match(/Content-Disposition: form-data/, curl.body_str)
824
+
825
+ curl.http_patch(fields)
826
+ assert_match(/HTTP POST file upload/, curl.body_str)
827
+ assert_match(/Content-Disposition: form-data/, curl.body_str)
805
828
  end
806
829
 
807
- def test_post_with_body_remote
830
+ def test_with_body_remote
808
831
  curl = Curl::Easy.new(TestServlet.url)
809
832
  curl.post_body = 'foo=bar&encoded%20string=val'
810
833
 
@@ -812,23 +835,42 @@ class TestCurbCurlEasy < Test::Unit::TestCase
812
835
 
813
836
  assert_equal "POST\nfoo=bar&encoded%20string=val", curl.body_str
814
837
  assert_equal 'foo=bar&encoded%20string=val', curl.post_body
838
+
839
+ curl = Curl::Easy.new(TestServlet.url)
840
+ curl.put_data = 'foo=bar&encoded%20string=val'
841
+
842
+ curl.perform
843
+
844
+ assert_equal "PUT\nfoo=bar&encoded%20string=val", curl.body_str
815
845
  end
816
846
 
817
- def test_form_post_body_remote
847
+ def test_form_body_remote
818
848
  curl = Curl::Easy.new(TestServlet.url)
819
849
  curl.http_post('foo=bar', 'encoded%20string=val')
820
850
 
821
851
  assert_equal "POST\nfoo=bar&encoded%20string=val", curl.body_str
822
852
  assert_equal 'foo=bar&encoded%20string=val', curl.post_body
823
- end
824
853
 
825
- def test_post_multipart_file_remote
826
854
  curl = Curl::Easy.new(TestServlet.url)
827
- curl.multipart_form_post = true
828
- pf = Curl::PostField.file('readme', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown')))
829
- curl.http_post(pf)
830
- assert_match(/HTTP POST file upload/, curl.body_str)
831
- assert_match(/Content-Disposition: form-data/, curl.body_str)
855
+ curl.http_put('foo=bar', 'encoded%20string=val')
856
+
857
+ assert_equal "PUT\nfoo=bar&encoded%20string=val", curl.body_str
858
+
859
+ curl = Curl::Easy.new(TestServlet.url)
860
+ curl.http_patch('foo=bar', 'encoded%20string=val')
861
+
862
+ assert_equal "PATCH\nfoo=bar&encoded%20string=val", curl.body_str
863
+ end
864
+
865
+ def test_multipart_file_remote
866
+ [:put, :post, :patch].each {|method|
867
+ curl = Curl::Easy.new(TestServlet.url)
868
+ curl.multipart_form_post = true
869
+ pf = Curl::PostField.file('readme', File.expand_path(File.join(File.dirname(__FILE__),'..','README.markdown')))
870
+ curl.send("http_#{method}", pf)
871
+ assert_match(/HTTP POST file upload/, curl.body_str)
872
+ assert_match(/Content-Disposition: form-data/, curl.body_str)
873
+ }
832
874
  end
833
875
 
834
876
  def test_delete_remote
@@ -1065,6 +1107,12 @@ class TestCurbCurlEasy < Test::Unit::TestCase
1065
1107
  assert_equal "PUT\nhello", curl.body_str
1066
1108
  curl.http('COPY')
1067
1109
  assert_equal 'COPY', curl.body_str
1110
+
1111
+ curl.http_patch
1112
+ assert_equal "PATCH\n", curl.body_str
1113
+
1114
+ curl.http_put
1115
+ assert_equal "PUT\n", curl.body_str
1068
1116
  end
1069
1117
 
1070
1118
  def test_easy_http_verbs_must_respond_to_str
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ross Bamford
@@ -52,6 +52,7 @@ files:
52
52
  - tests/bug_follow_redirect_288.rb
53
53
  - tests/bug_instance_post_differs_from_class_post.rb
54
54
  - tests/bug_issue102.rb
55
+ - tests/bug_issue277.rb
55
56
  - tests/bug_multi_segfault.rb
56
57
  - tests/bug_postfields_crash.rb
57
58
  - tests/bug_postfields_crash2.rb
@@ -108,6 +109,7 @@ test_files:
108
109
  - tests/bug_follow_redirect_288.rb
109
110
  - tests/bug_instance_post_differs_from_class_post.rb
110
111
  - tests/bug_issue102.rb
112
+ - tests/bug_issue277.rb
111
113
  - tests/bug_multi_segfault.rb
112
114
  - tests/bug_postfields_crash.rb
113
115
  - tests/bug_postfields_crash2.rb