class HTTP::Request

Constants

METHODS
PORTS

Default ports of supported schemes

SCHEMES

Allowed schemes

USER_AGENT

Default User-Agent header value

Attributes

body[R]
proxy[R]
scheme[R]

Scheme is normalized to be a lowercase symbol e.g. :http, :https

uri[R]

“Request URI” as per RFC 2616 www.w3.org/Protocols/rfc2616/rfc2616-sec5.html

uri_normalizer[R]
verb[R]

Method is given as a lowercase symbol e.g. :get, :post

version[R]

Public Class Methods

new(opts) click to toggle source

@option opts [String] :version @option opts [#to_s] :verb HTTP request method @option opts [#call] :uri_normalizer (HTTP::URI::NORMALIZER) @option opts [HTTP::URI, to_s] :uri @option opts [Hash] :headers @option opts [Hash] :proxy @option opts [String, Enumerable, IO, nil] :body

# File lib/http/request.rb, line 86
def initialize(opts)
  @verb           = opts.fetch(:verb).to_s.downcase.to_sym
  @uri_normalizer = opts[:uri_normalizer] || HTTP::URI::NORMALIZER

  @uri    = @uri_normalizer.call(opts.fetch(:uri))
  @scheme = @uri.scheme.to_s.downcase.to_sym if @uri.scheme

  raise(UnsupportedMethodError, "unknown method: #{verb}") unless METHODS.include?(@verb)
  raise(UnsupportedSchemeError, "unknown scheme: #{scheme}") unless SCHEMES.include?(@scheme)

  @proxy   = opts[:proxy] || {}
  @version = opts[:version] || "1.1"
  @headers = prepare_headers(opts[:headers])
  @body    = prepare_body(opts[:body])
end

Public Instance Methods

connect_using_proxy(socket) click to toggle source

Setup tunnel through proxy for SSL request

# File lib/http/request.rb, line 164
def connect_using_proxy(socket)
  Request::Writer.new(socket, nil, proxy_connect_headers, proxy_connect_header).connect_through_proxy
end
headline() click to toggle source

Compute HTTP request header for direct or proxy request

# File lib/http/request.rb, line 169
def headline
  request_uri =
    if using_proxy? && !uri.https?
      uri.omit(:fragment)
    else
      uri.request_uri
    end

  "#{verb.to_s.upcase} #{request_uri} HTTP/#{version}"
end
include_proxy_authorization_header() click to toggle source

Compute and add the Proxy-Authorization header

# File lib/http/request.rb, line 154
def include_proxy_authorization_header
  headers[Headers::PROXY_AUTHORIZATION] = proxy_authorization_header
end
include_proxy_headers() click to toggle source
# File lib/http/request.rb, line 148
def include_proxy_headers
  headers.merge!(proxy[:proxy_headers]) if proxy.key?(:proxy_headers)
  include_proxy_authorization_header if using_authenticated_proxy?
end
inspect() click to toggle source

Human-readable representation of base request info.

@example

req.inspect
# => #<HTTP::Request/1.1 GET https://example.com>

@return [String]

# File lib/http/request.rb, line 215
def inspect
  "#<#{self.class}/#{@version} #{verb.to_s.upcase} #{uri}>"
end
proxy_authorization_header() click to toggle source
# File lib/http/request.rb, line 158
def proxy_authorization_header
  digest = Base64.strict_encode64("#{proxy[:proxy_username]}:#{proxy[:proxy_password]}")
  "Basic #{digest}"
end
proxy_connect_header() click to toggle source

Compute HTTP request header SSL proxy connection

# File lib/http/request.rb, line 181
def proxy_connect_header
  "CONNECT #{host}:#{port} HTTP/#{version}"
end
proxy_connect_headers() click to toggle source

Headers to send with proxy connect request

# File lib/http/request.rb, line 186
def proxy_connect_headers
  connect_headers = HTTP::Headers.coerce(
    Headers::HOST       => headers[Headers::HOST],
    Headers::USER_AGENT => headers[Headers::USER_AGENT]
  )

  connect_headers[Headers::PROXY_AUTHORIZATION] = proxy_authorization_header if using_authenticated_proxy?
  connect_headers.merge!(proxy[:proxy_headers]) if proxy.key?(:proxy_headers)
  connect_headers
end
redirect(uri, verb = @verb) click to toggle source

Returns new Request with updated uri

# File lib/http/request.rb, line 103
def redirect(uri, verb = @verb)
  headers = self.headers.dup
  headers.delete(Headers::HOST)

  new_body = body.source
  if verb == :get
    # request bodies should not always be resubmitted when following a redirect
    # some servers will close the connection after receiving the request headers
    # which may cause Errno::ECONNRESET: Connection reset by peer
    # see https://github.com/httprb/http/issues/649
    # new_body = Request::Body.new(nil)
    new_body = nil
    # the CONTENT_TYPE header causes problems if set on a get request w/ an empty body
    # the server might assume that there should be content if it is set to multipart
    # rack raises EmptyContentError if this happens
    headers.delete(Headers::CONTENT_TYPE)
  end

  self.class.new(
    :verb           => verb,
    :uri            => @uri.join(uri),
    :headers        => headers,
    :proxy          => proxy,
    :body           => new_body,
    :version        => version,
    :uri_normalizer => uri_normalizer
  )
end
socket_host() click to toggle source

Host for tcp socket

# File lib/http/request.rb, line 198
def socket_host
  using_proxy? ? proxy[:proxy_address] : host
end
socket_port() click to toggle source

Port for tcp socket

# File lib/http/request.rb, line 203
def socket_port
  using_proxy? ? proxy[:proxy_port] : port
end
stream(socket) click to toggle source

Stream the request to a socket

# File lib/http/request.rb, line 133
def stream(socket)
  include_proxy_headers if using_proxy? && !@uri.https?
  Request::Writer.new(socket, body, headers, headline).stream
end
using_authenticated_proxy?() click to toggle source

Is this request using an authenticated proxy?

# File lib/http/request.rb, line 144
def using_authenticated_proxy?
  proxy && proxy.keys.size >= 4
end
using_proxy?() click to toggle source

Is this request using a proxy?

# File lib/http/request.rb, line 139
def using_proxy?
  proxy && proxy.keys.size >= 2
end

Private Instance Methods

default_host_header_value() click to toggle source

@return [String] Default host (with port if needed) header value.

# File lib/http/request.rb, line 232
def default_host_header_value
  PORTS[@scheme] == port ? host : "#{host}:#{port}"
end
port() click to toggle source

@!attribute [r] port

@return [Fixnum]
# File lib/http/request.rb, line 227
def port
  @uri.port || @uri.default_port
end
prepare_body(body) click to toggle source
# File lib/http/request.rb, line 236
def prepare_body(body)
  body.is_a?(Request::Body) ? body : Request::Body.new(body)
end
prepare_headers(headers) click to toggle source
# File lib/http/request.rb, line 240
def prepare_headers(headers)
  headers = HTTP::Headers.coerce(headers || {})

  headers[Headers::HOST]       ||= default_host_header_value
  headers[Headers::USER_AGENT] ||= USER_AGENT

  headers
end