class Seahorse::Client::NetHttp::Handler
The default HTTP handler for Seahorse::Client. This is based on the Ruby's `Net::HTTP`.
Constants
- DNS_ERROR_MESSAGE
@api private
- NETWORK_ERRORS
Public Instance Methods
@param [RequestContext] context @return [Response]
# File lib/seahorse/client/net_http/handler.rb, line 33 def call(context) transmit(context.config, context.http_request, context.http_response) Response.new(context: context) end
@param [Configuration] config @return [ConnectionPool]
# File lib/seahorse/client/net_http/handler.rb, line 40 def pool_for(config) ConnectionPool.for(pool_options(config)) end
Private Instance Methods
Constructs and returns a Net::HTTP::Request object from a {Http::Request}. @param [Http::Request] request @return [Net::HTTP::Request]
# File lib/seahorse/client/net_http/handler.rb, line 128 def build_net_request(request) request_class = net_http_request_class(request) req = request_class.new(request.endpoint.request_uri, headers(request)) req.body_stream = request.body req end
# File lib/seahorse/client/net_http/handler.rb, line 85 def complete_response(req, resp, bytes_received) if should_verify_bytes?(req, resp) verify_bytes_received(resp, bytes_received) else resp.signal_done end end
# File lib/seahorse/client/net_http/handler.rb, line 46 def error_message(req, error) if error.is_a?(SocketError) && error.message == DNS_ERROR_MESSAGE host = req.endpoint.host "unable to connect to `#{host}`; SocketError: #{error.message}" else error.message end end
@param [Net::HTTP::Response] response @return [Hash<String, String>]
# File lib/seahorse/client/net_http/handler.rb, line 160 def extract_headers(response) response.to_hash.inject({}) do |headers, (k, v)| headers[k] = v.first headers end end
@param [Http::Request] request @return [Hash] Returns a vanilla hash of headers to send with the
HTTP request.
# File lib/seahorse/client/net_http/handler.rb, line 149 def headers(request) # setting these to stop net/http from providing defaults headers = { 'content-type' => '', 'accept-encoding' => '' } request.headers.each_pair do |key, value| headers[key] = value end headers end
@param [Http::Request] request @raise [InvalidHttpVerbError] @return Returns a base `Net::HTTP::Request` class, e.g.,
`Net::HTTP::Get`, `Net::HTTP::Post`, etc.
# File lib/seahorse/client/net_http/handler.rb, line 139 def net_http_request_class(request) Net::HTTP.const_get(request.http_method.capitalize) rescue NameError msg = "`#{request.http_method}` is not a valid http verb" raise InvalidHttpVerbError, msg end
Extracts the {ConnectionPool} configuration options. @param [Configuration] config @return [Hash]
# File lib/seahorse/client/net_http/handler.rb, line 117 def pool_options(config) ConnectionPool::OPTIONS.keys.inject({}) do |opts,opt| opts[opt] = config.send(opt) opts end end
# File lib/seahorse/client/net_http/handler.rb, line 107 def session(config, req, &block) pool_for(config).session_for(req.endpoint) do |http| http.read_timeout = config.http_read_timeout yield(http) end end
# File lib/seahorse/client/net_http/handler.rb, line 93 def should_verify_bytes?(req, resp) req.http_method != 'HEAD' && resp.headers['content-length'] end
@param [Configuration] config @param [Http::Request] req @param [Http::Response] resp @return [void]
# File lib/seahorse/client/net_http/handler.rb, line 59 def transmit(config, req, resp) session(config, req) do |http| http.request(build_net_request(req)) do |net_resp| status_code = net_resp.code.to_i headers = extract_headers(net_resp) bytes_received = 0 resp.signal_headers(status_code, headers) net_resp.read_body do |chunk| bytes_received += chunk.bytesize resp.signal_data(chunk) end complete_response(req, resp, bytes_received) end end rescue *NETWORK_ERRORS => error # these are retryable error = NetworkingError.new(error, error_message(req, error)) resp.signal_error(error) rescue => error # not retryable resp.signal_error(error) end
# File lib/seahorse/client/net_http/handler.rb, line 97 def verify_bytes_received(resp, bytes_received) bytes_expected = resp.headers['content-length'].to_i if bytes_expected == bytes_received resp.signal_done else error = TruncatedBodyError.new(bytes_expected, bytes_received) resp.signal_error(NetworkingError.new(error, error.message)) end end