marnen-typhoeus 0.3.4

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.
Files changed (57) hide show
  1. data/CHANGELOG.markdown +84 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +56 -0
  4. data/LICENSE +20 -0
  5. data/Rakefile +43 -0
  6. data/ext/typhoeus/.gitignore +7 -0
  7. data/ext/typhoeus/extconf.rb +65 -0
  8. data/ext/typhoeus/native.c +12 -0
  9. data/ext/typhoeus/native.h +22 -0
  10. data/ext/typhoeus/typhoeus_easy.c +232 -0
  11. data/ext/typhoeus/typhoeus_easy.h +20 -0
  12. data/ext/typhoeus/typhoeus_form.c +59 -0
  13. data/ext/typhoeus/typhoeus_form.h +13 -0
  14. data/ext/typhoeus/typhoeus_multi.c +217 -0
  15. data/ext/typhoeus/typhoeus_multi.h +16 -0
  16. data/lib/typhoeus.rb +58 -0
  17. data/lib/typhoeus/.gitignore +1 -0
  18. data/lib/typhoeus/easy.rb +413 -0
  19. data/lib/typhoeus/filter.rb +28 -0
  20. data/lib/typhoeus/form.rb +32 -0
  21. data/lib/typhoeus/hydra.rb +250 -0
  22. data/lib/typhoeus/hydra/callbacks.rb +24 -0
  23. data/lib/typhoeus/hydra/connect_options.rb +61 -0
  24. data/lib/typhoeus/hydra/stubbing.rb +68 -0
  25. data/lib/typhoeus/hydra_mock.rb +131 -0
  26. data/lib/typhoeus/multi.rb +37 -0
  27. data/lib/typhoeus/normalized_header_hash.rb +58 -0
  28. data/lib/typhoeus/remote.rb +306 -0
  29. data/lib/typhoeus/remote_method.rb +108 -0
  30. data/lib/typhoeus/remote_proxy_object.rb +50 -0
  31. data/lib/typhoeus/request.rb +269 -0
  32. data/lib/typhoeus/response.rb +122 -0
  33. data/lib/typhoeus/service.rb +20 -0
  34. data/lib/typhoeus/utils.rb +74 -0
  35. data/lib/typhoeus/version.rb +3 -0
  36. data/spec/fixtures/placeholder.gif +0 -0
  37. data/spec/fixtures/placeholder.txt +1 -0
  38. data/spec/fixtures/placeholder.ukn +0 -0
  39. data/spec/fixtures/result_set.xml +60 -0
  40. data/spec/servers/app.rb +97 -0
  41. data/spec/spec_helper.rb +19 -0
  42. data/spec/support/typhoeus_localhost_server.rb +58 -0
  43. data/spec/typhoeus/easy_spec.rb +391 -0
  44. data/spec/typhoeus/filter_spec.rb +35 -0
  45. data/spec/typhoeus/form_spec.rb +117 -0
  46. data/spec/typhoeus/hydra_mock_spec.rb +300 -0
  47. data/spec/typhoeus/hydra_spec.rb +602 -0
  48. data/spec/typhoeus/multi_spec.rb +74 -0
  49. data/spec/typhoeus/normalized_header_hash_spec.rb +41 -0
  50. data/spec/typhoeus/remote_method_spec.rb +141 -0
  51. data/spec/typhoeus/remote_proxy_object_spec.rb +65 -0
  52. data/spec/typhoeus/remote_spec.rb +695 -0
  53. data/spec/typhoeus/request_spec.rb +387 -0
  54. data/spec/typhoeus/response_spec.rb +192 -0
  55. data/spec/typhoeus/utils_spec.rb +22 -0
  56. data/typhoeus.gemspec +35 -0
  57. metadata +235 -0
