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



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/puppet/util/http_proxy.rb', line 155

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_env ⇒ Object



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

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_host ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/puppet/util/http_proxy.rb', line 81

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_password ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/puppet/util/http_proxy.rb', line 119

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_port ⇒ Object



95
96
97
98
99
100
101
102
103
# File 'lib/puppet/util/http_proxy.rb', line 95

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_user ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/puppet/util/http_proxy.rb', line 105

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 ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/puppet/util/http_proxy.rb', line 133

def self.no_proxy
  no_proxy_env = ENV["no_proxy"] || ENV["NO_PROXY"]

  if no_proxy_env
    return no_proxy_env
  end

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

  return Puppet.settings[:no_proxy]
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)


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

def self.no_proxy?(dest)
  no_proxy = self.no_proxy
  unless no_proxy
    return false
  end

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

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

def self.proxy(uri)
  if http_proxy_host && !no_proxy?(uri)
    Net::HTTP.new(uri.host, uri.port, self.http_proxy_host, self.http_proxy_port, self.http_proxy_user, self.http_proxy_password)
  else
    http = Net::HTTP.new(uri.host, uri.port, nil, nil, nil, nil)
    # Net::HTTP defaults the proxy port even though we said not to
    # use one. Set it to nil so caller is not surprised
    http.proxy_port = nil
    http
  end
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


189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/puppet/util/http_proxy.rb', line 189

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, 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, headers, &block)
      else
        response = proxy.send(method, current_uri, 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