Class: Rev::HttpClient

Inherits:
TCPSocket show all
Includes:
HttpEncoding
Defined in:
lib/rev/http_client.rb

Overview

HTTP client class implemented as a subclass of Rev::TCPSocket. Encodes requests and allows streaming consumption of the response. Response is parsed with a Ragel-generated whitelist parser which supports chunked HTTP encoding.

Example

loop = Rev::Loop.default
client = Rev::HttpClient.connect("www.google.com").attach
client.get('/search', query: {q: 'foobar'})
loop.run

Constant Summary collapse

ALLOWED_METHODS =
[:put, :get, :post, :delete, :head]
TRANSFER_ENCODING =
"TRANSFER_ENCODING"
CONTENT_LENGTH =
"CONTENT_LENGTH"
"SET_COOKIE"
LOCATION =
"LOCATION"
HOST =
"HOST"
CRLF =
"\r\n"

Constants included from HttpEncoding

Rev::HttpEncoding::FIELD_ENCODING, Rev::HttpEncoding::HTTP_REQUEST_HEADER

Constants inherited from IO

IO::INPUT_SIZE

Instance Attribute Summary

Attributes inherited from TCPSocket

#address_family, #remote_addr, #remote_host, #remote_port

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HttpEncoding

#encode_cookies, #encode_field, #encode_headers, #encode_host, #encode_param, #encode_query, #encode_request, #escape, #munge_header_keys, #unescape

Methods inherited from TCPSocket

#peeraddr, precreate

Methods inherited from Socket

#attach, #on_connect_failed, #on_resolve_failed

Methods inherited from IO

#attach, #attached?, #close, #closed?, #detach, #disable, #enabled?, #evloop, #on_close, #on_write_complete, #output_buffer_size, #write

Methods included from Meta

#event_callback, #watcher_delegate

Constructor Details

#initialize(socket) ⇒ HttpClient

Returns a new instance of HttpClient.



141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/rev/http_client.rb', line 141

def initialize(socket)
  super

  @parser = HttpClientParser.new
  @parser_nbytes = 0

  @state = :response_header
  @data = Rev::Buffer.new

  @response_header = HttpResponseHeader.new
  @chunk_header = HttpChunkHeader.new
end

Class Method Details

.connect(addr, port = 80, *args) ⇒ Object

Connect to the given server, with port 80 as the default



137
138
139
# File 'lib/rev/http_client.rb', line 137

def self.connect(addr, port = 80, *args)
  super
end

Instance Method Details

#enableObject

Enable the HttpClient if it has been disabled



181
182
183
184
# File 'lib/rev/http_client.rb', line 181

def enable
  super
  dispatch unless @data.empty?
end

#on_body_data(data) ⇒ Object

Called when part of the body has been read



191
192
193
194
# File 'lib/rev/http_client.rb', line 191

def on_body_data(data)
  STDOUT.write data
  STDOUT.flush
end

#on_error(reason) ⇒ Object

Called when an error occurs dispatching the request

Raises:

  • (RuntimeError)


202
203
204
205
# File 'lib/rev/http_client.rb', line 202

def on_error(reason)
  close
  raise RuntimeError, reason
end

#on_request_completeObject

Called when the request has completed



197
198
199
# File 'lib/rev/http_client.rb', line 197

def on_request_complete
  close
end

#on_response_header(response_header) ⇒ Object

Called when response header has been received



187
188
# File 'lib/rev/http_client.rb', line 187

def on_response_header(response_header)
end

#request(method, path, options = {}) ⇒ Object

Send an HTTP request and consume the response.

Supports the following options:

head: {Key: Value}
  Specify an HTTP header, e.g. {'Connection': 'close'} 

query: {Key: Value}
  Specify query string parameters (auto-escaped)

cookies: {Key: Value}
  Specify hash of cookies (auto-escaped)

body: String
  Specify the request body (you must encode it for now)

Raises:

  • (ArgumentError)


169
170
171
172
173
174
175
176
177
178
# File 'lib/rev/http_client.rb', line 169

def request(method, path, options = {})
  raise ArgumentError, "invalid request path" unless /^\// === path
  raise RuntimeError, "request already sent" if @requested

  @method, @path, @options = method, path, options
  @requested = true

  return unless @connected
  send_request
end