@@ -0,0 +1,84 @@
1
+ 0.3.3
2
+ --------------
3
+ * Make sure to call the Easy::failure callback on all non-success http response codes, even invalid ones. [balexis]
4
+ * Use bytesize instead of length to determine Content-Length [dlamacchia]
5
+ * Added SSL version option to Easy/Request [michelbarbosa/dbalatero]
6
+
7
+ 0.3.2
8
+ -----
9
+ * Fix array params to be consistent with HTTP spec [gridaphobe]
10
+ * traversal_to_params_hash should use the escape option [itsmeduncan]
11
+ * Fix > 1024 open file descriptors [mschulkind]
12
+ * Fixed a bug with internally queued requests being dropped [mschulkind]
13
+ * Use gemspec in bundler to avoid duplication [mschulkind]
14
+ * Run internally queued requests in FIFO order [mschulkind]
15
+ * Moved Typhoeus::VERSION to a separate file, to fix rake build_native [mschulkind]
16
+ * Fixed problems related to put requests with empty bodies [skaes, GH-84]
17
+ * Added CURLOPT_INTERFACE option via Request#interface=. [spiegela]
18
+ * Added Tempfile support to Form#process! [richievos]
19
+ * Hydra won't forget to accept gzip/deflate encoding [codesnik]
20
+ * Accept and convert strings to integers in Typhoeus::Request#initialize for timeout/cache_timeout/connect_timeout values when using ruby 1.9.x. [djnawara]
21
+ * Added interface for registering stub finders [myronmarston]
22
+ * Fixed header stubbing [myronmarston]
23
+ * Added PKCS12 support [jodell]
24
+ * Make a request with handlers marshallable [bernerdschaefer]
25
+ * Upgraded to RSpec 2 [bernerdschaefer]
26
+ * Fix HTTP status edge-case [balexis]
27
+ * Expose primary_ip to easy object [balexis]
28
+
29
+ 0.2.4
30
+ -----
31
+ * Fix form POSTs to only use multipart for file uploads, otherwise use application/x-www-form-urlencoded [dbalatero]
32
+
33
+ 0.2.3
34
+ -----
35
+ * Code duplication in Typhoeus::Form led to nested URL param errors on POST only. Fixed [dbalatero]
36
+
37
+ 0.2.2
38
+ -----
39
+ * Fixed a problem with nested URL params encoding incorrectly [dbalatero]
40
+
41
+ 0.2.1
42
+ -----
43
+ * Added extended proxy support [Zapotek, GH-46]
44
+ * eliminated compile time warnings by using proper type declarations [skaes, GH-54]
45
+ * fixed broken calls to rb_raise [skaes, GH-54]
46
+ * prevent leaking of curl easy handles when exceptions are raised (either from typhoeus itself or user callbacks) [skaes, GH-54]
47
+ * fixed Easy#timed_out? using curl return codes [skaes, GH-54]
48
+ * provide curl return codes and corresponding curl error messages on classes Easy and Request [skaes, GH-54]
49
+ * allow VCR to whitelist hosts in Typhoeus stubbing/mocking [myronmarston, GH-57]
50
+ * added timed_out? documentation, method to Response [dbalatero, GH-34]
51
+ * added abort to Hydra to prematurely stop a hydra.run [Zapotek]
52
+ * added file upload support for POST requests [jtarchie, GH-59]
53
+
54
+ 0.2.0
55
+ ------
56
+ * Fix warning in Request#headers from attr_accessor
57
+ * Params with array values were not parsing into the format that rack expects
58
+ [GH-39, smartocci]
59
+ * Removed Rack as a dependency [GH-45]
60
+ * Added integration hooks for VCR!
61
+
62
+ 0.1.31
63
+ ------
64
+ * Fixed bug in setting compression encoding [morhekil]
65
+ * Exposed authentication control methods through Request interface [morhekil]
66
+
67
+ 0.1.30
68
+ -----------
69
+ * Exposed CURLOPT_CONNECTTIMEOUT_MS to Requests [balexis]
70
+
71
+ 0.1.29
72
+ ------
73
+ * Fixed a memory corruption with using CURLOPT_POSTFIELDS [gravis,
74
+ 32531d0821aecc4]
75
+
76
+ 0.1.28
77
+ ----------------
78
+ * Added SSL cert options for Typhoeus::Easy [GH-25, gravis]
79
+ * Ported SSL cert options to Typhoeus::Request interface [gravis]
80
+ * Added support for any HTTP method (purge for Varnish) [ryana]
81
+
82
+ 0.1.27
83
+ ------
84
+ * Added rack as dependency, added dev dependencies to Rakefile [GH-21]
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,56 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ typhoeus (0.3.3)
5
+ mime-types
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ ZenTest (4.7.0)
11
+ autotest (4.4.6)
12
+ ZenTest (>= 4.4.1)
13
+ coderay (0.9.8)
14
+ diff-lcs (1.1.2)
15
+ json (1.5.3)
16
+ method_source (0.6.7)
17
+ ruby_parser (>= 2.3.1)
18
+ mime-types (1.18)
19
+ pry (0.9.7.4)
20
+ coderay (~> 0.9.8)
21
+ method_source (~> 0.6.7)
22
+ ruby_parser (>= 2.3.1)
23
+ slop (~> 2.1.0)
24
+ pry-nav (0.0.4)
25
+ pry (~> 0.9.7.4)
26
+ rack (1.3.0)
27
+ rake (0.9.2)
28
+ rspec (2.6.0)
29
+ rspec-core (~> 2.6.0)
30
+ rspec-expectations (~> 2.6.0)
31
+ rspec-mocks (~> 2.6.0)
32
+ rspec-core (2.6.4)
33
+ rspec-expectations (2.6.0)
34
+ diff-lcs (~> 1.1.2)
35
+ rspec-mocks (2.6.0)
36
+ ruby_parser (2.3.1)
37
+ sexp_processor (~> 3.0)
38
+ sexp_processor (3.0.10)
39
+ sinatra (1.2.6)
40
+ rack (~> 1.1)
41
+ tilt (>= 1.2.2, < 2.0)
42
+ slop (2.1.0)
43
+ tilt (1.3.2)
44
+
45
+ PLATFORMS
46
+ ruby
47
+
48
+ DEPENDENCIES
49
+ autotest
50
+ diff-lcs
51
+ json
52
+ pry-nav
53
+ rake
54
+ rspec (~> 2.6)
55
+ sinatra
56
+ typhoeus!
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 David Balatero
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,43 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new do |t|
5
+ end
6
+
7
+ task :install do
8
+ rm_rf "*.gem"
9
+ puts `gem build typhoeus.gemspec`
10
+ puts `gem install typhoeus-#{Typhoeus::VERSION}.gem`
11
+ end
12
+
13
+ desc "Builds the native code"
14
+ task :build_native do
15
+ system("cd ext/typhoeus && ruby extconf.rb && make clean && make")
16
+ end
17
+
18
+ desc "Start up the test servers"
19
+ task :start_test_servers do
20
+ puts "Starting 3 test servers"
21
+
22
+ pids = []
23
+ [3000, 3001, 3002].each do |port|
24
+ if pid = fork
25
+ pids << pid
26
+ else
27
+ exec('ruby', 'spec/servers/app.rb', '-p', port.to_s)
28
+ end
29
+ end
30
+
31
+ at_exit do
32
+ pids.each do |pid|
33
+ puts "Killing pid #{pid}"
34
+ Process.kill("KILL", pid)
35
+ end
36
+ end
37
+
38
+ # Wait for kill.
39
+ sleep
40
+ end
41
+
42
+ desc "Build Typhoeus and run all the tests."
43
+ task :default => [:build_native, :spec]
@@ -0,0 +1,7 @@
1
+ conftest.dSYM/*
2
+ conftest.dSYM
3
+ mkmf.log
4
+ *.o
5
+ native.bundle
6
+ Makefile
7
+ *.bundle
@@ -0,0 +1,65 @@
1
+ ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
2
+
3
+ # :stopdoc:
4
+
5
+ require 'mkmf'
6
+
7
+ ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
8
+ specified_curl = ARGV[0] =~ /^--with-curl/ ? ARGV[0].split("=")[1] : nil
9
+ LIBDIR = specified_curl ? "#{specified_curl}/lib": Config::CONFIG['libdir']
10
+ INCLUDEDIR = specified_curl ? "#{specified_curl}/include" : Config::CONFIG['includedir']
11
+
12
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'macruby'
13
+ $LIBRUBYARG_STATIC.gsub!(/-static/, '')
14
+ end
15
+
16
+ $CFLAGS << " #{ENV["CFLAGS"]}"
17
+ if Config::CONFIG['target_os'] == 'mingw32'
18
+ $CFLAGS << " -DXP_WIN -DXP_WIN32 -DUSE_INCLUDED_VASPRINTF"
19
+ elsif Config::CONFIG['target_os'] == 'solaris2'
20
+ $CFLAGS << " -DUSE_INCLUDED_VASPRINTF"
21
+ else
22
+ $CFLAGS << " -g -DXP_UNIX"
23
+ end
24
+
25
+ use_macports = !(defined?(RUBY_ENGINE) && RUBY_ENGINE != 'ruby')
26
+ $LIBPATH << "/opt/local/lib" if use_macports
27
+
28
+ $CFLAGS << " -O3 -Wall -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline"
29
+
30
+ if Config::CONFIG['target_os'] == 'mingw32'
31
+ header = File.join(ROOT, 'cross', 'curl-7.19.4.win32', 'include')
32
+ unless find_header('curl/curl.h', header)
33
+ abort "need libcurl"
34
+ end
35
+ else
36
+ HEADER_DIRS = [
37
+ File.join(INCLUDEDIR, "curl"),
38
+ INCLUDEDIR,
39
+ '/usr/include/curl',
40
+ '/usr/local/include/curl'
41
+ ]
42
+
43
+ [
44
+ '/opt/local/include/curl',
45
+ '/opt/local/include',
46
+ ].each { |x| HEADER_DIRS.unshift(x) } if use_macports
47
+
48
+ unless find_header('curl/curl.h', *HEADER_DIRS)
49
+ abort "need libcurl"
50
+ end
51
+ end
52
+
53
+ if Config::CONFIG['target_os'] == 'mingw32'
54
+ find_library('curl', 'curl_easy_init',
55
+ File.join(ROOT, 'cross', 'curl-7.19.4.win32', 'bin'))
56
+ else
57
+ find_library('curl', 'curl_easy_init',
58
+ LIBDIR,
59
+ '/opt/local/lib',
60
+ '/usr/local/lib',
61
+ '/usr/lib'
62
+ )
63
+ end
64
+
65
+ create_makefile("typhoeus/native")
@@ -0,0 +1,12 @@
1
+ #include <native.h>
2
+
3
+ VALUE mTyphoeus;
4
+
5
+ void Init_native()
6
+ {
7
+ mTyphoeus = rb_const_get(rb_cObject, rb_intern("Typhoeus"));
8
+
9
+ init_typhoeus_easy();
10
+ init_typhoeus_multi();
11
+ init_typhoeus_form();
12
+ }
@@ -0,0 +1,22 @@
1
+ #ifndef TYPHOEUS_NATIVE
2
+ #define TYPHOEUS_NATIVE
3
+
4
+ #include <ruby.h>
5
+ #include <curl/curl.h>
6
+ #include <curl/easy.h>
7
+ #include <curl/multi.h>
8
+
9
+ void Init_native();
10
+ extern VALUE mTyphoeus;
11
+ extern void init_typhoeus_easy();
12
+ extern void init_typhoeus_multi();
13
+ extern void init_typhoeus_form();
14
+
15
+ #endif
16
+
17
+ #ifndef RSTRING_PTR
18
+
19
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
20
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
21
+
22
+ #endif
@@ -0,0 +1,232 @@
1
+ #include <typhoeus_easy.h>
2
+
3
+ static VALUE idAppend;
4
+ VALUE cTyphoeusEasy;
5
+
6
+ static void dealloc(CurlEasy *curl_easy) {
7
+ if (curl_easy->request_chunk != NULL) {
8
+ free(curl_easy->request_chunk);
9
+ }
10
+
11
+ if (curl_easy->headers != NULL) {
12
+ curl_slist_free_all(curl_easy->headers);
13
+ }
14
+
15
+ curl_easy_cleanup(curl_easy->curl);
16
+
17
+ free(curl_easy);
18
+ }
19
+
20
+ static VALUE easy_setopt_string(VALUE self, VALUE opt_name, VALUE parameter) {
21
+ CurlEasy *curl_easy;
22
+ Data_Get_Struct(self, CurlEasy, curl_easy);
23
+
24
+ CURLoption opt = NUM2LONG(opt_name);
25
+ curl_easy_setopt(curl_easy->curl, opt, StringValuePtr(parameter));
26
+ return opt_name;
27
+ }
28
+
29
+ static VALUE easy_setopt_form(VALUE self, VALUE opt_name, VALUE parameter) {
30
+ CurlEasy *curl_easy;
31
+ CurlForm *curl_form;
32
+ Data_Get_Struct(self, CurlEasy, curl_easy);
33
+ Data_Get_Struct(parameter, CurlForm, curl_form);
34
+
35
+ CURLoption opt = NUM2LONG(opt_name);
36
+ curl_easy_setopt(curl_easy->curl, opt, curl_form->first);
37
+ return opt_name;
38
+ }
39
+
40
+ static VALUE easy_setopt_long(VALUE self, VALUE opt_name, VALUE parameter) {
41
+ CurlEasy *curl_easy;
42
+ Data_Get_Struct(self, CurlEasy, curl_easy);
43
+
44
+ CURLoption opt = NUM2LONG(opt_name);
45
+ curl_easy_setopt(curl_easy->curl, opt, NUM2LONG(parameter));
46
+ return opt_name;
47
+ }
48
+
49
+ static VALUE easy_getinfo_string(VALUE self, VALUE info) {
50
+ char *info_string;
51
+ CurlEasy *curl_easy;
52
+ Data_Get_Struct(self, CurlEasy, curl_easy);
53
+
54
+ CURLoption opt = NUM2LONG(info);
55
+ curl_easy_getinfo(curl_easy->curl, opt, &info_string);
56
+
57
+ return rb_str_new2(info_string);
58
+ }
59
+
60
+ static VALUE easy_getinfo_long(VALUE self, VALUE info) {
61
+ long info_long;
62
+ CurlEasy *curl_easy;
63
+ Data_Get_Struct(self, CurlEasy, curl_easy);
64
+
65
+ CURLoption opt = NUM2LONG(info);
66
+ curl_easy_getinfo(curl_easy->curl, opt, &info_long);
67
+
68
+ return LONG2NUM(info_long);
69
+ }
70
+
71
+ static VALUE easy_getinfo_double(VALUE self, VALUE info) {
72
+ double info_double = 0;
73
+ CurlEasy *curl_easy;
74
+ Data_Get_Struct(self, CurlEasy, curl_easy);
75
+
76
+ CURLoption opt = NUM2LONG(info);
77
+ curl_easy_getinfo(curl_easy->curl, opt, &info_double);
78
+
79
+ return rb_float_new(info_double);
80
+ }
81
+
82
+ static VALUE easy_perform(VALUE self) {
83
+ CurlEasy *curl_easy;
84
+ CURLcode return_code;
85
+ Data_Get_Struct(self, CurlEasy, curl_easy);
86
+ return_code = curl_easy_perform(curl_easy->curl);
87
+ rb_iv_set(self, "@curl_return_code", INT2FIX(return_code));
88
+
89
+ return Qnil;
90
+ }
91
+
92
+ static size_t write_data_handler(char *stream, size_t size, size_t nmemb, VALUE val) {
93
+ long stream_size = (long)(size * nmemb);
94
+ rb_funcall(val, idAppend, 1, rb_str_new(stream, stream_size));
95
+ return size * nmemb;
96
+ }
97
+
98
+ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *data) {
99
+ size_t realsize = size * nmemb;
100
+ RequestChunk *mem = (RequestChunk *)data;
101
+
102
+ if (realsize > mem->size - mem->read) {
103
+ realsize = mem->size - mem->read;
104
+ }
105
+
106
+ if (realsize != 0) {
107
+ memcpy(ptr, &(mem->memory[mem->read]), realsize);
108
+ mem->read += realsize;
109
+ }
110
+
111
+ return realsize;
112
+ }
113
+
114
+ static void set_response_handlers(VALUE easy, CURL *curl) {
115
+ rb_iv_set(easy, "@response_body", rb_str_new2(""));
116
+ rb_iv_set(easy, "@response_header", rb_str_new2(""));
117
+
118
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&write_data_handler);
119
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, rb_iv_get(easy, "@response_body"));
120
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&write_data_handler);
121
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, rb_iv_get(easy, "@response_header"));
122
+ }
123
+
124
+ static VALUE easy_reset(VALUE self) {
125
+ CurlEasy *curl_easy;
126
+ Data_Get_Struct(self, CurlEasy, curl_easy);
127
+
128
+ if (curl_easy->request_chunk != NULL) {
129
+ free(curl_easy->request_chunk);
130
+ curl_easy->request_chunk = NULL;
131
+ }
132
+
133
+ if (curl_easy->headers != NULL) {
134
+ curl_slist_free_all(curl_easy->headers);
135
+ curl_easy->headers = NULL;
136
+ }
137
+
138
+ curl_easy_reset(curl_easy->curl);
139
+
140
+ set_response_handlers(self, curl_easy->curl);
141
+
142
+ return Qnil;
143
+ }
144
+
145
+ static VALUE easy_add_header(VALUE self, VALUE header) {
146
+ CurlEasy *curl_easy;
147
+ Data_Get_Struct(self, CurlEasy, curl_easy);
148
+
149
+ curl_easy->headers = curl_slist_append(curl_easy->headers, RSTRING_PTR(header));
150
+ return header;
151
+ }
152
+
153
+ static VALUE easy_set_headers(VALUE self) {
154
+ CurlEasy *curl_easy;
155
+ Data_Get_Struct(self, CurlEasy, curl_easy);
156
+
157
+ curl_easy_setopt(curl_easy->curl, CURLOPT_HTTPHEADER, curl_easy->headers);
158
+
159
+ return Qnil;
160
+ }
161
+
162
+ static VALUE easy_set_request_body(VALUE self, VALUE data, VALUE content_length_header) {
163
+ CurlEasy *curl_easy;
164
+ Data_Get_Struct(self, CurlEasy, curl_easy);
165
+
166
+ curl_easy->request_chunk = ALLOC(RequestChunk);
167
+ curl_easy->request_chunk->size = RSTRING_LEN(data);
168
+ curl_easy->request_chunk->memory = StringValuePtr(data);
169
+ curl_easy->request_chunk->read = 0;
170
+
171
+ curl_easy_setopt(curl_easy->curl, CURLOPT_READFUNCTION, (curl_read_callback)read_callback);
172
+ curl_easy_setopt(curl_easy->curl, CURLOPT_READDATA, curl_easy->request_chunk);
173
+ curl_easy_setopt(curl_easy->curl, CURLOPT_INFILESIZE, RSTRING_LEN(data));
174
+
175
+ return Qnil;
176
+ }
177
+
178
+ static VALUE easy_escape(VALUE self, VALUE data, VALUE length) {
179
+ CurlEasy *curl_easy;
180
+ Data_Get_Struct(self, CurlEasy, curl_easy);
181
+
182
+ return rb_str_new2(curl_easy_escape(curl_easy->curl, StringValuePtr(data), (int)NUM2INT(length)));
183
+ }
184
+
185
+ static VALUE version(VALUE self) {
186
+ return rb_str_new2(curl_version());
187
+ }
188
+
189
+ static VALUE new(int argc, VALUE *argv, VALUE klass) {
190
+ CURL *curl = curl_easy_init();
191
+ CurlEasy *curl_easy = ALLOC(CurlEasy);
192
+ curl_easy->curl = curl;
193
+ curl_easy->headers = NULL;
194
+ curl_easy->request_chunk = NULL;
195
+ VALUE easy = Data_Wrap_Struct(cTyphoeusEasy, 0, dealloc, curl_easy);
196
+
197
+ set_response_handlers(easy, curl);
198
+
199
+ rb_obj_call_init(easy, argc, argv);
200
+
201
+ return easy;
202
+ }
203
+
204
+ static VALUE curl_error_message(VALUE self) {
205
+ VALUE return_code = rb_iv_get(self, "@curl_return_code");
206
+ if (return_code == Qnil)
207
+ return Qnil;
208
+ else {
209
+ CURLcode rc = (CURLcode)FIX2INT(return_code);
210
+ return rb_str_new2(curl_easy_strerror(rc));
211
+ }
212
+ }
213
+
214
+ void init_typhoeus_easy() {
215
+ VALUE klass = cTyphoeusEasy = rb_define_class_under(mTyphoeus, "Easy", rb_cObject);
216
+ idAppend = rb_intern("<<");
217
+ rb_define_singleton_method(klass, "new", new, -1);
218
+ rb_define_method(klass, "curl_error_message", curl_error_message, 0);
219
+ rb_define_private_method(klass, "easy_setopt_string", easy_setopt_string, 2);
220
+ rb_define_private_method(klass, "easy_setopt_form", easy_setopt_form, 2);
221
+ rb_define_private_method(klass, "easy_setopt_long", easy_setopt_long, 2);
222
+ rb_define_private_method(klass, "easy_getinfo_string", easy_getinfo_string, 1);
223
+ rb_define_private_method(klass, "easy_getinfo_long", easy_getinfo_long, 1);
224
+ rb_define_private_method(klass, "easy_getinfo_double", easy_getinfo_double, 1);
225
+ rb_define_private_method(klass, "easy_perform", easy_perform, 0);
226
+ rb_define_private_method(klass, "easy_reset", easy_reset, 0);
227
+ rb_define_private_method(klass, "easy_set_request_body", easy_set_request_body, 1);
228
+ rb_define_private_method(klass, "easy_set_headers", easy_set_headers, 0);
229
+ rb_define_private_method(klass, "easy_add_header", easy_add_header, 1);
230
+ rb_define_private_method(klass, "easy_escape", easy_escape, 2);
231
+ rb_define_private_method(klass, "version", version, 0);
232
+ }