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
@!attribute [r] max_hops
Returns maximum allowed hops. @return [Fixnum]
@!attribute [r] strict
Returns redirector policy. @return [Boolean]
Public Class Methods
Source
# File lib/http/redirector.rb, line 42 def initialize(opts = {}) @strict = opts.fetch(:strict, true) @max_hops = opts.fetch(:max_hops, 5).to_i @on_redirect = opts.fetch(:on_redirect, nil) end
@param [Hash] opts @option opts [Boolean] :strict (true) redirector hops policy @option opts [#to_i] :max_hops (5) maximum allowed amount of hops
Public Instance Methods
Source
# File lib/http/redirector.rb, line 49 def perform(request, response) @request = request @response = response @visited = [] collect_cookies_from_request collect_cookies_from_response 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 # XXX(ixti): using `Array#inject` to return `nil` if no Location header. @request = redirect_to(@response.headers.get(Headers::LOCATION).inject(:+)) unless cookie_jar.empty? @request.headers.set(Headers::COOKIE, cookie_jar.cookies.map { |c| "#{c.name}=#{c.value}" }.join("; ")) end @on_redirect.call @response, @request if @on_redirect.respond_to?(:call) @response = yield @request collect_cookies_from_response end @response end
Follows redirects until non-redirect response found
Private Instance Methods
Source
# File lib/http/redirector.rb, line 129 def endless_loop? 2 <= @visited.count(@visited.last) end
Check if we got into an endless loop @return [Boolean]
Source
# File lib/http/redirector.rb, line 135 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
Redirect policy for follow @return [Request]
Source
# File lib/http/redirector.rb, line 123 def too_many_hops? 1 <= @max_hops && @max_hops < @visited.count end
Check if we reached max amount of redirect hops @return [Boolean]