Module: Puppet::Util::HttpProxy

Defined in:
lib/puppet/util/http_proxy.rb

Class Method Summary collapse

Class Method Details

.get_http_object(uri) ⇒ Net::HTTP::Proxy

Return a Net::HTTP::Proxy object.

This method optionally configures SSL correctly if the URI scheme is ‘https’, including setting up the root certificate store so remote server SSL certificates can be validated.

Parameters:

  • uri (URI)

    The URI that is to be accessed.

Returns:

  • (Net::HTTP::Proxy)

    object constructed tailored for the passed URI



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/puppet/util/http_proxy.rb', line 138

def self.get_http_object(uri)
  proxy = proxy(uri)

  if uri.scheme == 'https'
    cert_store = OpenSSL::X509::Store.new
    cert_store.set_default_paths

    proxy.use_ssl = true
    proxy.verify_mode = OpenSSL::SSL::VERIFY_PEER
    proxy.cert_store = cert_store
  end

  if Puppet[:http_debug]
    proxy.set_debug_output($stderr)
  end

  proxy.open_timeout = Puppet[:http_connect_timeout]
  proxy.read_timeout = Puppet[:http_read_timeout]

  proxy
end

.http_proxy_envObject



16
17
18
19
20
21
22
23
24
25
# File 'lib/puppet/util/http_proxy.rb', line 16

def self.http_proxy_env
  # Returns a URI object if proxy is set, or nil
  proxy_env = ENV["http_proxy"] || ENV["HTTP_PROXY"]
  begin
    return URI.parse(proxy_env) if proxy_env
  rescue URI::InvalidURIError
    return nil
  end
  return nil
end

.http_proxy_hostObject



78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/puppet/util/http_proxy.rb', line 78

def self.http_proxy_host
  env = self.http_proxy_env

  if env and env.host
    return env.host
  end

  if Puppet.settings[:http_proxy_host] == 'none'
    return nil
  end

  return Puppet.settings[:http_proxy_host]
end

.http_proxy_passwordObject



116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/puppet/util/http_proxy.rb', line 116

def self.http_proxy_password
  env = self.http_proxy_env

  if env and env.password
    return env.password
  end

  if Puppet.settings[:http_proxy_user] == 'none' or Puppet.settings[:http_proxy_password] == 'none'
    return nil
  end

  return Puppet.settings[:http_proxy_password]
end

.http_proxy_portObject



92
93
94
95
96
97
98
99
100
# File 'lib/puppet/util/http_proxy.rb', line 92

def self.http_proxy_port
  env = self.http_proxy_env

  if env and env.port
    return env.port
  end

  return Puppet.settings[:http_proxy_port]
end

.http_proxy_userObject



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/puppet/util/http_proxy.rb', line 102

def self.http_proxy_user
  env = self.http_proxy_env

  if env and env.user
    return env.user
  end

  if Puppet.settings[:http_proxy_user] == 'none'
    return nil
  end

  return Puppet.settings[:http_proxy_user]
end

.no_proxy?(dest) ⇒ Boolean

The documentation around the format of the no_proxy variable seems inconsistent. Some suggests the use of the * as a way of matching any hosts under a domain, e.g.:

*.example.com

Other documentation suggests that just a leading ‘.’ indicates a domain level exclusion, e.g.:

.example.com

We’ll accommodate both here.

Returns:

  • (Boolean)


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
# File 'lib/puppet/util/http_proxy.rb', line 35

def self.no_proxy?(dest)
  unless no_proxy_env = ENV["no_proxy"] || ENV["NO_PROXY"]
    return false
  end

  unless dest.is_a? URI
    begin
      dest = URI.parse(dest)
    rescue URI::InvalidURIError
      return false
    end
  end

  no_proxy_env.split(/\s*,\s*/).each do |d|
    host, port = d.split(':')
    host = Regexp.escape(host).gsub('\*', '.*')

    #If the host of this no_proxy value starts with '.', this entry is
    #a domain level entry. Don't pin the regex to the beginning of the entry.
    #If it does not start with a '.' then it is a host specific entry and
    #should be matched to the destination starting at the beginning.
    unless host =~ /^\\\./
      host = "^#{host}"
    end

    #If this no_proxy entry specifies a port, we want to match it against
    #the destination port.  Otherwise just match hosts.
    if port
      no_proxy_regex  = %r(#{host}:#{port}$)
      dest_string     = "#{dest.host}:#{dest.port}"
    else
      no_proxy_regex  = %r(#{host}$)
      dest_string     = "#{dest.host}"
    end

    if no_proxy_regex.match(dest_string)
      return true
    end
  end

  return false
end

.proxy(uri) ⇒ Object



6
7
8
9
10
11
12
13
14
# File 'lib/puppet/util/http_proxy.rb', line 6

def self.proxy(uri)
  if self.no_proxy?(uri)
    proxy_class = Net::HTTP::Proxy(nil)
  else
    proxy_class = Net::HTTP::Proxy(self.http_proxy_host, self.http_proxy_port, self.http_proxy_user, self.http_proxy_password)
  end

  return proxy_class.new(uri.host, uri.port)
end

.request_with_redirects(uri, method, redirect_limit = 10, &block) ⇒ Net::HTTPResponse

Retrieve a document through HTTP(s), following redirects if necessary. The returned response body may be compressed, and it is the caller’s responsibility to decompress it based on the ‘content-encoding’ header.

Based on the the client implementation in the HTTP pool.

Parameters:

  • uri (URI)

    The address of the resource to retrieve.

  • method (symbol)

    The name of the Net::HTTP method to use, typically :get, :head, :post etc.

  • redirect_limit (FixNum) (defaults to: 10)

    The number of redirections that can be followed.

Returns:

  • (Net::HTTPResponse)

    a response object

Raises:

  • (RedirectionLimitExceededException)

See Also:

  • Network::HTTP::Connection#request_with_redirects


172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/puppet/util/http_proxy.rb', line 172

def self.request_with_redirects(uri, method, redirect_limit = 10, &block)
  current_uri = uri
  response = nil

  0.upto(redirect_limit) do |redirection|
    proxy = get_http_object(current_uri)

    headers = { 'Accept' => '*/*', 'User-Agent' => Puppet[:http_user_agent] }
    if Puppet.features.zlib?
      headers.merge!({"Accept-Encoding" => Puppet::Network::HTTP::Compression::ACCEPT_ENCODING})
    end

    response = proxy.send(:head, current_uri.path, headers)
    Puppet.debug("HTTP HEAD request to #{current_uri} returned #{response.code} #{response.message}")

    if [301, 302, 307].include?(response.code.to_i)
      # handle the redirection
      current_uri = URI.parse(response['location'])
      next
    end

    if method != :head
      if block_given?
        response = proxy.send("request_#{method}".to_sym, current_uri.path, headers, &block)
      else
        response = proxy.send(method, current_uri.path, headers)
      end

      Puppet.debug("HTTP #{method.to_s.upcase} request to #{current_uri} returned #{response.code} #{response.message}")
    end

    return response
  end

  raise RedirectionLimitExceededException, _("Too many HTTP redirections for %{uri}") % { uri: uri }
end