arachni-typhoeus 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/CHANGELOG.markdown +43 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +30 -0
- data/README.textile +6 -0
- data/Rakefile +40 -0
- data/VERSION +1 -0
- data/benchmarks/profile.rb +25 -0
- data/benchmarks/vs_nethttp.rb +35 -0
- data/examples/twitter.rb +21 -0
- data/ext/typhoeus/.gitignore +7 -0
- data/ext/typhoeus/extconf.rb +65 -0
- data/ext/typhoeus/native.c +11 -0
- data/ext/typhoeus/native.h +21 -0
- data/ext/typhoeus/typhoeus_easy.c +220 -0
- data/ext/typhoeus/typhoeus_easy.h +19 -0
- data/ext/typhoeus/typhoeus_multi.c +211 -0
- data/ext/typhoeus/typhoeus_multi.h +16 -0
- data/lib/typhoeus.rb +58 -0
- data/lib/typhoeus/.gitignore +1 -0
- data/lib/typhoeus/easy.rb +366 -0
- data/lib/typhoeus/filter.rb +28 -0
- data/lib/typhoeus/hydra.rb +245 -0
- data/lib/typhoeus/hydra/callbacks.rb +24 -0
- data/lib/typhoeus/hydra/connect_options.rb +61 -0
- data/lib/typhoeus/hydra/stubbing.rb +52 -0
- data/lib/typhoeus/hydra_mock.rb +131 -0
- data/lib/typhoeus/multi.rb +37 -0
- data/lib/typhoeus/normalized_header_hash.rb +58 -0
- data/lib/typhoeus/remote.rb +306 -0
- data/lib/typhoeus/remote_method.rb +108 -0
- data/lib/typhoeus/remote_proxy_object.rb +50 -0
- data/lib/typhoeus/request.rb +210 -0
- data/lib/typhoeus/response.rb +91 -0
- data/lib/typhoeus/service.rb +20 -0
- data/lib/typhoeus/utils.rb +24 -0
- data/profilers/valgrind.rb +24 -0
- data/spec/fixtures/result_set.xml +60 -0
- data/spec/servers/app.rb +84 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/typhoeus/easy_spec.rb +284 -0
- data/spec/typhoeus/filter_spec.rb +35 -0
- data/spec/typhoeus/hydra_mock_spec.rb +300 -0
- data/spec/typhoeus/hydra_spec.rb +526 -0
- data/spec/typhoeus/multi_spec.rb +74 -0
- data/spec/typhoeus/normalized_header_hash_spec.rb +41 -0
- data/spec/typhoeus/remote_method_spec.rb +141 -0
- data/spec/typhoeus/remote_proxy_object_spec.rb +65 -0
- data/spec/typhoeus/remote_spec.rb +695 -0
- data/spec/typhoeus/request_spec.rb +276 -0
- data/spec/typhoeus/response_spec.rb +151 -0
- data/spec/typhoeus/utils_spec.rb +22 -0
- data/typhoeus.gemspec +123 -0
- metadata +196 -0
data/.gitignore
ADDED
data/CHANGELOG.markdown
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
Current Master
|
2
|
+
--------------
|
3
|
+
* Added extended proxy support [Zapotek, GH-46]
|
4
|
+
* eliminated compile time warnings by using proper type declarations [skaes, GH-54]
|
5
|
+
* fixed broken calls to rb_raise [skaes, GH-54]
|
6
|
+
* prevent leaking of curl easy handles when exceptions are raised (either from typhoeus itself or user callbacks) [skaes, GH-54]
|
7
|
+
* fixed Easy#timed_out? using curl return codes [skaes, GH-54]
|
8
|
+
* provide curl return codes and corresponding curl error messages on classes Easy and Request [skaes, GH-54]
|
9
|
+
* allow VCR to whitelist hosts in Typhoeus stubbing/mocking [myronmarston, GH-57]
|
10
|
+
* added timed_out? documentation, method to Response [dbalatero, GH-34]
|
11
|
+
* added abort to Hydra to prematurely stop a hydra.run [Zapotek]
|
12
|
+
|
13
|
+
0.2.0
|
14
|
+
------
|
15
|
+
* Fix warning in Request#headers from attr_accessor
|
16
|
+
* Params with array values were not parsing into the format that rack expects
|
17
|
+
[GH-39, smartocci]
|
18
|
+
* Removed Rack as a dependency [GH-45]
|
19
|
+
* Added integration hooks for VCR!
|
20
|
+
|
21
|
+
0.1.31
|
22
|
+
------
|
23
|
+
* Fixed bug in setting compression encoding [morhekil]
|
24
|
+
* Exposed authentication control methods through Request interface [morhekil]
|
25
|
+
|
26
|
+
0.1.30
|
27
|
+
-----------
|
28
|
+
* Exposed CURLOPT_CONNECTTIMEOUT_MS to Requests [balexis]
|
29
|
+
|
30
|
+
0.1.29
|
31
|
+
------
|
32
|
+
* Fixed a memory corruption with using CURLOPT_POSTFIELDS [gravis,
|
33
|
+
32531d0821aecc4]
|
34
|
+
|
35
|
+
0.1.28
|
36
|
+
----------------
|
37
|
+
* Added SSL cert options for Typhoeus::Easy [GH-25, gravis]
|
38
|
+
* Ported SSL cert options to Typhoeus::Request interface [gravis]
|
39
|
+
* Added support for any HTTP method (purge for Varnish) [ryana]
|
40
|
+
|
41
|
+
0.1.27
|
42
|
+
------
|
43
|
+
* Added rack as dependency, added dev dependencies to Rakefile [GH-21]
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.2)
|
5
|
+
gemcutter (0.6.1)
|
6
|
+
git (1.2.5)
|
7
|
+
jeweler (1.4.0)
|
8
|
+
gemcutter (>= 0.1.0)
|
9
|
+
git (>= 1.2.5)
|
10
|
+
rubyforge (>= 2.0.0)
|
11
|
+
json (1.4.6)
|
12
|
+
json_pure (1.4.6)
|
13
|
+
rack (1.2.1)
|
14
|
+
rspec (1.3.1)
|
15
|
+
rubyforge (2.0.4)
|
16
|
+
json_pure (>= 1.1.7)
|
17
|
+
sinatra (1.1.0)
|
18
|
+
rack (~> 1.1)
|
19
|
+
tilt (~> 1.1)
|
20
|
+
tilt (1.1)
|
21
|
+
|
22
|
+
PLATFORMS
|
23
|
+
ruby
|
24
|
+
|
25
|
+
DEPENDENCIES
|
26
|
+
diff-lcs
|
27
|
+
jeweler
|
28
|
+
json
|
29
|
+
rspec (= 1.3.1)
|
30
|
+
sinatra
|
data/README.textile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require "spec"
|
4
|
+
require "spec/rake/spectask"
|
5
|
+
require 'lib/typhoeus'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |gemspec|
|
10
|
+
gemspec.name = "arachni-typhoeus"
|
11
|
+
gemspec.summary = "Typhoeus gem tailored for Arachni."
|
12
|
+
gemspec.description = "Original @ https://github.com/dbalatero/typhoeus."
|
13
|
+
gemspec.email = "tasos.laskos@gmail.com"
|
14
|
+
gemspec.homepage = "https://github.com/Zapotek/typhoeus/tree/arachni-typhoeus"
|
15
|
+
gemspec.authors = ["Paul Dix", "Tasos Laskos"]
|
16
|
+
gemspec.add_development_dependency "rspec"
|
17
|
+
gemspec.add_development_dependency "jeweler"
|
18
|
+
gemspec.add_development_dependency "diff-lcs"
|
19
|
+
gemspec.add_development_dependency "sinatra"
|
20
|
+
gemspec.add_development_dependency "json"
|
21
|
+
end
|
22
|
+
|
23
|
+
Jeweler::GemcutterTasks.new
|
24
|
+
rescue LoadError
|
25
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
26
|
+
end
|
27
|
+
|
28
|
+
Spec::Rake::SpecTask.new do |t|
|
29
|
+
t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
|
30
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
31
|
+
end
|
32
|
+
|
33
|
+
task :install do
|
34
|
+
rm_rf "*.gem"
|
35
|
+
puts `gem build typhoeus.gemspec`
|
36
|
+
puts `sudo gem install typhoeus-#{Typhoeus::VERSION}.gem`
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Run all the tests"
|
40
|
+
task :default => :spec
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/typhoeus.rb'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'ruby-prof'
|
4
|
+
|
5
|
+
calls = 20
|
6
|
+
@klass = Class.new do
|
7
|
+
include Typhoeus
|
8
|
+
end
|
9
|
+
|
10
|
+
Typhoeus.init_easy_objects
|
11
|
+
|
12
|
+
RubyProf.start
|
13
|
+
|
14
|
+
responses = []
|
15
|
+
calls.times do |i|
|
16
|
+
responses << @klass.get("http://127.0.0.1:3000/#{i}")
|
17
|
+
end
|
18
|
+
|
19
|
+
responses.each {|r| }#raise unless r.response_body == "whatever"}
|
20
|
+
|
21
|
+
result = RubyProf.stop
|
22
|
+
|
23
|
+
# Print a flat profile to text
|
24
|
+
printer = RubyProf::FlatPrinter.new(result)
|
25
|
+
printer.print(STDOUT, 0)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/typhoeus.rb'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'benchmark'
|
5
|
+
include Benchmark
|
6
|
+
|
7
|
+
|
8
|
+
calls = 20
|
9
|
+
@klass = Class.new do
|
10
|
+
include Typhoeus
|
11
|
+
end
|
12
|
+
|
13
|
+
Typhoeus.init_easy_object_pool
|
14
|
+
|
15
|
+
benchmark do |t|
|
16
|
+
t.report("net::http") do
|
17
|
+
responses = []
|
18
|
+
|
19
|
+
calls.times do |i|
|
20
|
+
responses << open("http://127.0.0.1:3000/#{i}").read
|
21
|
+
end
|
22
|
+
|
23
|
+
responses.each {|r| raise unless r == "whatever"}
|
24
|
+
end
|
25
|
+
|
26
|
+
t.report("typhoeus") do
|
27
|
+
responses = []
|
28
|
+
|
29
|
+
calls.times do |i|
|
30
|
+
responses << @klass.get("http://127.0.0.1:3000/#{i}")
|
31
|
+
end
|
32
|
+
|
33
|
+
responses.each {|r| raise unless r.body == "whatever"}
|
34
|
+
end
|
35
|
+
end
|
data/examples/twitter.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/typhoeus.rb'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
class Twitter
|
6
|
+
include Typhoeus
|
7
|
+
remote_defaults :on_success => lambda {|response| JSON.parse(response.body)},
|
8
|
+
:on_failure => lambda {|response| puts "error code: #{response.code}"},
|
9
|
+
:base_uri => "http://search.twitter.com"
|
10
|
+
|
11
|
+
define_remote_method :search, :path => '/search.json'
|
12
|
+
define_remote_method :trends, :path => '/trends/:time_frame.json'
|
13
|
+
end
|
14
|
+
|
15
|
+
tweets = Twitter.search(:params => {:q => "railsconf"})
|
16
|
+
trends = Twitter.trends(:time_frame => :current)
|
17
|
+
|
18
|
+
# and then the calls don't actually happen until the first time you
|
19
|
+
# call a method on one of the objects returned from the remote_method
|
20
|
+
|
21
|
+
puts tweets.keys # it's a hash from parsed JSON
|
@@ -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,21 @@
|
|
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
|
+
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#ifndef RSTRING_PTR
|
17
|
+
|
18
|
+
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
19
|
+
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
20
|
+
|
21
|
+
#endif
|
@@ -0,0 +1,220 @@
|
|
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_long(VALUE self, VALUE opt_name, VALUE parameter) {
|
30
|
+
CurlEasy *curl_easy;
|
31
|
+
Data_Get_Struct(self, CurlEasy, curl_easy);
|
32
|
+
|
33
|
+
CURLoption opt = NUM2LONG(opt_name);
|
34
|
+
curl_easy_setopt(curl_easy->curl, opt, NUM2LONG(parameter));
|
35
|
+
return opt_name;
|
36
|
+
}
|
37
|
+
|
38
|
+
static VALUE easy_getinfo_string(VALUE self, VALUE info) {
|
39
|
+
char *info_string;
|
40
|
+
CurlEasy *curl_easy;
|
41
|
+
Data_Get_Struct(self, CurlEasy, curl_easy);
|
42
|
+
|
43
|
+
CURLoption opt = NUM2LONG(info);
|
44
|
+
curl_easy_getinfo(curl_easy->curl, opt, &info_string);
|
45
|
+
|
46
|
+
return rb_str_new2(info_string);
|
47
|
+
}
|
48
|
+
|
49
|
+
static VALUE easy_getinfo_long(VALUE self, VALUE info) {
|
50
|
+
long info_long;
|
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_long);
|
56
|
+
|
57
|
+
return LONG2NUM(info_long);
|
58
|
+
}
|
59
|
+
|
60
|
+
static VALUE easy_getinfo_double(VALUE self, VALUE info) {
|
61
|
+
double info_double = 0;
|
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_double);
|
67
|
+
|
68
|
+
return rb_float_new(info_double);
|
69
|
+
}
|
70
|
+
|
71
|
+
static VALUE easy_perform(VALUE self) {
|
72
|
+
CurlEasy *curl_easy;
|
73
|
+
CURLcode return_code;
|
74
|
+
Data_Get_Struct(self, CurlEasy, curl_easy);
|
75
|
+
return_code = curl_easy_perform(curl_easy->curl);
|
76
|
+
rb_iv_set(self, "@curl_return_code", INT2FIX(return_code));
|
77
|
+
|
78
|
+
return Qnil;
|
79
|
+
}
|
80
|
+
|
81
|
+
static size_t write_data_handler(char *stream, size_t size, size_t nmemb, VALUE val) {
|
82
|
+
long stream_size = (long)(size * nmemb);
|
83
|
+
rb_funcall(val, idAppend, 1, rb_str_new(stream, stream_size));
|
84
|
+
return size * nmemb;
|
85
|
+
}
|
86
|
+
|
87
|
+
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *data) {
|
88
|
+
size_t realsize = size * nmemb;
|
89
|
+
RequestChunk *mem = (RequestChunk *)data;
|
90
|
+
|
91
|
+
if (realsize > mem->size - mem->read) {
|
92
|
+
realsize = mem->size - mem->read;
|
93
|
+
}
|
94
|
+
|
95
|
+
if (realsize != 0) {
|
96
|
+
memcpy(ptr, &(mem->memory[mem->read]), realsize);
|
97
|
+
mem->read += realsize;
|
98
|
+
}
|
99
|
+
|
100
|
+
return realsize;
|
101
|
+
}
|
102
|
+
|
103
|
+
static void set_response_handlers(VALUE easy, CURL *curl) {
|
104
|
+
rb_iv_set(easy, "@response_body", rb_str_new2(""));
|
105
|
+
rb_iv_set(easy, "@response_header", rb_str_new2(""));
|
106
|
+
|
107
|
+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&write_data_handler);
|
108
|
+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, rb_iv_get(easy, "@response_body"));
|
109
|
+
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&write_data_handler);
|
110
|
+
curl_easy_setopt(curl, CURLOPT_HEADERDATA, rb_iv_get(easy, "@response_header"));
|
111
|
+
}
|
112
|
+
|
113
|
+
static VALUE easy_reset(VALUE self) {
|
114
|
+
CurlEasy *curl_easy;
|
115
|
+
Data_Get_Struct(self, CurlEasy, curl_easy);
|
116
|
+
|
117
|
+
if (curl_easy->request_chunk != NULL) {
|
118
|
+
free(curl_easy->request_chunk);
|
119
|
+
curl_easy->request_chunk = NULL;
|
120
|
+
}
|
121
|
+
|
122
|
+
if (curl_easy->headers != NULL) {
|
123
|
+
curl_slist_free_all(curl_easy->headers);
|
124
|
+
curl_easy->headers = NULL;
|
125
|
+
}
|
126
|
+
|
127
|
+
curl_easy_reset(curl_easy->curl);
|
128
|
+
|
129
|
+
set_response_handlers(self, curl_easy->curl);
|
130
|
+
|
131
|
+
return Qnil;
|
132
|
+
}
|
133
|
+
|
134
|
+
static VALUE easy_add_header(VALUE self, VALUE header) {
|
135
|
+
CurlEasy *curl_easy;
|
136
|
+
Data_Get_Struct(self, CurlEasy, curl_easy);
|
137
|
+
|
138
|
+
curl_easy->headers = curl_slist_append(curl_easy->headers, RSTRING_PTR(header));
|
139
|
+
return header;
|
140
|
+
}
|
141
|
+
|
142
|
+
static VALUE easy_set_headers(VALUE self) {
|
143
|
+
CurlEasy *curl_easy;
|
144
|
+
Data_Get_Struct(self, CurlEasy, curl_easy);
|
145
|
+
|
146
|
+
curl_easy_setopt(curl_easy->curl, CURLOPT_HTTPHEADER, curl_easy->headers);
|
147
|
+
|
148
|
+
return Qnil;
|
149
|
+
}
|
150
|
+
|
151
|
+
static VALUE easy_set_request_body(VALUE self, VALUE data, VALUE content_length_header) {
|
152
|
+
CurlEasy *curl_easy;
|
153
|
+
Data_Get_Struct(self, CurlEasy, curl_easy);
|
154
|
+
|
155
|
+
curl_easy->request_chunk = ALLOC(RequestChunk);
|
156
|
+
curl_easy->request_chunk->size = RSTRING_LEN(data);
|
157
|
+
curl_easy->request_chunk->memory = StringValuePtr(data);
|
158
|
+
curl_easy->request_chunk->read = 0;
|
159
|
+
|
160
|
+
curl_easy_setopt(curl_easy->curl, CURLOPT_READFUNCTION, (curl_read_callback)read_callback);
|
161
|
+
curl_easy_setopt(curl_easy->curl, CURLOPT_READDATA, curl_easy->request_chunk);
|
162
|
+
curl_easy_setopt(curl_easy->curl, CURLOPT_INFILESIZE, RSTRING_LEN(data));
|
163
|
+
|
164
|
+
return Qnil;
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE easy_escape(VALUE self, VALUE data, VALUE length) {
|
168
|
+
CurlEasy *curl_easy;
|
169
|
+
Data_Get_Struct(self, CurlEasy, curl_easy);
|
170
|
+
|
171
|
+
return rb_str_new2(curl_easy_escape(curl_easy->curl, StringValuePtr(data), (int)NUM2INT(length)));
|
172
|
+
}
|
173
|
+
|
174
|
+
static VALUE version(VALUE self) {
|
175
|
+
return rb_str_new2(curl_version());
|
176
|
+
}
|
177
|
+
|
178
|
+
static VALUE new(int argc, VALUE *argv, VALUE klass) {
|
179
|
+
CURL *curl = curl_easy_init();
|
180
|
+
CurlEasy *curl_easy = ALLOC(CurlEasy);
|
181
|
+
curl_easy->curl = curl;
|
182
|
+
curl_easy->headers = NULL;
|
183
|
+
curl_easy->request_chunk = NULL;
|
184
|
+
VALUE easy = Data_Wrap_Struct(cTyphoeusEasy, 0, dealloc, curl_easy);
|
185
|
+
|
186
|
+
set_response_handlers(easy, curl);
|
187
|
+
|
188
|
+
rb_obj_call_init(easy, argc, argv);
|
189
|
+
|
190
|
+
return easy;
|
191
|
+
}
|
192
|
+
|
193
|
+
static VALUE curl_error_message(VALUE self) {
|
194
|
+
VALUE return_code = rb_iv_get(self, "@curl_return_code");
|
195
|
+
if (return_code == Qnil)
|
196
|
+
return Qnil;
|
197
|
+
else {
|
198
|
+
CURLcode rc = (CURLcode)FIX2INT(return_code);
|
199
|
+
return rb_str_new2(curl_easy_strerror(rc));
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
void init_typhoeus_easy() {
|
204
|
+
VALUE klass = cTyphoeusEasy = rb_define_class_under(mTyphoeus, "Easy", rb_cObject);
|
205
|
+
idAppend = rb_intern("<<");
|
206
|
+
rb_define_singleton_method(klass, "new", new, -1);
|
207
|
+
rb_define_method(klass, "curl_error_message", curl_error_message, 0);
|
208
|
+
rb_define_private_method(klass, "easy_setopt_string", easy_setopt_string, 2);
|
209
|
+
rb_define_private_method(klass, "easy_setopt_long", easy_setopt_long, 2);
|
210
|
+
rb_define_private_method(klass, "easy_getinfo_string", easy_getinfo_string, 1);
|
211
|
+
rb_define_private_method(klass, "easy_getinfo_long", easy_getinfo_long, 1);
|
212
|
+
rb_define_private_method(klass, "easy_getinfo_double", easy_getinfo_double, 1);
|
213
|
+
rb_define_private_method(klass, "easy_perform", easy_perform, 0);
|
214
|
+
rb_define_private_method(klass, "easy_reset", easy_reset, 0);
|
215
|
+
rb_define_private_method(klass, "easy_set_request_body", easy_set_request_body, 1);
|
216
|
+
rb_define_private_method(klass, "easy_set_headers", easy_set_headers, 0);
|
217
|
+
rb_define_private_method(klass, "easy_add_header", easy_add_header, 1);
|
218
|
+
rb_define_private_method(klass, "easy_escape", easy_escape, 2);
|
219
|
+
rb_define_private_method(klass, "version", version, 0);
|
220
|
+
}
|