lib/aws/core/http/net_http_handler.rb



# Copyright 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

require 'net/http'
require 'net/https'
require 'openssl'

module AWS
  module Core
    module Http
  
      # The default http request handler for the aws-sdk gem.  It is based
      # on Net::Http.
      class NetHttpHandler
  
        def handle request, response
          http_session_for(request) do |http|
            begin
              http_resp = http.request(build_request(request))
              response.body = http_resp.body
              response.status = http_resp.code.to_i
              response.headers = http_resp.to_hash
            rescue Timeout::Error, Errno::ETIMEDOUT => e
              response.timeout = true
            end
          end
        end
          
        # @private
        protected
        def http_session_for request, &block
          begin
            http = build_http(request)
            http.start
            yield(http)
          ensure
            http.finish if http.started?
          end
        end

        # @private
        protected
        def build_http request

          http_args = []
          http_args << request.host
          http_args << (request.use_ssl? ? 443 : 80)

          ## add proxy arguments

          if proxy = request.proxy_uri
            proxy_addr = proxy.respond_to?(:request_uri) ?
              "#{proxy.host}#{proxy.request_uri}" : proxy.host
            http_args << proxy_addr
            http_args << proxy.port
            http_args << proxy.user
            http_args << proxy.password
          end

          # ruby 1.8.7 does not accept a hash of options at the end of
          # Net::HTTP.new like 1.9 does, therefore we have to set ssl
          # options on the returned http object
          http = Net::HTTP.new(*http_args)

          ## configure ssl 

          if request.use_ssl?
            http.use_ssl = true
            if request.ssl_verify_peer?
              http.verify_mode = OpenSSL::SSL::VERIFY_PEER
              http.ca_file = request.ssl_ca_file
            else
              http.verify_mode = OpenSSL::SSL::VERIFY_NONE
            end
          else
            http.use_ssl = false
          end

          http

        end

        # @private
        protected
        def build_request request

          # Net::HTTP adds a content-type header automatically unless its set
          # and this messes with request signature signing.  Also, it expects
          # all header values to be strings (it call strip on them).
          headers = { 'content-type' => '' }
          request.headers.each_pair do |key,value|
            headers[key] = value.to_s
          end

          req_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 raise "unsupported http method: #{request.http_method}"
          end

          net_http_req = req_class.new(request.uri, headers)
          net_http_req.body = request.body
          net_http_req

        end

      end

    end
  end
end