class Excon::Connection

def request_kernel(params, &block)

def request_kernel(params, &block)
  begin
    response = if params[:mock]
      invoke_stub(params, &block)
    else
      socket.params = params
      # start with "METHOD /path"
      request = params[:method].to_s.upcase << ' '
      if @proxy
        request << params[:scheme] << '://' << params[:host] << ':' << params[:port]
      end
      request << params[:path]
      # add query to path, if there is one
      case params[:query]
      when String
        request << '?' << params[:query]
      when Hash
        request << '?'
        for key, values in params[:query]
          if values.nil?
            request << key.to_s << '&'
          else
            for value in [*values]
              request << key.to_s << '=' << CGI.escape(value.to_s) << '&'
            end
          end
        end
        request.chop! # remove trailing '&'
      end
      # finish first line with "HTTP/1.1\r\n"
      request << HTTP_1_1
      # calculate content length and set to handle non-ascii
      unless params[:headers].has_key?('Content-Length')
        params[:headers]['Content-Length'] = case params[:body]
        when File
          params[:body].binmode
          File.size(params[:body])
        when String
          if FORCE_ENC
            params[:body].force_encoding('BINARY')
          end
          params[:body].length
        else
          0
        end
      end
      # add headers to request
      for key, values in params[:headers]
        for value in [*values]
          request << key.to_s << ': ' << value.to_s << CR_NL
        end
      end
      # add additional "\r\n" to indicate end of headers
      request << CR_NL
      # write out the request, sans body
      socket.write(request)
      # write out the body
      if params[:body]
        if params[:body].is_a?(String)
          socket.write(params[:body])
        else
          while chunk = params[:body].read(CHUNK_SIZE)
            socket.write(chunk)
          end
        end
      end
      # read the response
      response = Excon::Response.parse(socket, params, &block)
      if response.headers['Connection'] == 'close'
        reset
      end
      response
    end
  rescue Excon::Errors::StubNotFound => stub_not_found
    raise(stub_not_found)
  rescue => socket_error
    reset
    raise(Excon::Errors::SocketError.new(socket_error))
  end
  if params.has_key?(:expects) && ![*params[:expects]].include?(response.status)
    reset
    raise(Excon::Errors.status_error(params, response))
  else
    response
  end
end