class Excon::Connection

def request_kernel(params)

def request_kernel(params)
  begin
    response = if params[:mock]
      invoke_stub(params)
    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 << '?'
        params[:query].each do |key, values|
          if values.nil?
            request << key.to_s << '&'
          else
            [*values].each do |value|
              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
      if params.has_key?(:request_block)
        params[:headers]['Transfer-Encoding'] = 'chunked'
      elsif ! (params[:method].to_s.casecmp('GET') == 0 && params[:body].nil?)
        # The HTTP spec isn't clear on it, but specifically, GET requests don't usually send bodies;
        # if they don't, sending Content-Length:0 can cause issues.
        params[:headers]['Content-Length'] = detect_content_length(params[:body])
      end
      # add headers to request
      params[:headers].each do |key, values|
        [*values].each do |value|
          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.has_key?(:request_block)
        while true
          chunk = params[:request_block].call
          if FORCE_ENC
            chunk.force_encoding('BINARY')
          end
          if chunk.length > 0
            socket.write(chunk.length.to_s(16) << CR_NL << chunk << CR_NL)
          else
            socket.write('0' << CR_NL << CR_NL)
            break
          end
        end
      elsif !params[:body].nil?
        if params[:body].is_a?(String)
          unless params[:body].empty?
            socket.write(params[:body])
          end
        else
          if params[:body].respond_to?(:binmode)
            params[:body].binmode
          end
          while chunk = params[:body].read(CHUNK_SIZE)
            socket.write(chunk)
          end
        end
      end
      # read the response
      response = Excon::Response.parse(socket, params)
      if response.headers['Connection'] == 'close'
        reset
      end
      response
    end
  rescue Excon::Errors::StubNotFound, Excon::Errors::Timeout => error
    raise(error)
  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