master
py 82 lines 2.32 KB
Raw
1 # SPDX-License-Identifier: MIT
2 from __future__ import absolute_import
3 from ..packages.six.moves import http_client as httplib
4
5 from ..exceptions import HeaderParsingError
6
7
8 def is_fp_closed(obj):
9 """
10 Checks whether a given file-like object is closed.
11
12 :param obj:
13 The file-like object to check.
14 """
15
16 try:
17 # Check `isclosed()` first, in case Python3 doesn't set `closed`.
18 # GH Issue #928
19 return obj.isclosed()
20 except AttributeError:
21 pass
22
23 try:
24 # Check via the official file-like-object way.
25 return obj.closed
26 except AttributeError:
27 pass
28
29 try:
30 # Check if the object is a container for another file-like object that
31 # gets released on exhaustion (e.g. HTTPResponse).
32 return obj.fp is None
33 except AttributeError:
34 pass
35
36 raise ValueError("Unable to determine whether fp is closed.")
37
38
39 def assert_header_parsing(headers):
40 """
41 Asserts whether all headers have been successfully parsed.
42 Extracts encountered errors from the result of parsing headers.
43
44 Only works on Python 3.
45
46 :param headers: Headers to verify.
47 :type headers: `httplib.HTTPMessage`.
48
49 :raises urllib3.exceptions.HeaderParsingError:
50 If parsing errors are found.
51 """
52
53 # This will fail silently if we pass in the wrong kind of parameter.
54 # To make debugging easier add an explicit check.
55 if not isinstance(headers, httplib.HTTPMessage):
56 raise TypeError('expected httplib.Message, got {0}.'.format(
57 type(headers)))
58
59 defects = getattr(headers, 'defects', None)
60 get_payload = getattr(headers, 'get_payload', None)
61
62 unparsed_data = None
63 if get_payload: # Platform-specific: Python 3.
64 unparsed_data = get_payload()
65
66 if defects or unparsed_data:
67 raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data)
68
69
70 def is_response_to_head(response):
71 """
72 Checks whether the request of a response has been a HEAD-request.
73 Handles the quirks of AppEngine.
74
75 :param conn:
76 :type conn: :class:`httplib.HTTPResponse`
77 """
78 # FIXME: Can we do this somehow without accessing private httplib _method?
79 method = response._method
80 if isinstance(method, int): # Platform-specific: Appengine
81 return method == 3
82 return method.upper() == 'HEAD'