1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
# Handle HTTP redirects
#
# @api private
class Puppet::HTTP::Redirector
# Create a new redirect handler
#
# @param [Integer] redirect_limit maximum number of redirects allowed
#
# @api private
def initialize(redirect_limit)
@redirect_limit = redirect_limit
end
# Determine of the HTTP response code indicates a redirect
#
# @param [Net::HTTP] request request that received the response
# @param [Puppet::HTTP::Response] response
#
# @return [Boolean] true if the response code is 301, 302, or 307.
#
# @api private
def redirect?(request, response)
# Net::HTTPRedirection is not used because historically puppet
# has only handled these, and we're not a browser
case response.code
when 301, 302, 307
true
else
false
end
end
# Implement the HTTP request redirection
#
# @param [Net::HTTP] request request that has been redirected
# @param [Puppet::HTTP::Response] response
# @param [Integer] redirects the current number of redirects
#
# @return [Net::HTTP] A new request based on the original request, but with
# the redirected location
#
# @api private
def redirect_to(request, response, redirects)
raise Puppet::HTTP::TooManyRedirects.new(request.uri) if redirects >= @redirect_limit
location = parse_location(response)
url = request.uri.merge(location)
new_request = request.class.new(url)
new_request.body = request.body
request.each do |header, value|
unless Puppet[:location_trusted]
# skip adding potentially sensitive header to other hosts
next if header.casecmp('Authorization').zero? && request.uri.host.casecmp(location.host) != 0
next if header.casecmp('Cookie').zero? && request.uri.host.casecmp(location.host) != 0
end
new_request[header] = value
end
# mimic private Net::HTTP#addr_port
new_request['Host'] = if (location.scheme == 'https' && location.port == 443) ||
(location.scheme == 'http' && location.port == 80)
location.host
else
"#{location.host}:#{location.port}"
end
new_request
end
private
def parse_location(response)
location = response['location']
raise Puppet::HTTP::ProtocolError.new(_("Location response header is missing")) unless location
URI.parse(location)
rescue URI::InvalidURIError => e
raise Puppet::HTTP::ProtocolError.new(_("Location URI is invalid: %{detail}") % { detail: e.message}, e)
end
end
|