class HTTP::Connection

A connection to the HTTP server

def close

Returns:
  • (void) -
def close
  @socket.close unless @socket.closed?
  @pending_response = false
  @pending_request  = false
end

def expired?

Returns:
  • (Boolean) -
def expired?
  !@conn_expires_at || @conn_expires_at < Time.now
end

def failed_proxy_connect?

Returns:
  • (Boolean) - whenever proxy connect failed
def failed_proxy_connect?
  @failed_proxy_connect
end

def finish_response

Returns:
  • (void) -
def finish_response
  close unless keep_alive?
  @parser.reset
  @socket.reset_counter if @socket.respond_to?(:reset_counter)
  reset_timer
  @pending_response = false
end

def initialize(req, options)

Parameters:
  • options (HTTP::Options) --
  • req (HTTP::Request) --
def initialize(req, options)
  @persistent           = options.persistent?
  @keep_alive_timeout   = options[:keep_alive_timeout].to_f
  @pending_request      = false
  @pending_response     = false
  @failed_proxy_connect = false
  @parser = Response::Parser.new
  @socket = options[:timeout_class].new(options[:timeout_options])
  @socket.connect(options[:socket_class], req.socket_host, req.socket_port)
  send_proxy_connect_request(req)
  start_tls(req, options)
  reset_timer
end

def keep_alive?

Returns:
  • (Boolean) -
def keep_alive?
  !!@keep_alive && !@socket.closed?
end

def read_headers!

Returns:
  • (void) -
def read_headers!
  read_more BUFFER_SIZE until @parser.headers
  set_keep_alive
rescue IOError, Errno::ECONNRESET, Errno::EPIPE => e
  return if e.is_a?(EOFError) && @parser.headers
  raise IOError, "problem making HTTP request: #{e}"
end

def read_more(size)

Returns:
  • (void) -
def read_more(size)
  @parser << @socket.readpartial(size) unless @parser.finished?
end

def readpartial(size = BUFFER_SIZE)

Returns:
  • (nil) - when no more data left
  • (String) - data chunk
def readpartial(size = BUFFER_SIZE)
  return unless @pending_response
  begin
    read_more size
    finished = @parser.finished?
  rescue EOFError
    finished = true
  end
  chunk = @parser.chunk
  finish_response if finished
  chunk.to_s
end

def reset_timer

Returns:
  • (void) -
def reset_timer
  @conn_expires_at = Time.now + @keep_alive_timeout if @persistent
end

def send_proxy_connect_request(req)

Open tunnel through proxy
def send_proxy_connect_request(req)
  return unless req.uri.https? && req.using_proxy?
  @pending_request = true
  req.connect_using_proxy @socket
  @pending_request = false
  @pending_response = true
  read_headers!
  if @parser.status_code == 200
    @parser.reset
    @pending_response = false
    return
  end
  @failed_proxy_connect = true
end

def send_request(req)

Returns:
  • (nil) -

Parameters:
  • Request (Request) -- to send to the server
def send_request(req)
  if @pending_response
    fail StateError, "Tried to send a request while one is pending already. Make sure you read off the body."
  elsif @pending_request
    fail StateError, "Tried to send a request while a response is pending. Make sure you've fully read the body from the request."
  end
  @pending_request = true
  req.stream @socket
  @pending_response = true
  @pending_request  = false
end

def set_keep_alive

Returns:
  • (void) -
def set_keep_alive
  return @keep_alive = false unless @persistent
  case @parser.http_version
  when HTTP_1_0 # HTTP/1.0 requires opt in for Keep Alive
    @keep_alive = @parser.headers[Client::CONNECTION] == HTTP::Client::KEEP_ALIVE
  when HTTP_1_1 # HTTP/1.1 is opt-out
    @keep_alive = @parser.headers[Client::CONNECTION] != HTTP::Client::CLOSE
  else # Anything else we assume doesn't supportit
    @keep_alive = false
  end
end

def start_tls(req, options)

Returns:
  • (void) -

Parameters:
  • () --
def start_tls(req, options)
  return unless req.uri.https? && !failed_proxy_connect?
  ssl_context = options[:ssl_context]
  unless ssl_context
    ssl_context = OpenSSL::SSL::SSLContext.new
    ssl_context.set_params(options[:ssl] || {})
  end
  @socket.start_tls(req.uri.host, options[:ssl_socket_class], ssl_context)
end