Class: HTTP::Connection

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/http/connection.rb

Overview

A connection to the HTTP server

Constant Summary collapse

KEEP_ALIVE =

Allowed values for CONNECTION header

"Keep-Alive"
CLOSE =
"close"
BUFFER_SIZE =

Attempt to read this much data

16_384
HTTP_1_0 =

HTTP/1.0

"1.0"
HTTP_1_1 =

HTTP/1.1

"1.1"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(req, options) ⇒ Connection

Returns a new instance of Connection.

Parameters:

Raises:



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/http/connection.rb', line 31

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
  @buffer               = "".b

  @parser = Response::Parser.new

  @socket = options.timeout_class.new(options.timeout_options)
  @socket.connect(options.socket_class, req.socket_host, req.socket_port, options.nodelay)

  send_proxy_connect_request(req)
  start_tls(req, options)
  reset_timer
rescue IOError, SocketError, SystemCallError => e
  raise ConnectionError, "failed to connect: #{e}", e.backtrace
rescue TimeoutError
  close
  raise
end

Instance Attribute Details

#proxy_response_headersObject (readonly)

Returned after HTTP CONNECT (via proxy)



26
27
28
# File 'lib/http/connection.rb', line 26

def proxy_response_headers
  @proxy_response_headers
end

Instance Method Details

#closevoid

This method returns an undefined value.

Close the connection



131
132
133
134
135
136
# File 'lib/http/connection.rb', line 131

def close
  @socket.close unless @socket&.closed?

  @pending_response = false
  @pending_request  = false
end

#expired?Boolean

Whether our connection has expired

Returns:

  • (Boolean)


150
151
152
# File 'lib/http/connection.rb', line 150

def expired?
  !@conn_expires_at || @conn_expires_at < Time.now
end

#failed_proxy_connect?Boolean

Returns whenever proxy connect failed.

Returns:

  • (Boolean)

    whenever proxy connect failed



64
65
66
# File 'lib/http/connection.rb', line 64

def failed_proxy_connect?
  @failed_proxy_connect
end

#finish_responsevoid

This method returns an undefined value.

Callback for when we've reached the end of a response



119
120
121
122
123
124
125
126
127
# File 'lib/http/connection.rb', line 119

def finish_response
  close unless keep_alive?

  @parser.reset
  @socket.reset_counter if @socket.respond_to?(:reset_counter)
  reset_timer

  @pending_response = false
end

#finished_request?Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/http/connection.rb', line 138

def finished_request?
  !@pending_request && !@pending_response
end

#keep_alive?Boolean

Whether we're keeping the conn alive

Returns:

  • (Boolean)


144
145
146
# File 'lib/http/connection.rb', line 144

def keep_alive?
  !!@keep_alive && !@socket.closed?
end

#read_headers!void

This method returns an undefined value.

Reads data from socket up until headers are loaded



108
109
110
111
112
113
114
115
# File 'lib/http/connection.rb', line 108

def read_headers!
  until @parser.headers?
    result = read_more(BUFFER_SIZE)
    raise ConnectionError, "couldn't read response headers" if result == :eof
  end

  set_keep_alive
end

#readpartial(size = BUFFER_SIZE) ⇒ String?

Read a chunk of the body

Returns:

  • (String)

    data chunk

  • (nil)

    when no more data left



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/http/connection.rb', line 93

def readpartial(size = BUFFER_SIZE)
  return unless @pending_response

  chunk = @parser.read(size)
  return chunk if chunk

  finished = (read_more(size) == :eof) || @parser.finished?
  chunk    = @parser.read(size)
  finish_response if finished

  chunk || "".b
end

#send_request(req) ⇒ nil

Send a request to the server

Parameters:

  • req (Request)

    Request to send to the server

Returns:

  • (nil)


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/http/connection.rb', line 72

def send_request(req)
  if @pending_response
    raise StateError, "Tried to send a request while one is pending already. Make sure you read off the body."
  end

  if @pending_request
    raise StateError, "Tried to send a request while a response is pending. Make sure you read off the body."
  end

  @pending_request = true

  req.stream @socket

  @pending_response = true
  @pending_request  = false
end