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/lib/streamly_ffi.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
# encoding: UTF-8
|
5
|
+
require 'streamly_ffi/version'
|
6
|
+
|
7
|
+
module StreamlyFFI
|
8
|
+
autoload :Request, "streamly_ffi/request"
|
9
|
+
|
10
|
+
class Error < StandardError; end
|
11
|
+
class UnsupportedProtocol < StandardError; end
|
12
|
+
class URLFormatError < StandardError; end
|
13
|
+
class HostResolutionError < StandardError; end
|
14
|
+
class ConnectionFailed < StandardError; end
|
15
|
+
class PartialFileError < StandardError; end
|
16
|
+
class TimeoutError < StandardError; end
|
17
|
+
class TooManyRedirects < StandardError; end
|
18
|
+
|
19
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
# Streamly.head("www.somehost.com/some_resource/1")
|
23
|
+
#
|
24
|
+
# Streamly.head("www.somehost.com/some_resource/1") do |header_chunk|
|
25
|
+
# # do something with _header_chunk_
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Parameters:
|
29
|
+
# +url+ should be a String, the url to request
|
30
|
+
# +headers+ should be a Hash and is optional
|
31
|
+
#
|
32
|
+
# This method also accepts a block, which will stream the response headers in chunks to the caller
|
33
|
+
def self.head(url, headers=nil, &block)
|
34
|
+
opts = {:method => :head, :url => url, :headers => headers}
|
35
|
+
opts.merge!({:response_header_handler => block}) if block_given?
|
36
|
+
Request.execute(opts)
|
37
|
+
end
|
38
|
+
|
39
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
40
|
+
#
|
41
|
+
# Example:
|
42
|
+
# Streamly.get("www.somehost.com/some_resource/1")
|
43
|
+
#
|
44
|
+
# Streamly.get("www.somehost.com/some_resource/1") do |chunk|
|
45
|
+
# # do something with _chunk_
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# Parameters:
|
49
|
+
# +url+ should be a String, the url to request
|
50
|
+
# +headers+ should be a Hash and is optional
|
51
|
+
#
|
52
|
+
# This method also accepts a block, which will stream the response body in chunks to the caller
|
53
|
+
def self.get(url, headers=nil, &block)
|
54
|
+
opts = {:method => :get, :url => url, :headers => headers}
|
55
|
+
opts.merge!({:response_body_handler => block}) if block_given?
|
56
|
+
Request.execute(opts)
|
57
|
+
end
|
58
|
+
|
59
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
60
|
+
#
|
61
|
+
# Example:
|
62
|
+
# Streamly.post("www.somehost.com/some_resource", "asset[id]=2&asset[name]=bar")
|
63
|
+
#
|
64
|
+
# Streamly.post("www.somehost.com/some_resource", "asset[id]=2&asset[name]=bar") do |chunk|
|
65
|
+
# # do something with _chunk_
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# Parameters:
|
69
|
+
# +url+ should be a String (the url to request) and is required
|
70
|
+
# +payload+ should be a String and is required
|
71
|
+
# +headers+ should be a Hash and is optional
|
72
|
+
#
|
73
|
+
# This method also accepts a block, which will stream the response body in chunks to the caller
|
74
|
+
def self.post(url, payload, headers=nil, &block)
|
75
|
+
opts = {:method => :post, :url => url, :payload => payload, :headers => headers}
|
76
|
+
opts.merge!({:response_body_handler => block}) if block_given?
|
77
|
+
Request.execute(opts)
|
78
|
+
end
|
79
|
+
|
80
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
81
|
+
#
|
82
|
+
# Example:
|
83
|
+
# Streamly.put("www.somehost.com/some_resource/1", "asset[name]=foo")
|
84
|
+
#
|
85
|
+
# Streamly.put("www.somehost.com/some_resource/1", "asset[name]=foo") do |chunk|
|
86
|
+
# # do something with _chunk_
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# Parameters:
|
90
|
+
# +url+ should be a String (the url to request) and is required
|
91
|
+
# +payload+ should be a String and is required
|
92
|
+
# +headers+ should be a Hash and is optional
|
93
|
+
#
|
94
|
+
# This method also accepts a block, which will stream the response body in chunks to the caller
|
95
|
+
def self.put(url, payload, headers=nil, &block)
|
96
|
+
opts = {:method => :put, :url => url, :payload => payload, :headers => headers}
|
97
|
+
opts.merge!({:response_body_handler => block}) if block_given?
|
98
|
+
Request.execute(opts)
|
99
|
+
end
|
100
|
+
|
101
|
+
# A helper method to make HEAD requests a dead-simple one-liner
|
102
|
+
#
|
103
|
+
# Example:
|
104
|
+
# Streamly.delete("www.somehost.com/some_resource/1")
|
105
|
+
#
|
106
|
+
# Streamly.delete("www.somehost.com/some_resource/1") do |chunk|
|
107
|
+
# # do something with _chunk_
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# Parameters:
|
111
|
+
# +url+ should be a String, the url to request
|
112
|
+
# +headers+ should be a Hash and is optional
|
113
|
+
#
|
114
|
+
# This method also accepts a block, which will stream the response body in chunks to the caller
|
115
|
+
def self.delete(url, headers={}, &block)
|
116
|
+
opts = {:method => :delete, :url => url, :headers => headers}
|
117
|
+
opts.merge!({:response_body_handler => block}) if block_given?
|
118
|
+
Request.execute(opts)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# require "streamly/request" # May need to do this? Not sure how autoload works with FFI yet
|
@@ -0,0 +1,163 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require "curl_ffi"
|
5
|
+
require "singleton"
|
6
|
+
|
7
|
+
module StreamlyFFI
|
8
|
+
class Request
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
alias __method__ method
|
12
|
+
|
13
|
+
attr_reader :url, :method
|
14
|
+
|
15
|
+
# @TODO: Argumenting Checking + Error Handling
|
16
|
+
def initialize(options={})
|
17
|
+
url = options[:url]
|
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)
|
78
|
+
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
|
+
|
98
|
+
CurlFFI.slist_free_all(@request_headers) if @request_headers
|
99
|
+
|
100
|
+
@connection.reset
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.execute(options={})
|
104
|
+
request = new(options)
|
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)))
|
127
|
+
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
|
+
end
|
163
|
+
end
|
data/spec/server.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
|
4
|
+
get '/' do
|
5
|
+
"Hello, #{params[:name]}".strip
|
6
|
+
end
|
7
|
+
|
8
|
+
post '/' do
|
9
|
+
"Hello, #{params[:name]}".strip
|
10
|
+
end
|
11
|
+
|
12
|
+
put '/' do
|
13
|
+
"Hello, #{params[:name]}".strip
|
14
|
+
end
|
15
|
+
|
16
|
+
delete '/' do
|
17
|
+
"Hello, #{params[:name]}".strip
|
18
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,293 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
3
|
+
|
4
|
+
describe StreamlyFFI::Request do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
@response = "Hello, brian".strip
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "HEAD" do
|
11
|
+
describe "basic" do
|
12
|
+
it "should perform a basic request" do
|
13
|
+
resp = Streamly.head('localhost:4567')
|
14
|
+
resp.should_not be_nil
|
15
|
+
end
|
16
|
+
=begin
|
17
|
+
if RUBY_VERSION =~ /^1.9/
|
18
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
19
|
+
Encoding.default_internal = nil
|
20
|
+
Streamly.head('localhost:4567').encoding.should eql(Encoding.find('utf-8'))
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should use Encoding.default_internal" do
|
24
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
25
|
+
Streamly.head('localhost:4567').encoding.should eql(Encoding.default_internal)
|
26
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
27
|
+
Streamly.head('localhost:4567').encoding.should eql(Encoding.default_internal)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
=end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "streaming" do
|
34
|
+
it "should perform a basic request and stream header chunks to the caller" do
|
35
|
+
streamed_response = ""
|
36
|
+
resp = Streamly.head('localhost:4567') do |chunk|
|
37
|
+
chunk.should_not be_empty
|
38
|
+
streamed_response << chunk
|
39
|
+
end
|
40
|
+
resp.should be_nil
|
41
|
+
streamed_response.should_not be_nil
|
42
|
+
end
|
43
|
+
=begin
|
44
|
+
if RUBY_VERSION =~ /^1.9/
|
45
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
46
|
+
Encoding.default_internal = nil
|
47
|
+
Streamly.head('localhost:4567') do |chunk|
|
48
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should use Encoding.default_internal" do
|
53
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
54
|
+
Streamly.head('localhost:4567') do |chunk|
|
55
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
56
|
+
end
|
57
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
58
|
+
Streamly.head('localhost:4567') do |chunk|
|
59
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
=end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "GET" do
|
68
|
+
describe "basic" do
|
69
|
+
it "should perform a basic request" do
|
70
|
+
resp = Streamly.get('localhost:4567/?name=brian')
|
71
|
+
resp.should eql(@response)
|
72
|
+
end
|
73
|
+
=begin
|
74
|
+
if RUBY_VERSION =~ /^1.9/
|
75
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
76
|
+
Encoding.default_internal = nil
|
77
|
+
Streamly.get('localhost:4567').encoding.should eql(Encoding.find('utf-8'))
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should use Encoding.default_internal" do
|
81
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
82
|
+
Streamly.get('localhost:4567').encoding.should eql(Encoding.default_internal)
|
83
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
84
|
+
Streamly.get('localhost:4567').encoding.should eql(Encoding.default_internal)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
=end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "streaming" do
|
91
|
+
it "should perform a basic request and stream the response to the caller" do
|
92
|
+
streamed_response = ''
|
93
|
+
resp = Streamly.get('localhost:4567/?name=brian') do |chunk|
|
94
|
+
chunk.should_not be_empty
|
95
|
+
streamed_response << chunk
|
96
|
+
end
|
97
|
+
resp.should be_nil
|
98
|
+
streamed_response.should eql(@response)
|
99
|
+
end
|
100
|
+
=begin
|
101
|
+
if RUBY_VERSION =~ /^1.9/
|
102
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
103
|
+
Encoding.default_internal = nil
|
104
|
+
Streamly.get('localhost:4567') do |chunk|
|
105
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should use Encoding.default_internal" do
|
110
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
111
|
+
Streamly.get('localhost:4567') do |chunk|
|
112
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
113
|
+
end
|
114
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
115
|
+
Streamly.get('localhost:4567') do |chunk|
|
116
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
=end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "POST" do
|
125
|
+
describe "basic" do
|
126
|
+
it "should perform a basic request" do
|
127
|
+
resp = Streamly.post('localhost:4567', 'name=brian')
|
128
|
+
resp.should eql(@response)
|
129
|
+
end
|
130
|
+
=begin
|
131
|
+
if RUBY_VERSION =~ /^1.9/
|
132
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
133
|
+
Encoding.default_internal = nil
|
134
|
+
Streamly.post('localhost:4567', 'name=brian').encoding.should eql(Encoding.find('utf-8'))
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should use Encoding.default_internal" do
|
138
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
139
|
+
Streamly.post('localhost:4567', 'name=brian').encoding.should eql(Encoding.default_internal)
|
140
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
141
|
+
Streamly.post('localhost:4567', 'name=brian').encoding.should eql(Encoding.default_internal)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
=end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "streaming" do
|
148
|
+
it "should perform a basic request and stream the response to the caller" do
|
149
|
+
streamed_response = ''
|
150
|
+
resp = Streamly.post('localhost:4567', 'name=brian') do |chunk|
|
151
|
+
chunk.should_not be_empty
|
152
|
+
streamed_response << chunk
|
153
|
+
end
|
154
|
+
resp.should be_nil
|
155
|
+
streamed_response.should eql(@response)
|
156
|
+
end
|
157
|
+
=begin
|
158
|
+
if RUBY_VERSION =~ /^1.9/
|
159
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
160
|
+
Encoding.default_internal = nil
|
161
|
+
Streamly.post('localhost:4567', 'name=brian') do |chunk|
|
162
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should use Encoding.default_internal" do
|
167
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
168
|
+
Streamly.post('localhost:4567', 'name=brian') do |chunk|
|
169
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
170
|
+
end
|
171
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
172
|
+
Streamly.post('localhost:4567', 'name=brian') do |chunk|
|
173
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
=end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "PUT" do
|
182
|
+
describe "basic" do
|
183
|
+
it "should perform a basic request" do
|
184
|
+
resp = Streamly.put('localhost:4567', 'name=brian')
|
185
|
+
resp.should eql(@response)
|
186
|
+
end
|
187
|
+
=begin
|
188
|
+
if RUBY_VERSION =~ /^1.9/
|
189
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
190
|
+
Encoding.default_internal = nil
|
191
|
+
Streamly.put('localhost:4567', 'name=brian').encoding.should eql(Encoding.find('utf-8'))
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should use Encoding.default_internal" do
|
195
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
196
|
+
Streamly.put('localhost:4567', 'name=brian').encoding.should eql(Encoding.default_internal)
|
197
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
198
|
+
Streamly.put('localhost:4567', 'name=brian').encoding.should eql(Encoding.default_internal)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
=end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "streaming" do
|
205
|
+
it "should perform a basic request and stream the response to the caller" do
|
206
|
+
streamed_response = ''
|
207
|
+
resp = Streamly.put('localhost:4567', 'name=brian') do |chunk|
|
208
|
+
chunk.should_not be_empty
|
209
|
+
streamed_response << chunk
|
210
|
+
end
|
211
|
+
resp.should be_nil
|
212
|
+
streamed_response.should eql(@response)
|
213
|
+
end
|
214
|
+
=begin
|
215
|
+
if RUBY_VERSION =~ /^1.9/
|
216
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
217
|
+
Encoding.default_internal = nil
|
218
|
+
Streamly.put('localhost:4567', 'name=brian') do |chunk|
|
219
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should use Encoding.default_internal" do
|
224
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
225
|
+
Streamly.put('localhost:4567', 'name=brian') do |chunk|
|
226
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
227
|
+
end
|
228
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
229
|
+
Streamly.put('localhost:4567', 'name=brian') do |chunk|
|
230
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
=end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "DELETE" do
|
239
|
+
describe "basic" do
|
240
|
+
it "should perform a basic request" do
|
241
|
+
resp = Streamly.delete('localhost:4567/?name=brian').should eql(@response)
|
242
|
+
end
|
243
|
+
=begin
|
244
|
+
if RUBY_VERSION =~ /^1.9/
|
245
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
246
|
+
Encoding.default_internal = nil
|
247
|
+
Streamly.delete('localhost:4567/?name=brian').encoding.should eql(Encoding.find('utf-8'))
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should use Encoding.default_internal" do
|
251
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
252
|
+
Streamly.delete('localhost:4567/?name=brian').encoding.should eql(Encoding.default_internal)
|
253
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
254
|
+
Streamly.delete('localhost:4567/?name=brian').encoding.should eql(Encoding.default_internal)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
=end
|
258
|
+
end
|
259
|
+
|
260
|
+
describe "streaming" do
|
261
|
+
it "should perform a basic request and stream the response to the caller" do
|
262
|
+
streamed_response = ''
|
263
|
+
resp = Streamly.delete('localhost:4567/?name=brian') do |chunk|
|
264
|
+
chunk.should_not be_empty
|
265
|
+
streamed_response << chunk
|
266
|
+
end
|
267
|
+
resp.should be_nil
|
268
|
+
streamed_response.should eql(@response)
|
269
|
+
end
|
270
|
+
=begin
|
271
|
+
if RUBY_VERSION =~ /^1.9/
|
272
|
+
it "should default to utf-8 if Encoding.default_internal is nil" do
|
273
|
+
Encoding.default_internal = nil
|
274
|
+
Streamly.delete('localhost:4567/?name=brian') do |chunk|
|
275
|
+
chunk.encoding.should eql(Encoding.find('utf-8'))
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should use Encoding.default_internal" do
|
280
|
+
Encoding.default_internal = Encoding.find('utf-8')
|
281
|
+
Streamly.delete('localhost:4567/?name=brian') do |chunk|
|
282
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
283
|
+
end
|
284
|
+
Encoding.default_internal = Encoding.find('us-ascii')
|
285
|
+
Streamly.delete('localhost:4567/?name=brian') do |chunk|
|
286
|
+
chunk.encoding.should eql(Encoding.default_internal)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
=end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|