class Excon::Connection
def request(params={}, &block)
(**params)
-
:query
(Hash
) -- appended to the 'scheme://host:port/path/' in the form of '?key=value' -
:path
(String
) -- appears after 'scheme://host:port/' -
:headers
(Hash
) -- The default headers to supply in a request -
:body
(String
) -- text to be sent over a socket
Parameters:
-
params
(Hash
) -- One or more optional params, override defaults set in Connection.new
Other tags:
- Yield: - @see Response#self.parse
def request(params={}, &block) # @data has defaults, merge in new params to override datum = @data.merge(params) # Set the deadline for the current request in order to determine when we have run out of time. # Only set when a request timeout has been defined. if datum[:timeout] datum[:deadline] = Process.clock_gettime(Process::CLOCK_MONOTONIC) + datum[:timeout] end datum[:headers] = @data[:headers].merge(datum[:headers] || {}) validate_params(:request, params, datum[:middlewares]) # If the user passed in new middleware, we want to validate that the original connection parameters # are still valid with the provided middleware. if params[:middlewares] validate_params(:connection, @data, datum[:middlewares]) end if datum[:user] || datum[:password] user, pass = Utils.unescape_uri(datum[:user].to_s), Utils.unescape_uri(datum[:password].to_s) datum[:headers]['Authorization'] ||= 'Basic ' + ["#{user}:#{pass}"].pack('m').delete(Excon::CR_NL) end host_key = datum[:headers].keys.detect {|k| k.casecmp('Host') == 0 } || 'Host' if datum[:scheme] == UNIX datum[:headers][host_key] ||= '' else datum[:headers][host_key] ||= datum[:host] + port_string(datum) end # RFC 7230, section 5.4, states that the Host header SHOULD be the first one # to be present. # Some web servers will reject the request if it comes too late, so let's hoist it to the top. if (host = datum[:headers].delete(host_key)) datum[:headers] = { host_key => host }.merge(datum[:headers]) end # default to GET if no method specified unless datum[:method] datum[:method] = :get end # if path is empty or doesn't start with '/', insert one unless datum[:path][0, 1] == '/' datum[:path] = datum[:path].dup.insert(0, '/') end if block_given? Excon.display_warning('Excon requests with a block are deprecated, pass :response_block instead.') datum[:response_block] = block end datum[:connection] = self # cleanup data left behind on persistent connection after interrupt if datum[:persistent] && !@persistent_socket_reusable reset end datum[:stack] = datum[:middlewares].map do |middleware| lambda {|stack| middleware.new(stack)} end.reverse.inject(self) do |middlewares, middleware| middleware.call(middlewares) end datum = datum[:stack].request_call(datum) unless datum[:pipeline] @persistent_socket_reusable = false datum = response(datum) @persistent_socket_reusable = true if datum[:persistent] if (key = datum[:response][:headers].keys.detect {|k| k.casecmp('Connection') == 0 }) if datum[:response][:headers][key].casecmp('close') == 0 reset end end else reset end Excon::Response.new(datum[:response]) else datum end rescue => error reset # If we didn't get far enough to initialize datum and the middleware stack, just raise raise error if !datum datum[:error] = error if datum[:stack] datum[:stack].error_call(datum) else raise error end end