class HTTPI::Adapter::Curb

HTTPI::Adapter::Curb

Adapter for the Curb client. rubygems.org/gems/curb

Attributes

client[R]

Public Class Methods

new(request) click to toggle source
# File lib/httpi/adapter/curb.rb, line 15
def initialize(request)
  @request = request
  @client = Curl::Easy.new
end

Public Instance Methods

request(method) click to toggle source
# File lib/httpi/adapter/curb.rb, line 22
def request(method)
  unless REQUEST_METHODS.include? method
    raise NotSupportedError, "Curb does not support custom HTTP methods"
  end

  arguments = ["http_#{method}"]
  if [:put, :post].include? method
    arguments << (@request.body || "")
  end

  if @request.on_body
    client.on_body do |data|
      @request.on_body.call(data)
      # curb requires you to return the length of the data read from the block.
      # It allows you to abort the connection by returning a smaller value
      data.length
    end
  end

  do_request { |client| client.send(*arguments) }
rescue Curl::Err::SSLCACertificateError
  raise SSLError
rescue Curl::Err::SSLPeerCertificateError
  raise SSLError
rescue Curl::Err::ConnectionFailedError  # connection refused
  $!.extend ConnectionError
  raise
end

Private Instance Methods

basic_setup() click to toggle source
# File lib/httpi/adapter/curb.rb, line 72
def basic_setup
  @client.url = @request.url.to_s
  @client.proxy_url = @request.proxy.to_s if @request.proxy
  read_or_write_timeout = @request.read_timeout || @request.write_timeout
  @client.timeout_ms = read_or_write_timeout * 1000 if read_or_write_timeout
  @client.connect_timeout_ms = @request.open_timeout * 1000 if @request.open_timeout
  @client.headers = @request.headers.to_hash
  @client.verbose = false
  # cURL workaround
  # see: http://stackoverflow.com/a/10755612/102920
  #      https://github.com/typhoeus/typhoeus/issues/260
  @client.set(:NOSIGNAL, true)
end
do_request() { |client| ... } click to toggle source
# File lib/httpi/adapter/curb.rb, line 53
def do_request
  setup_client
  yield @client
  respond_with @client
end
parse_header_string(header_string) click to toggle source

Borrowed from Webmock’s Curb adapter: github.com/bblimke/webmock/blob/master/lib/webmock/http_lib_adapters/curb.rb

# File lib/httpi/adapter/curb.rb, line 144
def parse_header_string(header_string)
  status, headers = nil, {}
  return [status, headers] unless header_string

  header_string.split(/\r\n/).each do |header|
    if header =~ %r|^HTTP/1.[01] \d\d\d (.*)|
      status = $1
    else
      parts = header.split(':', 2)
      unless parts.empty?
        parts[1].strip! unless parts[1].nil?
        if headers.has_key?(parts[0])
          headers[parts[0]] = [headers[parts[0]]] unless headers[parts[0]].kind_of? Array
          headers[parts[0]] << parts[1]
        else
          headers[parts[0]] = parts[1]
        end
      end
    end
  end

  [status, headers]
end
respond_with(client) click to toggle source
# File lib/httpi/adapter/curb.rb, line 137
def respond_with(client)
  headers = parse_header_string(client.header_str).last
  Response.new client.response_code, headers, client.body_str
end
setup_client() click to toggle source
# File lib/httpi/adapter/curb.rb, line 59
def setup_client
  basic_setup

  if @request.auth.ntlm? && !Curl.ntlm?
    raise NotSupportedError, "installed version of libcurl does not support NTLM authentication"
  end

  setup_ntlm_auth if @request.auth.ntlm?
  setup_http_auth if @request.auth.http?
  setup_gssnegotiate_auth if @request.auth.gssnegotiate?
  setup_ssl_auth if @request.auth.ssl? || @request.ssl?
end
setup_gssnegotiate_auth() click to toggle source
# File lib/httpi/adapter/curb.rb, line 96
def setup_gssnegotiate_auth
  @client.http_auth_types = @request.auth.type
  # The curl man page (http://curl.haxx.se/docs/manpage.html) says that
  # you have to specify a fake username when using Negotiate auth, and
  # they use ':' in their example.
  @client.username = ':'
end
setup_http_auth() click to toggle source
# File lib/httpi/adapter/curb.rb, line 91
def setup_http_auth
  @client.http_auth_types = @request.auth.type
  @client.username, @client.password = *@request.auth.credentials
end
setup_ntlm_auth() click to toggle source
# File lib/httpi/adapter/curb.rb, line 86
def setup_ntlm_auth
  @client.http_auth_types = @request.auth.type
  @client.username, @client.password = *@request.auth.credentials
end
setup_ssl_auth() click to toggle source
# File lib/httpi/adapter/curb.rb, line 104
def setup_ssl_auth
  ssl = @request.auth.ssl

  if @request.auth.ssl?
    if ssl.verify_mode == :none
      @client.ssl_verify_host = 0
    else
      @client.cacert = ssl.ca_cert_file if ssl.ca_cert_file
      @client.certtype = ssl.cert_type.to_s.upcase
    end

    # Send client-side certificate regardless of state of SSL verify mode
    @client.cert_key = ssl.cert_key_file
    @client.cert = ssl.cert_file
    @client.certpassword = ssl.cert_key_password
    @client.set(:ssl_cipher_list, ssl.ciphers.join(':')) if ssl.ciphers

    @client.ssl_verify_peer = ssl.verify_mode == :peer
  end

  @client.ssl_version = case ssl.ssl_version
    when :TLSv1_2 then 1
    when :TLSv1_1 then 1
    when :TLSv1   then 1
    when :SSLv2   then 2
    when :SSLv23  then 2
    when :SSLv3   then 3
  end
  if ssl.min_version || ssl.max_version
    raise NotSupportedError, 'Curb adapter does not support #min_version or #max_version. Please, use #ssl_version instead.'
  end
end