class HTTP::Redirector

Constants

REDIRECT_CODES

HTTP status codes which indicate redirects

SEE_OTHER_ALLOWED_VERBS

Verbs which will remain unchanged upon See Other response.

STRICT_SENSITIVE_CODES

Codes which which should raise StateError in strict mode if original request was any of {UNSAFE_VERBS}

UNSAFE_VERBS

Insecure http verbs, which should trigger StateError in strict mode upon {STRICT_SENSITIVE_CODES}

Attributes

max_hops[R]

@!attribute [r] max_hops

Returns maximum allowed hops.
@return [Fixnum]
strict[R]

@!attribute [r] strict

Returns redirector policy.
@return [Boolean]

Public Class Methods

new(opts = {}) click to toggle source

@param [Hash] opts @option opts [Boolean] :strict (true) redirector hops policy @option opts [#to_i] :max_hops (5) maximum allowed amount of hops

# File lib/http/redirector.rb, line 42
def initialize(opts = {}) # rubocop:disable Style/OptionHash
  @strict   = opts.fetch(:strict, true)
  @max_hops = opts.fetch(:max_hops, 5).to_i
end

Public Instance Methods

perform(request, response) { |request| ... } click to toggle source

Follows redirects until non-redirect response found

# File lib/http/redirector.rb, line 48
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

Private Instance Methods

endless_loop?() click to toggle source

Check if we got into an endless loop @return [Boolean]

# File lib/http/redirector.rb, line 78
def endless_loop?
  2 <= @visited.count(@visited.last)
end
redirect_to(uri) click to toggle source

Redirect policy for follow @return [Request]

# File lib/http/redirector.rb, line 84
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
too_many_hops?() click to toggle source

Check if we reached max amount of redirect hops @return [Boolean]

# File lib/http/redirector.rb, line 72
def too_many_hops?
  1 <= @max_hops && @max_hops < @visited.count
end