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
         |