class AWS::Core::Http::NetHttpHandler

# NetHttpHandler

This is the default HTTP handler for the aws-sdk gem. It uses Ruby's Net::HTTP to make requests. It uses persistent connections and a connection pool.

Constants

NETWORK_ERRORS

@api private

Attributes

pool[R]

@return [ConnectionPool]

Public Class Methods

new(options = {}) click to toggle source

(see AWS::Core::Http::ConnectionPool.new)

# File lib/aws/core/http/net_http_handler.rb, line 36
def initialize options = {}
  @pool = ConnectionPool.new(options)
  @verify_content_length = options[:verify_response_body_content_length]
end

Public Instance Methods

handle(request, response) { |data| ... } click to toggle source

Given a populated request object and an empty response object, this method will make the request and them populate the response. @param [Request] request @param [Response] response @return [nil]

# File lib/aws/core/http/net_http_handler.rb, line 50
def handle request, response, &read_block
  retry_possible = true

  begin

    @pool.session_for(request.endpoint) do |http|

      http.read_timeout = request.read_timeout
      http.continue_timeout = request.continue_timeout if
        http.respond_to?(:continue_timeout=)

      http.request(build_net_http_request(request)) do |net_http_resp|
        response.status = net_http_resp.code.to_i
        response.headers = net_http_resp.to_hash
        exp_length = determine_expected_content_length(response)
        act_length = 0
        begin
          if block_given? and response.status < 300
            net_http_resp.read_body do |data|
              begin
                act_length += data.bytesize
                yield data
              ensure
                retry_possible = false
              end
            end
          else
            response.body = net_http_resp.read_body
            act_length += response.body.bytesize unless response.body.nil?
          end
        ensure
          run_check = exp_length.nil? == false && request.http_method != "HEAD" && @verify_content_length
          if run_check && act_length != exp_length
            raise TruncatedBodyError, 'content-length does not match'
          end
        end
      end

    end

  rescue *NETWORK_ERRORS => error
    raise error unless retry_possible
    response.network_error = error
  end
  nil
end

Protected Instance Methods

build_net_http_request(request) click to toggle source

Given an AWS::Core::HttpRequest, this method translates it into a Net::HTTPRequest (Get, Put, Post, Head or Delete). @param [Request] request @return [Net::HTTPRequest]

# File lib/aws/core/http/net_http_handler.rb, line 111
def build_net_http_request request

  # Net::HTTP adds a content-type (1.8.7+) and accept-encoding (2.0.0+)
  # to the request if these headers are not set.  Setting a default
  # empty value defeats this.
  #
  # Removing these are necessary for most services to no break request
  # signatures as well as dynamodb crc32 checks (these fail if the
  # response is gzipped).
  headers = { 'content-type' => '', 'accept-encoding' => '' }

  request.headers.each_pair do |key,value|
    headers[key] = value.to_s
  end

  request_class = case request.http_method
    when 'GET'    then Net::HTTP::Get
    when 'PUT'    then Net::HTTP::Put
    when 'POST'   then Net::HTTP::Post
    when 'HEAD'   then Net::HTTP::Head
    when 'DELETE' then Net::HTTP::Delete
    else
      msg = "unsupported http method: #{request.http_method}"
      raise ArgumentError, msg
    end

  net_http_req = request_class.new(request.uri, headers)
  net_http_req.body_stream = request.body_stream
  net_http_req

end
determine_expected_content_length(response) click to toggle source
# File lib/aws/core/http/net_http_handler.rb, line 99
def determine_expected_content_length response
  if header = response.headers['content-length']
    if header.is_a?(Array)
      header.first.to_i
    end
  end
end