File: redirector.rb

package info (click to toggle)
puppet-agent 7.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 19,092 kB
  • sloc: ruby: 245,074; sh: 456; makefile: 38; xml: 33
file content (81 lines) | stat: -rw-r--r-- 2,590 bytes parent folder | download
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