curl_ffi 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/bindings.rb +5 -4
- data/lib/curl_ffi/version.rb +1 -1
- metadata +2 -4
- data/lib/streamly/request.rb +0 -136
- data/lib/streamly.rb +0 -124
data/lib/bindings.rb
CHANGED
@@ -28,10 +28,6 @@ module CurlFFI
|
|
28
28
|
INFO_DOUBLE = 0x300000
|
29
29
|
INFO_SLIST = 0x400000
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
31
|
CODE = enum :code, [
|
36
32
|
:OK, 0,
|
37
33
|
:UNSUPPORTED_PROTOCOL, 1,
|
@@ -997,4 +993,9 @@ module CurlFFI
|
|
997
993
|
|
998
994
|
attach_function :slist_append, :curl_slist_append, [:pointer, :string], :pointer
|
999
995
|
attach_function :slist_free_all, :curl_slist_free_all, [:pointer], :void
|
996
|
+
|
997
|
+
class CurlSlist < FFI::Struct
|
998
|
+
layout :data, :string,
|
999
|
+
:next, :pointer
|
1000
|
+
end
|
1000
1001
|
end
|
data/lib/curl_ffi/version.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 6
|
9
|
+
version: 0.0.6
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Arthur Schreiber
|
@@ -67,8 +67,6 @@ files:
|
|
67
67
|
- lib/curl_ffi/easy.rb
|
68
68
|
- lib/curl_ffi/multi.rb
|
69
69
|
- lib/curl_ffi/version.rb
|
70
|
-
- lib/streamly.rb
|
71
|
-
- lib/streamly/request.rb
|
72
70
|
- spec/curl_ffi/easy_spec.rb
|
73
71
|
- spec/curl_ffi/multi_spec.rb
|
74
72
|
- spec/spec_helper.rb
|
data/lib/streamly/request.rb
DELETED
@@ -1,136 +0,0 @@
|
|
1
|
-
require "ffi"
|
2
|
-
require "singleton"
|
3
|
-
|
4
|
-
module Streamly
|
5
|
-
class Request
|
6
|
-
include Singleton
|
7
|
-
|
8
|
-
attr_reader :response_header_handler, :response_body_handler
|
9
|
-
|
10
|
-
CallHandler = Proc.new do |stream, size, nmemb, handler|
|
11
|
-
handler.call(stream)
|
12
|
-
size * nmemb
|
13
|
-
end
|
14
|
-
|
15
|
-
StringHandler = Proc.new do |stream, size, nmemb, handler|
|
16
|
-
if handler.nil?
|
17
|
-
handler = stream.clone
|
18
|
-
else
|
19
|
-
handler << stream
|
20
|
-
end
|
21
|
-
size * nmemb
|
22
|
-
end
|
23
|
-
|
24
|
-
DataHandler = Proc.new do |stream, size, nmemb, handler|
|
25
|
-
case handler
|
26
|
-
when String then handler << stream
|
27
|
-
else handler.call(stream)
|
28
|
-
end
|
29
|
-
size * nmemb
|
30
|
-
end
|
31
|
-
|
32
|
-
# @TODO: Argumenting Checking + Error Handling
|
33
|
-
def initialize(url, method=:get, options={})
|
34
|
-
# url should be a string that doesn't suck
|
35
|
-
# method should be :post, :get, :put, :delete, :head
|
36
|
-
# options should contain any of the following keys:
|
37
|
-
# :headers, :response_header_handler, :response_body_handler, :payload (required if method = :post / :put)
|
38
|
-
|
39
|
-
# @response_header_handler ||= options[:response_header_handler] || FFI::MemoryPointer.from_string("")
|
40
|
-
# @response_body_handler ||= options[:response_body_handler] || FFI::MemoryPointer.from_string("")
|
41
|
-
|
42
|
-
case method
|
43
|
-
when :get then connection.setopt :HTTPGET, 1
|
44
|
-
when :head then connection.setopt :NOBODY, 1
|
45
|
-
when :post then connection.setopt :POST, 1
|
46
|
-
connection.setopt :POSTFIELDS, options[:payload]
|
47
|
-
connection.setopt :POSTFIELDSIZE, options[:payload].size
|
48
|
-
when :put then connection.setopt :CUSTOMREQUEST, "PUT"
|
49
|
-
connection.setopt :POSTFIELDS, options[:payload]
|
50
|
-
connection.setopt :POSTFIELDSIZE, options[:payload].size
|
51
|
-
when :delete then connection.setopt :CUSTOMREQUEST, "DELETE"
|
52
|
-
# else I WILL CUT YOU
|
53
|
-
end
|
54
|
-
|
55
|
-
if options[:headers].is_a? Hash and options[:headers].size > 0
|
56
|
-
options[:headers].each_pair do |key_and_value|
|
57
|
-
@request_headers = CurlFFI.slist_append(request_headers, key_and_value.join(": "))
|
58
|
-
end
|
59
|
-
connection.setopt :HTTPHEADER, @request_headers
|
60
|
-
end
|
61
|
-
|
62
|
-
if options[:response_header_handler].nil?
|
63
|
-
# @response_header_handler = FFI::MemoryPointer.from_string("")
|
64
|
-
@response_header_handler = FFI::MemoryPointer.new(:pointer)
|
65
|
-
connection.setopt_str_handler :HEADERFUNCTION, StringHandler
|
66
|
-
connection.setopt_str_handler :WRITEHEADER, @response_header_handler
|
67
|
-
else
|
68
|
-
@response_header_handler = options[:response_header_handler]
|
69
|
-
connection.setopt_handler :HEADERFUNCTION, CallHandler
|
70
|
-
connection.setopt_handler :WRITEHEADER, @response_header_handler
|
71
|
-
end
|
72
|
-
|
73
|
-
unless method == :head
|
74
|
-
connection.setopt :ENCODING, "identity, deflate, gzip"
|
75
|
-
|
76
|
-
if options[:response_body_handler].nil?
|
77
|
-
# @response_body_handler = FFI::MemoryPointer.from_string("")
|
78
|
-
@response_body_handler = FFI::MemoryPointer.new(:pointer)
|
79
|
-
connection.setopt_str_handler :WRITEFUNCTION, StringHandler
|
80
|
-
connection.setopt_str_handler :FILE, @response_body_handler
|
81
|
-
else
|
82
|
-
@response_body_handler = options[:response_body_handler]
|
83
|
-
connection.setopt_handler :WRITEFUNCTION, CallHandler
|
84
|
-
connection.setopt_handler :FILE, @response_body_handler
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
connection.setopt :URL, FFI::MemoryPointer.from_string(url)
|
89
|
-
|
90
|
-
# Other common options (blame streamly guy)
|
91
|
-
connection.setopt :FOLLOWLOCATION, 1
|
92
|
-
connection.setopt :MAXREDIRS, 3
|
93
|
-
|
94
|
-
# This should be an option
|
95
|
-
connection.setopt :SSL_VERIFYPEER, 0
|
96
|
-
connection.setopt :SSL_VERIFYHOST, 0
|
97
|
-
|
98
|
-
connection.setopt :ERRORBUFFER, error_buffer
|
99
|
-
|
100
|
-
return self
|
101
|
-
end
|
102
|
-
|
103
|
-
def connection
|
104
|
-
@connection ||= CurlFFI::Easy.new
|
105
|
-
end
|
106
|
-
|
107
|
-
def error_buffer
|
108
|
-
@error_buffer ||= FFI::MemoryPointer.new(:char, CurlFFI::ERROR_SIZE, :clear)
|
109
|
-
end
|
110
|
-
|
111
|
-
def request_headers
|
112
|
-
@request_headers ||= FFI::MemoryPointer.from_string("")
|
113
|
-
end
|
114
|
-
=begin
|
115
|
-
|
116
|
-
=end
|
117
|
-
def execute
|
118
|
-
connection.perform
|
119
|
-
return response_body_handler
|
120
|
-
end
|
121
|
-
|
122
|
-
def self.execute(url, method=:get, options={})
|
123
|
-
new(url, method, options).execute
|
124
|
-
end
|
125
|
-
|
126
|
-
# streamly's .c internal methods:
|
127
|
-
# @TODO: header_handler
|
128
|
-
# @TODO: data_handler
|
129
|
-
# @TODO: each_http_header
|
130
|
-
# @TODO: select_error
|
131
|
-
# @TODO: rb_streamly_new
|
132
|
-
# @TODO: rb_streamly_init
|
133
|
-
# @TODO: nogvl_perform
|
134
|
-
# @TODO: rb_streamly_execute
|
135
|
-
end
|
136
|
-
end
|
data/lib/streamly.rb
DELETED
@@ -1,124 +0,0 @@
|
|
1
|
-
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
-
|
4
|
-
require "ffi"
|
5
|
-
require "curl_ffi"
|
6
|
-
|
7
|
-
module Streamly
|
8
|
-
extend FFI::Library
|
9
|
-
|
10
|
-
autoload :Request, "streamly/request"
|
11
|
-
|
12
|
-
class Error < StandardError; end
|
13
|
-
class UnsupportedProtocol < StandardError; end
|
14
|
-
class URLFormatError < StandardError; end
|
15
|
-
class HostResolutionError < StandardError; end
|
16
|
-
class ConnectionFailed < StandardError; end
|
17
|
-
class PartialFileError < StandardError; end
|
18
|
-
class TimeoutError < StandardError; end
|
19
|
-
class TooManyRedirects < StandardError; end
|
20
|
-
|
21
|
-
# A helper method to make HEAD requests a dead-simple one-liner
|
22
|
-
#
|
23
|
-
# Example:
|
24
|
-
# Streamly.head("www.somehost.com/some_resource/1")
|
25
|
-
#
|
26
|
-
# Streamly.head("www.somehost.com/some_resource/1") do |header_chunk|
|
27
|
-
# # do something with _header_chunk_
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# Parameters:
|
31
|
-
# +url+ should be a String, the url to request
|
32
|
-
# +headers+ should be a Hash and is optional
|
33
|
-
#
|
34
|
-
# This method also accepts a block, which will stream the response headers in chunks to the caller
|
35
|
-
def self.head(url, headers=nil, &block)
|
36
|
-
opts = {:method => :head, :url => url, :headers => headers}
|
37
|
-
opts.merge!({:response_header_handler => block}) if block_given?
|
38
|
-
Request.execute(opts)
|
39
|
-
end
|
40
|
-
|
41
|
-
# A helper method to make HEAD requests a dead-simple one-liner
|
42
|
-
#
|
43
|
-
# Example:
|
44
|
-
# Streamly.get("www.somehost.com/some_resource/1")
|
45
|
-
#
|
46
|
-
# Streamly.get("www.somehost.com/some_resource/1") do |chunk|
|
47
|
-
# # do something with _chunk_
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# Parameters:
|
51
|
-
# +url+ should be a String, the url to request
|
52
|
-
# +headers+ should be a Hash and is optional
|
53
|
-
#
|
54
|
-
# This method also accepts a block, which will stream the response body in chunks to the caller
|
55
|
-
def self.get(url, headers=nil, &block)
|
56
|
-
opts = {:headers => headers}
|
57
|
-
opts.merge!({:response_body_handler => block}) if block_given?
|
58
|
-
Request.execute(url, :get, opts)
|
59
|
-
end
|
60
|
-
|
61
|
-
# A helper method to make HEAD requests a dead-simple one-liner
|
62
|
-
#
|
63
|
-
# Example:
|
64
|
-
# Streamly.post("www.somehost.com/some_resource", "asset[id]=2&asset[name]=bar")
|
65
|
-
#
|
66
|
-
# Streamly.post("www.somehost.com/some_resource", "asset[id]=2&asset[name]=bar") do |chunk|
|
67
|
-
# # do something with _chunk_
|
68
|
-
# end
|
69
|
-
#
|
70
|
-
# Parameters:
|
71
|
-
# +url+ should be a String (the url to request) and is required
|
72
|
-
# +payload+ should be a String and is required
|
73
|
-
# +headers+ should be a Hash and is optional
|
74
|
-
#
|
75
|
-
# This method also accepts a block, which will stream the response body in chunks to the caller
|
76
|
-
def self.post(url, payload, headers=nil, &block)
|
77
|
-
opts = {:payload => payload, :headers => headers}
|
78
|
-
opts.merge!({:response_body_handler => block}) if block_given?
|
79
|
-
Request.execute(url, :post, opts)
|
80
|
-
end
|
81
|
-
|
82
|
-
# A helper method to make HEAD requests a dead-simple one-liner
|
83
|
-
#
|
84
|
-
# Example:
|
85
|
-
# Streamly.put("www.somehost.com/some_resource/1", "asset[name]=foo")
|
86
|
-
#
|
87
|
-
# Streamly.put("www.somehost.com/some_resource/1", "asset[name]=foo") do |chunk|
|
88
|
-
# # do something with _chunk_
|
89
|
-
# end
|
90
|
-
#
|
91
|
-
# Parameters:
|
92
|
-
# +url+ should be a String (the url to request) and is required
|
93
|
-
# +payload+ should be a String and is required
|
94
|
-
# +headers+ should be a Hash and is optional
|
95
|
-
#
|
96
|
-
# This method also accepts a block, which will stream the response body in chunks to the caller
|
97
|
-
def self.put(url, payload, headers=nil, &block)
|
98
|
-
opts = {:payload => payload, :headers => headers}
|
99
|
-
opts.merge!({:response_body_handler => block}) if block_given?
|
100
|
-
Request.execute(url, :put, opts)
|
101
|
-
end
|
102
|
-
|
103
|
-
# A helper method to make HEAD requests a dead-simple one-liner
|
104
|
-
#
|
105
|
-
# Example:
|
106
|
-
# Streamly.delete("www.somehost.com/some_resource/1")
|
107
|
-
#
|
108
|
-
# Streamly.delete("www.somehost.com/some_resource/1") do |chunk|
|
109
|
-
# # do something with _chunk_
|
110
|
-
# end
|
111
|
-
#
|
112
|
-
# Parameters:
|
113
|
-
# +url+ should be a String, the url to request
|
114
|
-
# +headers+ should be a Hash and is optional
|
115
|
-
#
|
116
|
-
# This method also accepts a block, which will stream the response body in chunks to the caller
|
117
|
-
def self.delete(url, headers={}, &block)
|
118
|
-
opts = {:method => :delete, :url => url, :headers => headers}
|
119
|
-
opts.merge!({:response_body_handler => block}) if block_given?
|
120
|
-
Request.execute(opts)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# require "streamly/request" # May need to do this? Not sure how autoload works with FFI yet
|