lib/streamly_ffi/base.rb in streamly_ffi-0.2.4 vs lib/streamly_ffi/base.rb in streamly_ffi-0.2.6

- old
+ new

@@ -2,17 +2,18 @@ module Base alias __method__ method attr_accessor :url, :method, :default_write_handler, :default_header_handler + DEFAULT_CURL_ENCODING = "identity, deflate, gzip" + def execute(options={}) + connection.reset set_options(options).perform CurlFFI.slist_free_all(@request_headers) if @request_headers - connection.reset - resp = if(options.has_key?(:response_header_handler) or options.has_key?(:response_body_handler)) nil elsif(options[:method] == :head && response_header.respond_to?(:to_str)) response_header elsif(response_body.is_a?(String)) @@ -26,14 +27,33 @@ def perform connection.perform end + # Set/add request headers in Curl's slist + # @param [Hash, Array<Hash>, Set<Hash>] headers Any number of headers to be added to curl's slist. Ultimate form + # must be a Hash; multiple Hashes with the same key (and different value) can be placed in an Array, if desired. + def set_headers(headers) + case headers + when Hash + headers.each_pair do |k_v| + self.request_headers = CurlFFI.slist_append(self.request_headers, k_v.join(": ")) + end + when Array, Set + headers.each do |header| + header.each_pair do |k_v| + self.request_headers = CurlFFI.slist_append(self.request_headers, k_v.join(": ")) + end + end + end + return self.request_headers + end # def set_headers + def set_options(options={}) - @url = options[:url] if options.has_key?(:url) # Make sure @url is set, if not - @method = options[:method] if options.has_key?(:method) # Make sure @method is set, if not - @payload = options[:payload] + @url = options[:url].dup if options.has_key?(:url) # Make sure @url is set, if not + @method = options[:method] if options.has_key?(:method) # Make sure @method is set, if not + @payload = options[:payload].dup if options.has_key?(:payload) @response_body = nil @response_header = nil @custom_header_handler = nil @custom_write_handler = nil @@ -54,32 +74,31 @@ connection.setopt :POSTFIELDSIZE, @payload.size when :delete then connection.setopt :CUSTOMREQUEST, "DELETE" # else I WILL CUT YOU end - if options.has_key?(:headers) and not options[:headers].nil? - options[:headers].each_pair do |key_and_value| - self.request_headers = CurlFFI.slist_append(self.request_headers, key_and_value.join(": ")) - end - connection.setopt :HTTPHEADER, @request_headers + if options.has_key?(:headers) + connection.setopt(:HTTPHEADER, set_headers(options[:headers])) unless options[:headers].nil? end if options.has_key?(:response_header_handler) @custom_header_handler = options[:response_header_handler] set_header_handler(:custom_header_callback) else + @response_header = "" set_header_handler end if options.has_key?(:response_body_handler) @custom_write_handler = options[:response_body_handler] set_write_handler(:custom_write_callback) else + @response_body = "" set_write_handler end - connection.setopt :ENCODING, "identity, deflate, gzip" unless @method == :head + connection.setopt :ENCODING, DEFAULT_CURL_ENCODING unless @method == :head connection.setopt :URL, @url # Other common options (blame streamly guy) connection.setopt :FOLLOWLOCATION, 1 connection.setopt :MAXREDIRS, 3 @@ -100,11 +119,11 @@ @error_buffer ||= FFI::MemoryPointer.new(:char, CurlFFI::ERROR_SIZE, :clear) end alias :error :error_buffer def request_headers - @request_headers ||= FFI::MemoryPointer.from_string("") + @request_headers ||= FFI::MemoryPointer.new(:pointer) end def response_body @response_body ||= "" end @@ -115,40 +134,45 @@ @response_header ||= "" end alias :headers :response_header def set_write_handler(_callback=:default_write_callback) - connection.setopt(:WRITEFUNCTION, FFI::Function.new(:size_t, [:pointer, :size_t, :size_t,], &self.__method__(_callback))) + @_write_handler = FFI::Function.new(:size_t, [:pointer, :size_t, :size_t,], &self.__method__(_callback)) + + connection.setopt(:WRITEFUNCTION, @_write_handler) end def set_header_handler(_callback=:default_header_callback) - connection.setopt(:HEADERFUNCTION, FFI::Function.new(:size_t, [:pointer, :size_t, :size_t], &self.__method__(_callback))) + @_header_handler = FFI::Function.new(:size_t, [:pointer, :size_t, :size_t], &self.__method__(_callback)) + connection.setopt(:HEADERFUNCTION, @_header_handler) end def default_write_callback(string_ptr, size, nmemb) - length = size * nmemb - response_body << string_ptr.read_string(length) + length = size * nmemb + @response_body << string_ptr.read_string(length).dup return length end def default_header_callback(string_ptr, size, nmemb) - length = size * nmemb - response_header << string_ptr.read_string(length) + length = size * nmemb + @response_header << string_ptr.read_string(length).dup return length end def custom_write_callback(string_ptr, size, nmemb) - length = size * nmemb - @custom_write_handler.call(string_ptr.read_string(length)) + length = size * nmemb + @_wcall = string_ptr.read_string(length) + @custom_write_handler.call(string_ptr.read_string(length).dup) return length end def custom_header_callback(string_ptr, size, nmemb) - length = size * nmemb - @custom_header_handler.call(string_ptr.read_string(length)) + length = size * nmemb + @_hcall = string_ptr.read_string(length) + @custom_header_handler.call(string_ptr.read_string(length).dup) return length end end end