class HTTP::Redirector
def endless_loop?
-
(Boolean)
-
def endless_loop? 2 <= @visited.count(@visited.last) end
def initialize(opts = {}) # rubocop:disable Style/OptionHash
(**opts)
-
:max_hops
(#to_i
) -- maximum allowed amount of hops -
:strict
(Boolean
) -- redirector hops policy
Parameters:
-
opts
(Hash
) --
def initialize(opts = {}) # rubocop:disable Style/OptionHash @strict = opts.fetch(:strict, true) @max_hops = opts.fetch(:max_hops, 5).to_i end
def perform(request, response)
def perform(request, response) @request = request @response = response @visited = [] while REDIRECT_CODES.include? @response.status.code @visited << "#{@request.verb} #{@request.uri}" raise TooManyRedirectsError if too_many_hops? raise EndlessRedirectError if endless_loop? @response.flush @request = redirect_to @response.headers[Headers::LOCATION] @response = yield @request end @response end
def redirect_to(uri)
-
(Request)
-
def redirect_to(uri) raise StateError, "no Location header in redirect" unless uri verb = @request.verb code = @response.status.code if UNSAFE_VERBS.include?(verb) && STRICT_SENSITIVE_CODES.include?(code) raise StateError, "can't follow #{@response.status} redirect" if @strict verb = :get end verb = :get if !SEE_OTHER_ALLOWED_VERBS.include?(verb) && 303 == code @request.redirect(uri, verb) end
def too_many_hops?
-
(Boolean)
-
def too_many_hops? 1 <= @max_hops && @max_hops < @visited.count end