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



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

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



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

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



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

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



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

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



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

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



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

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)


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

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



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

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.

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


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

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)
    response = proxy.send(:head, current_uri.path)

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

    if block_given?
      headers = {'Accept' => 'binary', 'accept-encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3'}
      response = proxy.send("request_#{method}".to_sym, current_uri.path, headers, &block)
    else
      response = proxy.send(method, current_uri.path)
    end

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

    return response
  end

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