11
11
# License for the specific language governing permissions and limitations
12
12
# under the License.
13
13
14
+ import logging
14
15
import os
15
16
import sys
16
17
17
- import certifi
18
- import urllib3
18
+ import httpx
19
19
20
20
from gabbi .handlers import jsonhandler
21
21
from gabbi import utils
22
22
23
- # Disable SSL warnings otherwise tests which process stderr will get
24
- # extra information.
25
- urllib3 .disable_warnings ()
23
+ logging .getLogger ('httpx' ).setLevel (logging .WARNING )
26
24
27
25
28
- class Http ( urllib3 . PoolManager ) :
29
- """A subclass of the ``urllib3.PoolManager`` to munge the data .
26
+ class Http :
27
+ """A class to munge the HTTP response .
30
28
31
29
This transforms the response to look more like what httplib2
32
30
provided when it was used as the HTTP client.
33
31
"""
34
32
33
+ def __init__ (self , ** kwargs ):
34
+ self .extensions = {}
35
+ if 'server_hostname' in kwargs :
36
+ self .extensions ['sni_hostname' ] = kwargs ['server_hostname' ]
37
+ self .client = httpx .Client (verify = kwargs .get ('cert_validate' , True ))
38
+
35
39
def request (self , absolute_uri , method , body , headers , redirect , timeout ):
36
- if redirect :
37
- retry = urllib3 .util .Retry (raise_on_redirect = False , redirect = 5 )
38
- else :
39
- retry = urllib3 .util .Retry (total = False , redirect = False )
40
- response = super (Http , self ).request (
41
- method ,
42
- absolute_uri ,
43
- body = body ,
40
+ response = self .client .request (
41
+ method = method ,
42
+ url = absolute_uri ,
44
43
headers = headers ,
45
- retries = retry ,
44
+ content = body ,
46
45
timeout = timeout ,
46
+ follow_redirects = redirect ,
47
+ extensions = self .extensions ,
47
48
)
48
49
49
50
# Transform response into something akin to httplib2
50
51
# response object.
51
- content = response .data
52
- status = response .status
53
- reason = response .reason
52
+ content = response .content
53
+ status = response .status_code
54
+ reason = response .reason_phrase
55
+ http_version = response .http_version
54
56
headers = response .headers
55
57
headers ['status' ] = str (status )
56
- headers ['reason' ] = reason
58
+ headers ['reason' ] = str (reason )
59
+ headers ['http_protocol_version' ] = str (http_version )
57
60
58
- # Shut down open PoolManagers whose connections have completed to
59
- # save on socket file descriptors.
60
- self .clear ()
61
61
return headers , content
62
62
63
63
@@ -87,6 +87,7 @@ class VerboseHttp(Http):
87
87
HEADER_BLACKLIST = [
88
88
'status' ,
89
89
'reason' ,
90
+ 'http_protocol_version' ,
90
91
]
91
92
92
93
REQUEST_PREFIX = '>'
@@ -106,27 +107,26 @@ def __init__(self, **kwargs):
106
107
self ._stream = kwargs .pop ('stream' )
107
108
if self ._use_color :
108
109
self .colorize = utils .get_colorizer (self ._stream )
109
- super (VerboseHttp , self ).__init__ (** kwargs )
110
+ super ().__init__ (** kwargs )
110
111
111
112
def request (self , absolute_uri , method , body , headers , redirect , timeout ):
112
113
"""Display request parameters before requesting."""
113
114
114
- self ._verbose_output ('#### %s ####' % self . caption ,
115
+ self ._verbose_output (f '#### { self . caption } ####' ,
115
116
color = self .COLORMAP ['caption' ])
116
- self ._verbose_output ('%s %s' % ( method , absolute_uri ) ,
117
+ self ._verbose_output (f' { method } { absolute_uri } ' ,
117
118
prefix = self .REQUEST_PREFIX ,
118
119
color = self .COLORMAP ['request' ])
119
120
120
121
self ._print_headers (headers , prefix = self .REQUEST_PREFIX )
121
122
self ._print_body (headers , body )
122
123
123
- response , content = super (VerboseHttp , self ).request (
124
+ response , content = super ().request (
124
125
absolute_uri , method , body , headers , redirect , timeout )
125
126
126
127
# Blank line for division
127
128
self ._verbose_output ('' )
128
- self ._verbose_output ('%s %s' % (response ['status' ],
129
- response ['reason' ]),
129
+ self ._verbose_output (f'{ response ["status" ]} { response ["reason" ]} ' ,
130
130
prefix = self .RESPONSE_PREFIX ,
131
131
color = self .COLORMAP ['status' ])
132
132
self ._print_headers (response , prefix = self .RESPONSE_PREFIX )
@@ -172,8 +172,8 @@ def _print_body(self, headers, content):
172
172
173
173
def _print_header (self , name , value , prefix = '' , stream = None ):
174
174
"""Output one single header."""
175
- header = self .colorize (self .COLORMAP ['header' ], "%s:" % name )
176
- self ._verbose_output ("%s %s" % ( header , value ) , prefix = prefix ,
175
+ header = self .colorize (self .COLORMAP ['header' ], f' { name } :' )
176
+ self ._verbose_output (f' { header } { value } ' , prefix = prefix ,
177
177
stream = stream )
178
178
179
179
def _verbose_output (self , message , prefix = '' , color = None , stream = None ):
@@ -194,29 +194,23 @@ def get_http(
194
194
timeout = 30 ,
195
195
):
196
196
"""Return an ``Http`` class for making requests."""
197
- cert_validation = {'cert_reqs' : 'CERT_NONE' } if not cert_validate else {}
198
-
199
197
if not verbose :
200
198
return Http (
201
- strict = True ,
202
- ca_certs = certifi .where (),
203
199
server_hostname = hostname ,
204
200
timeout = timeout ,
205
- ** cert_validation
201
+ cert_validate = cert_validate ,
206
202
)
207
203
208
- headers = False if verbose == 'body' else True
209
- body = False if verbose == 'headers' else True
204
+ headers = verbose != 'body'
205
+ body = verbose != 'headers'
210
206
211
207
return VerboseHttp (
212
208
headers = headers ,
213
209
body = body ,
214
210
stream = sys .stdout ,
215
211
caption = caption ,
216
212
colorize = True ,
217
- strict = True ,
218
- ca_certs = certifi .where (),
219
213
server_hostname = hostname ,
220
214
timeout = timeout ,
221
- ** cert_validation
215
+ cert_validate = cert_validate ,
222
216
)
0 commit comments