streamly_ffi 0.1.6 → 0.2.0
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.
- data/Gemfile +9 -0
- data/Gemfile.lock +32 -0
- data/benchmark/basic_request.rb +9 -1
- data/lib/streamly_ffi.rb +22 -3
- data/lib/streamly_ffi/base.rb +155 -0
- data/lib/streamly_ffi/connection.rb +112 -0
- data/lib/streamly_ffi/persistent_request.rb +15 -0
- data/lib/streamly_ffi/request.rb +3 -146
- data/lib/streamly_ffi/version.rb +1 -1
- data/streamly_ffi.gemspec +0 -1
- metadata +9 -4
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
streamly_ffi (0.1.6)
|
5
|
+
curl_ffi
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
curl_ffi (0.0.6)
|
11
|
+
ffi
|
12
|
+
diff-lcs (1.1.2)
|
13
|
+
ffi (0.6.3)
|
14
|
+
rake (>= 0.8.7)
|
15
|
+
rake (0.8.7)
|
16
|
+
rspec (2.1.0)
|
17
|
+
rspec-core (~> 2.1.0)
|
18
|
+
rspec-expectations (~> 2.1.0)
|
19
|
+
rspec-mocks (~> 2.1.0)
|
20
|
+
rspec-core (2.1.0)
|
21
|
+
rspec-expectations (2.1.0)
|
22
|
+
diff-lcs (~> 1.1.2)
|
23
|
+
rspec-mocks (2.1.0)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
curl_ffi
|
30
|
+
rspec
|
31
|
+
rspec-core
|
32
|
+
streamly_ffi!
|
data/benchmark/basic_request.rb
CHANGED
@@ -34,10 +34,18 @@ Benchmark.bmbm do |x|
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
x.report do
|
38
|
+
puts "StreamlyFFI2"
|
39
|
+
conn = StreamlyFFI::Connection.new
|
40
|
+
(ARGV[1] || 1).to_i.times do
|
41
|
+
conn.get(url)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
37
45
|
x.report do
|
38
46
|
puts "`curl`"
|
39
47
|
(ARGV[1] || 1).to_i.times do
|
40
|
-
`curl
|
48
|
+
`curl --compressed --silent #{url}`
|
41
49
|
end
|
42
50
|
end
|
43
51
|
|
data/lib/streamly_ffi.rb
CHANGED
@@ -5,7 +5,10 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
5
5
|
require 'streamly_ffi/version'
|
6
6
|
|
7
7
|
module StreamlyFFI
|
8
|
-
autoload :
|
8
|
+
autoload :Base, "streamly_ffi/base"
|
9
|
+
autoload :Connection, "streamly_ffi/connection"
|
10
|
+
autoload :Request, "streamly_ffi/request"
|
11
|
+
autoload :PersistentRequest, "streamly_ffi/persistent_request"
|
9
12
|
|
10
13
|
class Error < StandardError; end
|
11
14
|
class UnsupportedProtocol < StandardError; end
|
@@ -117,6 +120,22 @@ module StreamlyFFI
|
|
117
120
|
opts.merge!({:response_body_handler => block}) if block_given?
|
118
121
|
Request.execute(opts)
|
119
122
|
end
|
120
|
-
end
|
121
123
|
|
122
|
-
#
|
124
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
125
|
+
#
|
126
|
+
# Example:
|
127
|
+
# Streamly.delete("www.somehost.com/some_resource/1")
|
128
|
+
#
|
129
|
+
# Streamly.delete("www.somehost.com/some_resource/1") do |chunk|
|
130
|
+
# # do something with _chunk_
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# Parameters:
|
134
|
+
# +url+ should be a String, the url to request
|
135
|
+
# +headers+ should be a Hash and is optional
|
136
|
+
#
|
137
|
+
# This method also accepts a block, which will stream the response body in chunks to the caller
|
138
|
+
def self.connect
|
139
|
+
Connection.new
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module StreamlyFFI
|
2
|
+
module Base
|
3
|
+
alias __method__ method
|
4
|
+
|
5
|
+
attr_accessor :url, :method, :default_write_handler, :default_header_handler
|
6
|
+
|
7
|
+
def execute(options={})
|
8
|
+
set_options(options).perform
|
9
|
+
|
10
|
+
CurlFFI.slist_free_all(@request_headers) if @request_headers
|
11
|
+
|
12
|
+
connection.reset
|
13
|
+
|
14
|
+
resp = if(options.has_key?(:response_header_handler) or options.has_key?(:response_body_handler))
|
15
|
+
nil
|
16
|
+
elsif(options[:method] == :head && response_header.respond_to?(:to_str))
|
17
|
+
response_header
|
18
|
+
elsif(response_body.is_a?(String))
|
19
|
+
response_body
|
20
|
+
else
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
return resp
|
25
|
+
end
|
26
|
+
|
27
|
+
def perform
|
28
|
+
connection.perform
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_options(options={})
|
32
|
+
@url = options[:url] if options.has_key?(:url) # Make sure @url is set, if not
|
33
|
+
@method = options[:method] if options.has_key?(:method) # Make sure @method is set, if not
|
34
|
+
@payload = options[:payload]
|
35
|
+
|
36
|
+
@response_body = nil
|
37
|
+
@response_header = nil
|
38
|
+
@custom_header_handler = nil
|
39
|
+
@custom_write_handler = nil
|
40
|
+
|
41
|
+
# url should be a string that doesn't suck
|
42
|
+
# method should be :post, :get, :put, :delete, :head
|
43
|
+
# options should contain any of the following keys:
|
44
|
+
# :headers, :response_header_handler, :response_body_handler, :payload (required if method = :post / :put)
|
45
|
+
|
46
|
+
case @method
|
47
|
+
when :get then connection.setopt :HTTPGET, 1
|
48
|
+
when :head then connection.setopt :NOBODY, 1
|
49
|
+
when :post then connection.setopt :POST, 1
|
50
|
+
connection.setopt :POSTFIELDS, @payload
|
51
|
+
connection.setopt :POSTFIELDSIZE, @payload.size
|
52
|
+
when :put then connection.setopt :CUSTOMREQUEST, "PUT"
|
53
|
+
connection.setopt :POSTFIELDS, @payload
|
54
|
+
connection.setopt :POSTFIELDSIZE, @payload.size
|
55
|
+
when :delete then connection.setopt :CUSTOMREQUEST, "DELETE"
|
56
|
+
# else I WILL CUT YOU
|
57
|
+
end
|
58
|
+
|
59
|
+
if options.has_key?(:headers) and not options[:headers].nil?
|
60
|
+
options[:headers].each_pair do |key_and_value|
|
61
|
+
self.request_headers = CurlFFI.slist_append(self.request_headers, key_and_value.join(": "))
|
62
|
+
end
|
63
|
+
connection.setopt :HTTPHEADER, @request_headers
|
64
|
+
end
|
65
|
+
|
66
|
+
if options.has_key?(:response_header_handler)
|
67
|
+
@custom_header_handler = options[:response_header_handler]
|
68
|
+
set_header_handler(:custom_header_callback)
|
69
|
+
else
|
70
|
+
set_header_handler
|
71
|
+
end
|
72
|
+
|
73
|
+
if options.has_key?(:response_body_handler)
|
74
|
+
@custom_write_handler = options[:response_body_handler]
|
75
|
+
set_write_handler(:custom_write_callback)
|
76
|
+
else
|
77
|
+
set_write_handler
|
78
|
+
end
|
79
|
+
|
80
|
+
connection.setopt :ENCODING, "identity, deflate, gzip" unless @method == :head
|
81
|
+
connection.setopt :URL, @url
|
82
|
+
|
83
|
+
# Other common options (blame streamly guy)
|
84
|
+
connection.setopt :FOLLOWLOCATION, 1
|
85
|
+
connection.setopt :MAXREDIRS, 3
|
86
|
+
# @TODO: This should be an option
|
87
|
+
connection.setopt :SSL_VERIFYPEER, 0
|
88
|
+
connection.setopt :SSL_VERIFYHOST, 0
|
89
|
+
|
90
|
+
connection.setopt :ERRORBUFFER, self.error_buffer
|
91
|
+
|
92
|
+
return self
|
93
|
+
end
|
94
|
+
|
95
|
+
def connection
|
96
|
+
@connection ||= CurlFFI::Easy.new
|
97
|
+
end
|
98
|
+
|
99
|
+
def error_buffer
|
100
|
+
@error_buffer ||= FFI::MemoryPointer.new(:char, CurlFFI::ERROR_SIZE, :clear)
|
101
|
+
end
|
102
|
+
alias :error :error_buffer
|
103
|
+
|
104
|
+
def request_headers
|
105
|
+
@request_headers ||= FFI::MemoryPointer.from_string("")
|
106
|
+
end
|
107
|
+
|
108
|
+
def response_body
|
109
|
+
@response_body ||= ""
|
110
|
+
end
|
111
|
+
alias :response :response_body
|
112
|
+
alias :body :response_body
|
113
|
+
|
114
|
+
def response_header
|
115
|
+
@response_header ||= ""
|
116
|
+
end
|
117
|
+
alias :headers :response_header
|
118
|
+
|
119
|
+
def set_write_handler(_callback=:default_write_callback)
|
120
|
+
connection.setopt(:WRITEFUNCTION, FFI::Function.new(:size_t, [:pointer, :size_t, :size_t,], &self.__method__(_callback)))
|
121
|
+
end
|
122
|
+
|
123
|
+
def set_header_handler(_callback=:default_header_callback)
|
124
|
+
connection.setopt(:HEADERFUNCTION, FFI::Function.new(:size_t, [:pointer, :size_t, :size_t], &self.__method__(_callback)))
|
125
|
+
end
|
126
|
+
|
127
|
+
def default_write_callback(string_ptr, size, nmemb)
|
128
|
+
length = size * nmemb
|
129
|
+
response_body << string_ptr.read_string(length)
|
130
|
+
|
131
|
+
return length
|
132
|
+
end
|
133
|
+
|
134
|
+
def default_header_callback(string_ptr, size, nmemb)
|
135
|
+
length = size * nmemb
|
136
|
+
response_header << string_ptr.read_string(length)
|
137
|
+
|
138
|
+
return length
|
139
|
+
end
|
140
|
+
|
141
|
+
def custom_write_callback(string_ptr, size, nmemb)
|
142
|
+
length = size * nmemb
|
143
|
+
@custom_write_handler.call(string_ptr.read_string(length))
|
144
|
+
|
145
|
+
return length
|
146
|
+
end
|
147
|
+
|
148
|
+
def custom_header_callback(string_ptr, size, nmemb)
|
149
|
+
length = size * nmemb
|
150
|
+
@custom_header_handler.call(string_ptr.read_string(length))
|
151
|
+
|
152
|
+
return length
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module StreamlyFFI
|
2
|
+
class Connection
|
3
|
+
|
4
|
+
attr_accessor :connection
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
self.connection = StreamlyFFI::PersistentRequest.new
|
8
|
+
end
|
9
|
+
|
10
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# Streamly.head("www.somehost.com/some_resource/1")
|
14
|
+
#
|
15
|
+
# Streamly.head("www.somehost.com/some_resource/1") do |header_chunk|
|
16
|
+
# # do something with _header_chunk_
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# Parameters:
|
20
|
+
# +url+ should be a String, the url to request
|
21
|
+
# +headers+ should be a Hash and is optional
|
22
|
+
#
|
23
|
+
# This method also accepts a block, which will stream the response headers in chunks to the caller
|
24
|
+
def head(url, headers=nil, &block)
|
25
|
+
opts = {:method => :head, :url => url, :headers => headers}
|
26
|
+
opts[:response_header_handler] = block if block_given?
|
27
|
+
self.connection.execute(opts)
|
28
|
+
end
|
29
|
+
|
30
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
31
|
+
#
|
32
|
+
# Example:
|
33
|
+
# Streamly.get("www.somehost.com/some_resource/1")
|
34
|
+
#
|
35
|
+
# Streamly.get("www.somehost.com/some_resource/1") do |chunk|
|
36
|
+
# # do something with _chunk_
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# Parameters:
|
40
|
+
# +url+ should be a String, the url to request
|
41
|
+
# +headers+ should be a Hash and is optional
|
42
|
+
#
|
43
|
+
# This method also accepts a block, which will stream the response body in chunks to the caller
|
44
|
+
def get(url, headers=nil, &block)
|
45
|
+
opts = {:method => :get, :url => url, :headers => headers}
|
46
|
+
opts[:response_body_handler] = block if block_given?
|
47
|
+
self.connection.execute(opts)
|
48
|
+
end
|
49
|
+
|
50
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
51
|
+
#
|
52
|
+
# Example:
|
53
|
+
# Streamly.post("www.somehost.com/some_resource", "asset[id]=2&asset[name]=bar")
|
54
|
+
#
|
55
|
+
# Streamly.post("www.somehost.com/some_resource", "asset[id]=2&asset[name]=bar") do |chunk|
|
56
|
+
# # do something with _chunk_
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# Parameters:
|
60
|
+
# +url+ should be a String (the url to request) and is required
|
61
|
+
# +payload+ should be a String and is required
|
62
|
+
# +headers+ should be a Hash and is optional
|
63
|
+
#
|
64
|
+
# This method also accepts a block, which will stream the response body in chunks to the caller
|
65
|
+
def post(url, payload, headers=nil, &block)
|
66
|
+
opts = {:method => :post, :url => url, :payload => payload, :headers => headers}
|
67
|
+
opts[:response_body_handler] = block if block_given?
|
68
|
+
self.connection.execute(opts)
|
69
|
+
end
|
70
|
+
|
71
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
72
|
+
#
|
73
|
+
# Example:
|
74
|
+
# Streamly.put("www.somehost.com/some_resource/1", "asset[name]=foo")
|
75
|
+
#
|
76
|
+
# Streamly.put("www.somehost.com/some_resource/1", "asset[name]=foo") do |chunk|
|
77
|
+
# # do something with _chunk_
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# Parameters:
|
81
|
+
# +url+ should be a String (the url to request) and is required
|
82
|
+
# +payload+ should be a String and is required
|
83
|
+
# +headers+ should be a Hash and is optional
|
84
|
+
#
|
85
|
+
# This method also accepts a block, which will stream the response body in chunks to the caller
|
86
|
+
def put(url, payload, headers=nil, &block)
|
87
|
+
opts = {:method => :put, :url => url, :payload => payload, :headers => headers}
|
88
|
+
opts[:response_body_handler] = block if block_given?
|
89
|
+
self.connection.execute(opts)
|
90
|
+
end
|
91
|
+
|
92
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
93
|
+
#
|
94
|
+
# Example:
|
95
|
+
# Streamly.delete("www.somehost.com/some_resource/1")
|
96
|
+
#
|
97
|
+
# Streamly.delete("www.somehost.com/some_resource/1") do |chunk|
|
98
|
+
# # do something with _chunk_
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# Parameters:
|
102
|
+
# +url+ should be a String, the url to request
|
103
|
+
# +headers+ should be a Hash and is optional
|
104
|
+
#
|
105
|
+
# This method also accepts a block, which will stream the response body in chunks to the caller
|
106
|
+
def delete(url, headers={}, &block)
|
107
|
+
opts = {:method => :delete, :url => url, :headers => headers}
|
108
|
+
opts[:response_body_handler] = block if block_given?
|
109
|
+
self.connection.execute(opts)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require "curl_ffi"
|
5
|
+
|
6
|
+
module StreamlyFFI
|
7
|
+
class PersistentRequest
|
8
|
+
include StreamlyFFI::Base
|
9
|
+
|
10
|
+
def [](_sym)
|
11
|
+
send _sym
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
data/lib/streamly_ffi/request.rb
CHANGED
@@ -7,157 +7,14 @@ require "singleton"
|
|
7
7
|
module StreamlyFFI
|
8
8
|
class Request
|
9
9
|
include Singleton
|
10
|
+
include StreamlyFFI::Base
|
10
11
|
|
11
|
-
alias __method__ method
|
12
|
-
|
13
|
-
attr_reader :url, :method
|
14
|
-
|
15
|
-
# @TODO: Argumenting Checking + Error Handling
|
16
12
|
def initialize(options={})
|
17
|
-
|
18
|
-
method = options[:method]
|
19
|
-
|
20
|
-
@response_body = nil
|
21
|
-
@response_header = nil
|
22
|
-
@custom_header_handler = nil
|
23
|
-
@custom_write_handler = nil
|
24
|
-
|
25
|
-
# url should be a string that doesn't suck
|
26
|
-
# method should be :post, :get, :put, :delete, :head
|
27
|
-
# options should contain any of the following keys:
|
28
|
-
# :headers, :response_header_handler, :response_body_handler, :payload (required if method = :post / :put)
|
29
|
-
|
30
|
-
case method
|
31
|
-
when :get then connection.setopt :HTTPGET, 1
|
32
|
-
when :head then connection.setopt :NOBODY, 1
|
33
|
-
when :post then connection.setopt :POST, 1
|
34
|
-
connection.setopt :POSTFIELDS, options[:payload]
|
35
|
-
connection.setopt :POSTFIELDSIZE, options[:payload].size
|
36
|
-
when :put then connection.setopt :CUSTOMREQUEST, "PUT"
|
37
|
-
connection.setopt :POSTFIELDS, options[:payload]
|
38
|
-
connection.setopt :POSTFIELDSIZE, options[:payload].size
|
39
|
-
when :delete then connection.setopt :CUSTOMREQUEST, "DELETE"
|
40
|
-
# else I WILL CUT YOU
|
41
|
-
end
|
42
|
-
|
43
|
-
if options[:headers].is_a? Hash and options[:headers].size > 0
|
44
|
-
options[:headers].each_pair do |key_and_value|
|
45
|
-
request_headers = CurlFFI.slist_append(request_headers, key_and_value.join(": "))
|
46
|
-
end
|
47
|
-
connection.setopt :HTTPHEADER, request_headers
|
48
|
-
end
|
49
|
-
|
50
|
-
@custom_header_handler = options[:response_header_handler] if options.has_key?(:response_header_handler)
|
51
|
-
@custom_write_handler = options[:response_body_handler] if options.has_key?(:response_body_handler)
|
52
|
-
|
53
|
-
default_header_handler
|
54
|
-
default_write_handler
|
55
|
-
|
56
|
-
|
57
|
-
connection.setopt :ENCODING, "identity, deflate, gzip" unless method == :head
|
58
|
-
connection.setopt :URL, url
|
59
|
-
|
60
|
-
# Other common options (blame streamly guy)
|
61
|
-
connection.setopt :FOLLOWLOCATION, 1
|
62
|
-
connection.setopt :MAXREDIRS, 3
|
63
|
-
# @TODO: This should be an option
|
64
|
-
connection.setopt :SSL_VERIFYPEER, 0
|
65
|
-
connection.setopt :SSL_VERIFYHOST, 0
|
66
|
-
|
67
|
-
connection.setopt :ERRORBUFFER, error_buffer
|
68
|
-
|
69
|
-
return self # I am a terrible hack. I should abandon the singleton
|
70
|
-
end
|
71
|
-
|
72
|
-
def connection
|
73
|
-
@connection ||= CurlFFI::Easy.new
|
74
|
-
end
|
75
|
-
|
76
|
-
def error_buffer
|
77
|
-
@error_buffer ||= FFI::MemoryPointer.new(:char, CurlFFI::ERROR_SIZE, :clear)
|
13
|
+
self.set_options(options)
|
78
14
|
end
|
79
|
-
|
80
|
-
def request_headers
|
81
|
-
@request_headers ||= FFI::MemoryPointer.from_string("")
|
82
|
-
end
|
83
|
-
|
84
|
-
def response_body
|
85
|
-
@response_body ||= ""
|
86
|
-
end
|
87
|
-
|
88
|
-
def response_header
|
89
|
-
@response_header ||= ""
|
90
|
-
end
|
91
|
-
|
92
|
-
def execute
|
93
|
-
status = connection.perform
|
94
|
-
|
95
|
-
# @TODO: Intelligent error stuff
|
96
|
-
# raise Streamly::Error if status
|
97
15
|
|
98
|
-
CurlFFI.slist_free_all(@request_headers) if @request_headers
|
99
|
-
|
100
|
-
@connection.reset
|
101
|
-
end
|
102
|
-
|
103
16
|
def self.execute(options={})
|
104
|
-
|
105
|
-
|
106
|
-
request.execute
|
107
|
-
|
108
|
-
return nil if(options.has_key?(:response_header_handler) or options.has_key?(:response_body_handler))
|
109
|
-
|
110
|
-
resp = if(options[:method] == :head && request.response_header.respond_to?(:to_str))
|
111
|
-
request.response_header
|
112
|
-
elsif(request.response_body.is_a?(String))
|
113
|
-
request.response_body
|
114
|
-
else
|
115
|
-
nil
|
116
|
-
end
|
117
|
-
|
118
|
-
return resp
|
119
|
-
end
|
120
|
-
|
121
|
-
def default_write_handler
|
122
|
-
connection.setopt(:WRITEFUNCTION, FFI::Function.new(:size_t, [:pointer, :size_t, :size_t,], &self.__method__(:write_callback)))
|
123
|
-
end
|
124
|
-
|
125
|
-
def default_header_handler
|
126
|
-
connection.setopt(:HEADERFUNCTION, FFI::Function.new(:size_t, [:pointer, :size_t, :size_t], &self.__method__(:header_callback)))
|
17
|
+
new(options).execute
|
127
18
|
end
|
128
|
-
|
129
|
-
def write_callback(string_ptr, size, nmemb)
|
130
|
-
length = size * nmemb
|
131
|
-
|
132
|
-
if(@custom_write_handler)
|
133
|
-
@custom_write_handler.call(string_ptr.read_string(length))
|
134
|
-
else
|
135
|
-
response_body << string_ptr.read_string(length)
|
136
|
-
end
|
137
|
-
|
138
|
-
return length
|
139
|
-
end
|
140
|
-
|
141
|
-
def header_callback(string_ptr, size, nmemb)
|
142
|
-
length = size * nmemb
|
143
|
-
|
144
|
-
if(@custom_header_handler)
|
145
|
-
@custom_header_handler.call(string_ptr.read_string(length))
|
146
|
-
else
|
147
|
-
response_header << string_ptr.read_string(length)
|
148
|
-
end
|
149
|
-
|
150
|
-
return length
|
151
|
-
end
|
152
|
-
|
153
|
-
# streamly's .c internal methods:
|
154
|
-
# @TODO: header_handler
|
155
|
-
# @TODO: data_handler
|
156
|
-
# @TODO: each_http_header
|
157
|
-
# @TODO: select_error
|
158
|
-
# @TODO: rb_streamly_new
|
159
|
-
# @TODO: rb_streamly_init
|
160
|
-
# @TODO: nogvl_perform
|
161
|
-
# @TODO: rb_streamly_execute
|
162
19
|
end
|
163
20
|
end
|
data/lib/streamly_ffi/version.rb
CHANGED
data/streamly_ffi.gemspec
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Brian Lopez
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-10 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -56,6 +56,8 @@ files:
|
|
56
56
|
- .gitignore
|
57
57
|
- .rspec
|
58
58
|
- CHANGELOG.md
|
59
|
+
- Gemfile
|
60
|
+
- Gemfile.lock
|
59
61
|
- MIT-LICENSE
|
60
62
|
- README.rdoc
|
61
63
|
- Rakefile
|
@@ -76,6 +78,9 @@ files:
|
|
76
78
|
- ext/streamly.c
|
77
79
|
- ext/streamly.h
|
78
80
|
- lib/streamly_ffi.rb
|
81
|
+
- lib/streamly_ffi/base.rb
|
82
|
+
- lib/streamly_ffi/connection.rb
|
83
|
+
- lib/streamly_ffi/persistent_request.rb
|
79
84
|
- lib/streamly_ffi/request.rb
|
80
85
|
- lib/streamly_ffi/version.rb
|
81
86
|
- spec/server.rb
|