205 lines
5.8 KiB
Ruby
205 lines
5.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Faraday
|
|
# @!parse
|
|
# # @!attribute method
|
|
# # @return [Symbol] HTTP method (`:get`, `:post`)
|
|
# #
|
|
# # @!attribute body
|
|
# # @return [String] The request body that will eventually be converted to a
|
|
# # string.
|
|
# #
|
|
# # @!attribute url
|
|
# # @return [URI] URI instance for the current request.
|
|
# #
|
|
# # @!attribute request
|
|
# # @return [Hash] options for configuring the request.
|
|
# # Options for configuring the request.
|
|
# #
|
|
# # - `:timeout` - time limit for the entire request (Integer in
|
|
# # seconds)
|
|
# # - `:open_timeout` - time limit for just the connection phase (e.g.
|
|
# # handshake) (Integer in seconds)
|
|
# # - `:read_timeout` - time limit for the first response byte received from
|
|
# # the server (Integer in seconds)
|
|
# # - `:write_timeout` - time limit for the client to send the request to the
|
|
# # server (Integer in seconds)
|
|
# # - `:on_data` - Proc for streaming
|
|
# # - `:proxy` - Hash of proxy options
|
|
# # - `:uri` - Proxy server URI
|
|
# # - `:user` - Proxy server username
|
|
# # - `:password` - Proxy server password
|
|
# #
|
|
# # @!attribute request_headers
|
|
# # @return [Hash] HTTP Headers to be sent to the server.
|
|
# #
|
|
# # @!attribute ssl
|
|
# # @return [Hash] options for configuring SSL requests
|
|
# #
|
|
# # @!attribute parallel_manager
|
|
# # @return [Object] sent if the connection is in parallel mode
|
|
# #
|
|
# # @!attribute params
|
|
# # @return [Hash]
|
|
# #
|
|
# # @!attribute response
|
|
# # @return [Response]
|
|
# #
|
|
# # @!attribute response_headers
|
|
# # @return [Hash] HTTP headers from the server
|
|
# #
|
|
# # @!attribute status
|
|
# # @return [Integer] HTTP response status code
|
|
# #
|
|
# # @!attribute reason_phrase
|
|
# # @return [String]
|
|
# class Env < Options; end
|
|
Env = Options.new(:method, :request_body, :url, :request,
|
|
:request_headers, :ssl, :parallel_manager, :params,
|
|
:response, :response_headers, :status,
|
|
:reason_phrase, :response_body) do
|
|
const_set(:ContentLength, 'Content-Length')
|
|
const_set(:StatusesWithoutBody, Set.new([204, 304]))
|
|
const_set(:SuccessfulStatuses, (200..299))
|
|
|
|
# A Set of HTTP verbs that typically send a body. If no body is set for
|
|
# these requests, the Content-Length header is set to 0.
|
|
const_set(:MethodsWithBodies, Set.new(Faraday::METHODS_WITH_BODY.map(&:to_sym)))
|
|
|
|
options request: RequestOptions,
|
|
request_headers: Utils::Headers, response_headers: Utils::Headers
|
|
|
|
extend Forwardable
|
|
|
|
def_delegators :request, :params_encoder
|
|
|
|
# Build a new Env from given value. Respects and updates `custom_members`.
|
|
#
|
|
# @param value [Object] a value fitting Option.from(v).
|
|
# @return [Env] from given value
|
|
def self.from(value)
|
|
env = super(value)
|
|
if value.respond_to?(:custom_members)
|
|
env.custom_members.update(value.custom_members)
|
|
end
|
|
env
|
|
end
|
|
|
|
# @param key [Object]
|
|
def [](key)
|
|
return self[current_body] if key == :body
|
|
|
|
if in_member_set?(key)
|
|
super(key)
|
|
else
|
|
custom_members[key]
|
|
end
|
|
end
|
|
|
|
# @param key [Object]
|
|
# @param value [Object]
|
|
def []=(key, value)
|
|
if key == :body
|
|
super(current_body, value)
|
|
return
|
|
end
|
|
|
|
if in_member_set?(key)
|
|
super(key, value)
|
|
else
|
|
custom_members[key] = value
|
|
end
|
|
end
|
|
|
|
def current_body
|
|
!!status ? :response_body : :request_body
|
|
end
|
|
|
|
def body
|
|
self[:body]
|
|
end
|
|
|
|
def body=(value)
|
|
self[:body] = value
|
|
end
|
|
|
|
# @return [Boolean] true if status is in the set of {SuccessfulStatuses}.
|
|
def success?
|
|
Env::SuccessfulStatuses.include?(status)
|
|
end
|
|
|
|
# @return [Boolean] true if there's no body yet, and the method is in the
|
|
# set of {Env::MethodsWithBodies}.
|
|
def needs_body?
|
|
!body && Env::MethodsWithBodies.include?(method)
|
|
end
|
|
|
|
# Sets content length to zero and the body to the empty string.
|
|
def clear_body
|
|
request_headers[Env::ContentLength] = '0'
|
|
self.body = +''
|
|
end
|
|
|
|
# @return [Boolean] true if the status isn't in the set of
|
|
# {Env::StatusesWithoutBody}.
|
|
def parse_body?
|
|
!Env::StatusesWithoutBody.include?(status)
|
|
end
|
|
|
|
# @return [Boolean] true if there is a parallel_manager
|
|
def parallel?
|
|
!!parallel_manager
|
|
end
|
|
|
|
def inspect
|
|
attrs = [nil]
|
|
members.each do |mem|
|
|
if (value = send(mem))
|
|
attrs << "@#{mem}=#{value.inspect}"
|
|
end
|
|
end
|
|
attrs << "@custom=#{custom_members.inspect}" unless custom_members.empty?
|
|
%(#<#{self.class}#{attrs.join(' ')}>)
|
|
end
|
|
|
|
def stream_response?
|
|
request.stream_response?
|
|
end
|
|
|
|
def stream_response(&block)
|
|
size = 0
|
|
yielded = false
|
|
block_result = block.call do |chunk| # rubocop:disable Performance/RedundantBlockCall
|
|
if chunk.bytesize.positive? || size.positive?
|
|
yielded = true
|
|
size += chunk.bytesize
|
|
request.on_data.call(chunk, size, self)
|
|
end
|
|
end
|
|
request.on_data.call(+'', 0, self) unless yielded
|
|
block_result
|
|
end
|
|
|
|
# @private
|
|
def custom_members
|
|
@custom_members ||= {}
|
|
end
|
|
|
|
# @private
|
|
if members.first.is_a?(Symbol)
|
|
def in_member_set?(key)
|
|
self.class.member_set.include?(key.to_sym)
|
|
end
|
|
else
|
|
def in_member_set?(key)
|
|
self.class.member_set.include?(key.to_s)
|
|
end
|
|
end
|
|
|
|
# @private
|
|
def self.member_set
|
|
@member_set ||= Set.new(members)
|
|
end
|
|
end
|
|
end
|