blob: 8c1a80222d00f78d6f8282f82e8633d563e0312f [file] [log] [blame]
Jordan Pittier00f25962016-03-18 17:10:07 +01001# Copyright 2016 OpenStack Foundation
Matthew Treinish9e26ca82016-02-23 11:43:20 -05002# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
Jordan Pittierb84f2d42016-12-21 19:02:15 +010016import six
Jordan Pittier00f25962016-03-18 17:10:07 +010017import urllib3
Matthew Treinish9e26ca82016-02-23 11:43:20 -050018
19
Matthew Treinish74514402016-09-01 11:44:57 -040020class ClosingProxyHttp(urllib3.ProxyManager):
21 def __init__(self, proxy_url, disable_ssl_certificate_validation=False,
Jens Harbott3ffa54e2018-07-04 11:59:49 +000022 ca_certs=None, timeout=None, follow_redirects=True):
23 self.follow_redirects = follow_redirects
Matthew Treinish74514402016-09-01 11:44:57 -040024 kwargs = {}
25
26 if disable_ssl_certificate_validation:
27 urllib3.disable_warnings()
28 kwargs['cert_reqs'] = 'CERT_NONE'
29 elif ca_certs:
30 kwargs['cert_reqs'] = 'CERT_REQUIRED'
31 kwargs['ca_certs'] = ca_certs
32
33 if timeout:
34 kwargs['timeout'] = timeout
35
36 super(ClosingProxyHttp, self).__init__(proxy_url, **kwargs)
37
38 def request(self, url, method, *args, **kwargs):
39
40 class Response(dict):
41 def __init__(self, info):
42 for key, value in info.getheaders().items():
43 self[key.lower()] = value
44 self.status = info.status
45 self['status'] = str(self.status)
46 self.reason = info.reason
47 self.version = info.version
48 self['content-location'] = url
49
50 original_headers = kwargs.get('headers', {})
51 new_headers = dict(original_headers, connection='close')
52 new_kwargs = dict(kwargs, headers=new_headers)
53
Jens Harbott3ffa54e2018-07-04 11:59:49 +000054 if self.follow_redirects:
55 # Follow up to 5 redirections. Don't raise an exception if
56 # it's exceeded but return the HTTP 3XX response instead.
57 retry = urllib3.util.Retry(raise_on_redirect=False, redirect=5)
58 else:
59 # Do not follow redirections. Don't raise an exception if
60 # a redirect is found, but return the HTTP 3XX response instead.
61 retry = urllib3.util.Retry(redirect=False)
Matthew Treinish74514402016-09-01 11:44:57 -040062 r = super(ClosingProxyHttp, self).request(method, url, retries=retry,
63 *args, **new_kwargs)
64 return Response(r), r.data
65
66
Jordan Pittier00f25962016-03-18 17:10:07 +010067class ClosingHttp(urllib3.poolmanager.PoolManager):
68 def __init__(self, disable_ssl_certificate_validation=False,
Jens Harbott3ffa54e2018-07-04 11:59:49 +000069 ca_certs=None, timeout=None, follow_redirects=True):
70 self.follow_redirects = follow_redirects
Jordan Pittier00f25962016-03-18 17:10:07 +010071 kwargs = {}
72
73 if disable_ssl_certificate_validation:
74 urllib3.disable_warnings()
75 kwargs['cert_reqs'] = 'CERT_NONE'
Anna Pankiewiczc6a79052017-07-24 10:38:35 -050076 elif ca_certs:
Jordan Pittier00f25962016-03-18 17:10:07 +010077 kwargs['cert_reqs'] = 'CERT_REQUIRED'
78 kwargs['ca_certs'] = ca_certs
79
zhufl071e94c2016-07-12 10:26:34 +080080 if timeout:
81 kwargs['timeout'] = timeout
82
Jordan Pittier00f25962016-03-18 17:10:07 +010083 super(ClosingHttp, self).__init__(**kwargs)
84
85 def request(self, url, method, *args, **kwargs):
86
87 class Response(dict):
88 def __init__(self, info):
89 for key, value in info.getheaders().items():
Jordan Pittierb84f2d42016-12-21 19:02:15 +010090 # We assume HTTP header name to be string, not random
91 # bytes, thus ensure we have string keys.
92 self[six.u(key).lower()] = value
Jordan Pittier00f25962016-03-18 17:10:07 +010093 self.status = info.status
94 self['status'] = str(self.status)
95 self.reason = info.reason
96 self.version = info.version
97 self['content-location'] = url
98
Matthew Treinish9e26ca82016-02-23 11:43:20 -050099 original_headers = kwargs.get('headers', {})
100 new_headers = dict(original_headers, connection='close')
101 new_kwargs = dict(kwargs, headers=new_headers)
Jordan Pittier00f25962016-03-18 17:10:07 +0100102
Jens Harbott3ffa54e2018-07-04 11:59:49 +0000103 if self.follow_redirects:
104 # Follow up to 5 redirections. Don't raise an exception if
105 # it's exceeded but return the HTTP 3XX response instead.
106 retry = urllib3.util.Retry(raise_on_redirect=False, redirect=5)
107 else:
108 # Do not follow redirections. Don't raise an exception if
109 # a redirect is found, but return the HTTP 3XX response instead.
110 retry = urllib3.util.Retry(redirect=False)
Jordan Pittier00f25962016-03-18 17:10:07 +0100111 r = super(ClosingHttp, self).request(method, url, retries=retry,
112 *args, **new_kwargs)
113 return Response(r), r.data