streamly_ffi 0.1.5
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/.gitignore +5 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +18 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +115 -0
- data/Rakefile +43 -0
- data/VERSION.yml +5 -0
- data/benchmark/basic_request.rb +34 -0
- data/benchmark/streaming_json_request.rb +43 -0
- data/examples/basic/delete.rb +9 -0
- data/examples/basic/get.rb +9 -0
- data/examples/basic/head.rb +9 -0
- data/examples/basic/post.rb +11 -0
- data/examples/basic/put.rb +11 -0
- data/examples/streaming/delete.rb +13 -0
- data/examples/streaming/get.rb +13 -0
- data/examples/streaming/head.rb +13 -0
- data/examples/streaming/post.rb +15 -0
- data/examples/streaming/put.rb +16 -0
- data/ext/extconf.rb +28 -0
- data/ext/streamly.c +427 -0
- data/ext/streamly.h +66 -0
- data/lib/streamly_ffi.rb +122 -0
- data/lib/streamly_ffi/request.rb +163 -0
- data/lib/streamly_ffi/version.rb +3 -0
- data/spec/server.rb +18 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/streamly_ffi/request_spec.rb +293 -0
- data/streamly_ffi.gemspec +41 -0
- metadata +96 -0
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 0.1.4 (September 2nd, 2010)
|
4
|
+
* Streamly now respects Encoding.default_internal on 1.9
|
5
|
+
* fixed a random segfault when applying a NULL auth field
|
6
|
+
* take advantage of rb_thread_blocking_region on 1.9 and emulate it's behavior on 1.8 for Ruby-aware thread-saftey
|
7
|
+
|
8
|
+
## 0.1.3 (August 19th, 2009)
|
9
|
+
* Fixed a bug where a username or password was specified, but not both
|
10
|
+
|
11
|
+
## 0.1.2 (July 28th, 2009)
|
12
|
+
* removing call to set CURLOPT_USERPWD to NULL as it would crash in linux
|
13
|
+
|
14
|
+
## 0.1.1 (July 27th, 2009)
|
15
|
+
* Version bump for Github's gem builder
|
16
|
+
|
17
|
+
## 0.1.0 (July 27th, 2009)
|
18
|
+
* Initial release
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008-2009 Brian Lopez - http://github.com/brianmario
|
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.
|
data/README.rdoc
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
= A streaming REST client for Ruby that uses libcurl
|
2
|
+
|
3
|
+
== Features
|
4
|
+
* rest-client like API
|
5
|
+
* Streaming API allows the caller to be handed chunks of the response while it's being received
|
6
|
+
* uses Encoding.default_internal (otherwise falls back to utf-8) for strings it hands back in 1.9
|
7
|
+
|
8
|
+
== How to install
|
9
|
+
|
10
|
+
Nothing special about it, just:
|
11
|
+
|
12
|
+
sudo gem install streamly
|
13
|
+
|
14
|
+
== Example of use
|
15
|
+
|
16
|
+
=== A basic HEAD request
|
17
|
+
|
18
|
+
Streamly.head 'www.somehost.com'
|
19
|
+
|
20
|
+
Or streaming
|
21
|
+
|
22
|
+
Streamly.head 'www.somehost.com' do |header_chunk|
|
23
|
+
# do something with header_chunk
|
24
|
+
end
|
25
|
+
|
26
|
+
You can also pass a Hash of headers
|
27
|
+
|
28
|
+
Streamly.head 'www.somehost.com', {"User-Agent" => "Your Mom"}
|
29
|
+
|
30
|
+
=== A basic GET request
|
31
|
+
|
32
|
+
Streamly.get 'www.somehost.com'
|
33
|
+
|
34
|
+
Or streaming
|
35
|
+
|
36
|
+
Streamly.get 'www.somehost.com' do |body_chunk|
|
37
|
+
# do something with body_chunk
|
38
|
+
end
|
39
|
+
|
40
|
+
You can also pass a Hash of headers
|
41
|
+
|
42
|
+
Streamly.get 'www.somehost.com', {"User-Agent" => "Your Mom"}
|
43
|
+
|
44
|
+
=== A basic POST request
|
45
|
+
|
46
|
+
Streamly.post 'www.somehost.com', 'blah=foo'
|
47
|
+
|
48
|
+
Or streaming
|
49
|
+
|
50
|
+
Streamly.post 'www.somehost.com', 'blah=foo' do |body_chunk|
|
51
|
+
# do something with body_chunk
|
52
|
+
end
|
53
|
+
|
54
|
+
You can also pass a Hash of headers
|
55
|
+
|
56
|
+
Streamly.post 'www.somehost.com', 'blah=foo', {"User-Agent" => "Your Mom"}
|
57
|
+
|
58
|
+
=== A basic PUT request
|
59
|
+
|
60
|
+
Streamly.put 'www.somehost.com', 'blah=foo'
|
61
|
+
|
62
|
+
Or streaming
|
63
|
+
|
64
|
+
Streamly.put 'www.somehost.com', 'blah=foo' do |body_chunk|
|
65
|
+
# do something with body_chunk
|
66
|
+
end
|
67
|
+
|
68
|
+
You can also pass a Hash of headers
|
69
|
+
|
70
|
+
Streamly.put 'www.somehost.com', 'blah=foo', {"User-Agent" => "Your Mom"}
|
71
|
+
|
72
|
+
=== A basic DELETE request
|
73
|
+
|
74
|
+
Streamly.delete 'www.somehost.com'
|
75
|
+
|
76
|
+
Or streaming
|
77
|
+
|
78
|
+
Streamly.delete 'www.somehost.com' do |body_chunk|
|
79
|
+
# do something with body_chunk
|
80
|
+
end
|
81
|
+
|
82
|
+
You can also pass a Hash of headers
|
83
|
+
|
84
|
+
Streamly.delete 'www.somehost.com', {"User-Agent" => "Your Mom"}
|
85
|
+
|
86
|
+
== Benchmarks
|
87
|
+
|
88
|
+
Fetching 2,405,005 bytes of JSON from a local lighttpd server
|
89
|
+
|
90
|
+
* Streamly: 0.011s
|
91
|
+
* Shell out to curl: 0.046s
|
92
|
+
* rest-client: 0.205s
|
93
|
+
|
94
|
+
Streaming, and parsing 2,405,005 bytes of JSON from a local lighttpd server
|
95
|
+
|
96
|
+
* Streamly: 0.231s
|
97
|
+
* Shell out to curl: 0.341s
|
98
|
+
* rest-client: 0.447s
|
99
|
+
|
100
|
+
== Other Notes
|
101
|
+
|
102
|
+
This library was basically an exercise in dealing with libcurl in C.
|
103
|
+
|
104
|
+
== Special Thanks
|
105
|
+
|
106
|
+
There are quite a few *extremely* nice REST client libraries out there for Ruby today. I especially owe thanks
|
107
|
+
to the following projects. Without them I probably would have never had the inspiration to even take the time
|
108
|
+
to write this library. In Streamly, you'll find snippets of code, API patterns and examples from all 3 of these projects.
|
109
|
+
I'll do my best to make sure I give credit where it's due *in* the source. Please let me know if I've missed something!
|
110
|
+
|
111
|
+
* rest-client - https://github.com/adamwiggins/rest-client
|
112
|
+
* curb - https://github.com/taf2/curb
|
113
|
+
* patron - https://github.com/toland/patron
|
114
|
+
|
115
|
+
And again, the Github crew for this amazing service!
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
gemspec = eval File.read('streamly_ffi.gemspec')
|
6
|
+
|
7
|
+
# Gem packaging tasks
|
8
|
+
Rake::GemPackageTask.new(gemspec) do |pkg|
|
9
|
+
pkg.need_zip = false
|
10
|
+
pkg.need_tar = false
|
11
|
+
end
|
12
|
+
|
13
|
+
task :gem => :gemspec
|
14
|
+
|
15
|
+
desc %{Build the gemspec file.}
|
16
|
+
task :gemspec do
|
17
|
+
gemspec.validate
|
18
|
+
end
|
19
|
+
|
20
|
+
desc %{Release the gem to RubyGems.org}
|
21
|
+
task :release => :gem do
|
22
|
+
system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rspec/core'
|
26
|
+
require 'rspec/core/rake_task'
|
27
|
+
|
28
|
+
desc "Run all examples with RCov"
|
29
|
+
Rspec::Core::RakeTask.new('spec:rcov') do |t|
|
30
|
+
#Spec::Rake::SpecTask.new('spec:rcov') do |t|
|
31
|
+
t.pattern = "spec/requests/**/*_spec.rb"
|
32
|
+
t.rcov = true
|
33
|
+
t.rcov_opts = lambda do
|
34
|
+
IO.readlines("spec/rcov.opts").map {|line|
|
35
|
+
line.chomp.split " "
|
36
|
+
}.flatten
|
37
|
+
end
|
38
|
+
end
|
39
|
+
Rspec::Core::RakeTask.new(:spec) do |t|
|
40
|
+
#Spec::Rake::SpecTask.new('spec') do |t|
|
41
|
+
t.pattern = "spec/streamly_ffi/**/*_spec.rb"
|
42
|
+
# t.opts << '--options' << 'spec/spec.opts'
|
43
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
|
3
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'net/http'
|
7
|
+
require 'rest_client'
|
8
|
+
require 'streamly'
|
9
|
+
require 'benchmark'
|
10
|
+
|
11
|
+
url = ARGV[0]
|
12
|
+
|
13
|
+
Benchmark.bmbm do |x|
|
14
|
+
x.report do
|
15
|
+
puts "Streamly"
|
16
|
+
(ARGV[1] || 1).to_i.times do
|
17
|
+
Streamly.get(url)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
x.report do
|
22
|
+
puts "Shell out to curl"
|
23
|
+
(ARGV[1] || 1).to_i.times do
|
24
|
+
`curl -s --compressed #{url}`
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
x.report do
|
29
|
+
puts "rest-client"
|
30
|
+
(ARGV[1] || 1).to_i.times do
|
31
|
+
RestClient.get(url, {"Accept-Encoding" => "identity, deflate, gzip"})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
|
3
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'net/http'
|
7
|
+
require 'rest_client'
|
8
|
+
require 'streamly'
|
9
|
+
require 'yajl'
|
10
|
+
require 'benchmark'
|
11
|
+
|
12
|
+
url = ARGV[0]
|
13
|
+
|
14
|
+
Benchmark.bmbm do |x|
|
15
|
+
parser = Yajl::Parser.new
|
16
|
+
parser.on_parse_complete = lambda {|obj| }
|
17
|
+
x.report do
|
18
|
+
puts "Streamly"
|
19
|
+
(ARGV[1] || 1).to_i.times do
|
20
|
+
Streamly.get(url) do |chunk|
|
21
|
+
parser << chunk
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
parser = Yajl::Parser.new
|
27
|
+
parser.on_parse_complete = lambda {|obj| }
|
28
|
+
x.report do
|
29
|
+
puts "Shell out to curl"
|
30
|
+
(ARGV[1] || 1).to_i.times do
|
31
|
+
parser.parse `curl -s --compressed #{url}`
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
parser = Yajl::Parser.new
|
36
|
+
parser.on_parse_complete = lambda {|obj| }
|
37
|
+
x.report do
|
38
|
+
puts "rest-client"
|
39
|
+
(ARGV[1] || 1).to_i.times do
|
40
|
+
parser.parse RestClient.get(url, {"Accept-Encoding" => "identity, deflate, gzip"})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
|
4
|
+
require 'streamly'
|
5
|
+
|
6
|
+
raise Exception, "You must pass a URL to request" if ARGV[0].nil?
|
7
|
+
raise Exception, "You must pass a payload to POST" if ARGV[1].nil?
|
8
|
+
|
9
|
+
url = ARGV[0]
|
10
|
+
payload = ARGV[1]
|
11
|
+
puts Streamly.post(url, payload)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
|
4
|
+
require 'streamly'
|
5
|
+
|
6
|
+
raise Exception, "You must pass a URL to request" if ARGV[0].nil?
|
7
|
+
raise Exception, "You must pass a payload to PUT" if ARGV[1].nil?
|
8
|
+
|
9
|
+
url = ARGV[0]
|
10
|
+
payload = ARGV[1]
|
11
|
+
puts Streamly.put(url, payload)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
|
4
|
+
require 'streamly'
|
5
|
+
|
6
|
+
raise Exception, "You must pass a URL to request" if ARGV[0].nil?
|
7
|
+
|
8
|
+
url = ARGV[0]
|
9
|
+
Streamly.delete(url) do |chunk|
|
10
|
+
STDOUT.write chunk
|
11
|
+
STDOUT.flush
|
12
|
+
end
|
13
|
+
puts
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
|
4
|
+
require 'streamly'
|
5
|
+
|
6
|
+
raise Exception, "You must pass a URL to request" if ARGV[0].nil?
|
7
|
+
|
8
|
+
url = ARGV[0]
|
9
|
+
Streamly.get(url) do |chunk|
|
10
|
+
STDOUT.write chunk
|
11
|
+
STDOUT.flush
|
12
|
+
end
|
13
|
+
puts
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
|
4
|
+
require 'streamly'
|
5
|
+
|
6
|
+
raise Exception, "You must pass a URL to request" if ARGV[0].nil?
|
7
|
+
|
8
|
+
url = ARGV[0]
|
9
|
+
Streamly.head(url) do |chunk|
|
10
|
+
STDOUT.write chunk
|
11
|
+
STDOUT.flush
|
12
|
+
end
|
13
|
+
puts
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
|
4
|
+
require 'streamly'
|
5
|
+
|
6
|
+
raise Exception, "You must pass a URL to request" if ARGV[0].nil?
|
7
|
+
raise Exception, "You must pass a payload to POST" if ARGV[1].nil?
|
8
|
+
|
9
|
+
url = ARGV[0]
|
10
|
+
payload = ARGV[1]
|
11
|
+
Streamly.post(url, payload) do |chunk|
|
12
|
+
STDOUT.write chunk
|
13
|
+
STDOUT.flush
|
14
|
+
end
|
15
|
+
puts
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
3
|
+
|
4
|
+
require 'streamly'
|
5
|
+
|
6
|
+
raise Exception, "You must pass a URL to request" if ARGV[0].nil?
|
7
|
+
raise Exception, "You must pass a payload to PUT" if ARGV[1].nil?
|
8
|
+
|
9
|
+
url = ARGV[0]
|
10
|
+
payload = ARGV[1]
|
11
|
+
resp = ''
|
12
|
+
Streamly.put(url, payload) do |chunk|
|
13
|
+
STDOUT.write chunk
|
14
|
+
STDOUT.flush
|
15
|
+
end
|
16
|
+
puts
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'mkmf'
|
3
|
+
require 'rbconfig'
|
4
|
+
|
5
|
+
# 1.9-only
|
6
|
+
have_func('rb_thread_blocking_region')
|
7
|
+
|
8
|
+
$CFLAGS << ' -DHAVE_RBTRAP' if have_var('rb_trap_immediate', ['ruby.h', 'rubysig.h'])
|
9
|
+
# add_define 'HAVE_RBTRAP' if have_var('rb_trap_immediate', ['ruby.h', 'rubysig.h'])
|
10
|
+
|
11
|
+
# Borrowed from taf2-curb
|
12
|
+
dir_config('curl')
|
13
|
+
if find_executable('curl-config')
|
14
|
+
$CFLAGS << " #{`curl-config --cflags`.strip}"
|
15
|
+
$LIBS << " #{`curl-config --libs`.strip}"
|
16
|
+
elsif !have_library('curl') or !have_header('curl/curl.h')
|
17
|
+
fail <<-EOM
|
18
|
+
Can't find libcurl or curl/curl.h
|
19
|
+
|
20
|
+
Try passing --with-curl-dir or --with-curl-lib and --with-curl-include
|
21
|
+
options to extconf.
|
22
|
+
EOM
|
23
|
+
end
|
24
|
+
|
25
|
+
$CFLAGS << ' -Wall -Wextra -funroll-loops'
|
26
|
+
# $CFLAGS << ' -O0 -ggdb'
|
27
|
+
|
28
|
+
create_makefile("streamly_ext")
|