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