Class: HTTP::Connection

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Internals
Defined in:
lib/http/connection.rb,
lib/http/connection/internals.rb,
sig/http.rbs

Overview

A connection to the HTTP server

Defined Under Namespace

Modules: Internals

Constant Summary collapse

KEEP_ALIVE =

Allowed values for CONNECTION header

Returns:

  • (String)
"Keep-Alive"
CLOSE =

Connection: close header value

Returns:

  • (String)
"close"
BUFFER_SIZE =

Attempt to read this much data

Returns:

  • (Integer)
16_384
MAX_FLUSH_SIZE =

Maximum response body size (in bytes) to auto-flush when reusing a connection. Bodies larger than this cause the connection to close instead, to avoid blocking on huge downloads.

Returns:

  • (Integer)
1_048_576
HTTP_1_0 =

HTTP/1.0

Returns:

  • (String)
"1.0"
HTTP_1_1 =

HTTP/1.1

Returns:

  • (String)
"1.1"

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Internals

#body_framed?, #flush_or_close_response, #flush_pending_response

Constructor Details

#initialize(req, options) ⇒ Connection

Initialize a new connection to an HTTP server

Examples:

Connection.new(req, options)

Parameters:

Raises:



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/http/connection.rb', line 52

def initialize(req, options)
  init_state(options)
  connect_socket(req, options)
rescue IO::TimeoutError => e
  close
  raise ConnectTimeoutError, e.message, e.backtrace
rescue IOError, SocketError, SystemCallError => e
  raise ConnectionError, "failed to connect: #{e}", e.backtrace
rescue TimeoutError
  close
  raise
end

Instance Attribute Details

#pending_response=(value) ⇒ void (writeonly)

This method returns an undefined value.

Set the pending response for auto-flushing before the next request

Examples:

connection.pending_response = response

Parameters:



93
94
95
# File 'lib/http/connection.rb', line 93

def pending_response=(value)
  @pending_response = value
end

#proxy_response_headersHTTP::Headers? (readonly)

Returned after HTTP CONNECT (via proxy)

Examples:

connection.proxy_response_headers

Returns:



40
41
42
# File 'lib/http/connection.rb', line 40

def proxy_response_headers
  @proxy_response_headers
end

Instance Method Details

#check_premature_eof(eof) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Check for premature end-of-file and raise if detected

Examples:

check_premature_eof(:eof)

Parameters:

  • eof (Boolean)

Raises:



246
247
248
249
250
251
# File 'lib/http/connection.rb', line 246

def check_premature_eof(eof)
  return unless eof && !@parser.finished? && body_framed?

  close
  raise ConnectionError, "response body ended prematurely"
end

#closevoid

This method returns an undefined value.

Close the connection

Examples:

connection.close


184
185
186
187
188
189
# File 'lib/http/connection.rb', line 184

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

  @pending_response = false
  @pending_request  = false
end

#connect_socket(req, options) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Connect socket and set up proxy/TLS

Parameters:



256
257
258
259
260
261
262
263
# File 'lib/http/connection.rb', line 256

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

  send_proxy_connect_request(req)
  start_tls(req, options)
  reset_timer
end

#expired?Boolean

Whether our connection has expired

Examples:

connection.expired?

Returns:

  • (Boolean)


220
221
222
# File 'lib/http/connection.rb', line 220

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

#failed_proxy_connect?Boolean

Whether the proxy CONNECT request failed

Examples:

connection.failed_proxy_connect?

Returns:

  • (Boolean)

    whenever proxy connect failed



81
82
83
# File 'lib/http/connection.rb', line 81

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

Examples:

connection.finish_response


167
168
169
170
171
172
173
174
175
# File 'lib/http/connection.rb', line 167

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

Whether there are no pending requests or responses

Examples:

connection.finished_request?

Returns:

  • (Boolean)


198
199
200
# File 'lib/http/connection.rb', line 198

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

#handle_proxy_connect_responsevoid

This method returns an undefined value.



1155
# File 'sig/http.rbs', line 1155

def handle_proxy_connect_response: () -> void

#headersHeaders

Returns:



1146
# File 'sig/http.rbs', line 1146

def headers: () -> Headers

#http_versionString?

Returns:

  • (String, nil)


1145
# File 'sig/http.rbs', line 1145

def http_version: () -> String?

#init_state(options) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Initialize connection state

Parameters:



229
230
231
232
233
234
235
236
237
# File 'lib/http/connection.rb', line 229

def init_state(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
end

#keep_alive?Boolean

Whether we're keeping the conn alive

Examples:

connection.keep_alive?

Returns:

  • (Boolean)


209
210
211
# File 'lib/http/connection.rb', line 209

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

Examples:

connection.read_headers!

Raises:



151
152
153
154
155
156
157
158
# File 'lib/http/connection.rb', line 151

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

  set_keep_alive
end

#read_moreObject

Parameters:

  • size (Integer)

Returns:

  • (Object)


1158
# File 'sig/http.rbs', line 1158

def read_more: (Integer size) -> untyped

#readpartial(size = BUFFER_SIZE, outbuf = nil) ⇒ String

Read a chunk of the body

Examples:

connection.readpartial

Parameters:

  • size (Integer) (defaults to: BUFFER_SIZE)

    maximum bytes to read

  • outbuf (String, nil) (defaults to: nil)

    buffer to fill with data

Returns:

  • (String)

    data chunk

Raises:

  • (EOFError)

    when no more data left



128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/http/connection.rb', line 128

def readpartial(size = BUFFER_SIZE, outbuf = nil)
  raise EOFError unless @pending_response

  chunk = @parser.read(size)
  unless chunk
    eof = read_more(size) == :eof
    check_premature_eof(eof)
    finished = eof || @parser.finished?
    chunk    = @parser.read(size) || "".b
    finish_response if finished
  end

  outbuf ? outbuf.replace(chunk) : chunk
end

#reset_timervoid

This method returns an undefined value.



1156
# File 'sig/http.rbs', line 1156

def reset_timer: () -> void

#send_proxy_connect_requestvoid

This method returns an undefined value.

Parameters:



1154
# File 'sig/http.rbs', line 1154

def send_proxy_connect_request: (Request req) -> void

#send_request(req) ⇒ nil

Send a request to the server

Examples:

connection.send_request(req)

Parameters:

  • req (Request)

    Request to send to the server

Returns:

  • (nil)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/http/connection.rb', line 103

def send_request(req)
  flush_pending_response if @pending_response

  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

#set_keep_alivevoid

This method returns an undefined value.



1157
# File 'sig/http.rbs', line 1157

def set_keep_alive: () -> void

#start_tlsvoid

This method returns an undefined value.

Parameters:



1153
# File 'sig/http.rbs', line 1153

def start_tls: (Request req, Options options) -> void

#status_codeInteger?

Returns:

  • (Integer, nil)


1144
# File 'sig/http.rbs', line 1144

def status_code: () -> Integer?