6a1fe1a77ccc5c3a2702d978cc70cb74b0cbbc85
[sdc/sdc-distribution-client.git] /
1 # urllib3/response.py
2 # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
3 #
4 # This module is part of urllib3 and is released under
5 # the MIT License: http://www.opensource.org/licenses/mit-license.php
6
7
8 import logging
9 import zlib
10 import io
11
12 from .exceptions import DecodeError
13 from .packages.six import string_types as basestring, binary_type
14 from .util import is_fp_closed
15
16
17 log = logging.getLogger(__name__)
18
19
20 class DeflateDecoder(object):
21
22     def __init__(self):
23         self._first_try = True
24         self._data = binary_type()
25         self._obj = zlib.decompressobj()
26
27     def __getattr__(self, name):
28         return getattr(self._obj, name)
29
30     def decompress(self, data):
31         if not self._first_try:
32             return self._obj.decompress(data)
33
34         self._data += data
35         try:
36             return self._obj.decompress(data)
37         except zlib.error:
38             self._first_try = False
39             self._obj = zlib.decompressobj(-zlib.MAX_WBITS)
40             try:
41                 return self.decompress(self._data)
42             finally:
43                 self._data = None
44
45
46 def _get_decoder(mode):
47     if mode == 'gzip':
48         return zlib.decompressobj(16 + zlib.MAX_WBITS)
49
50     return DeflateDecoder()
51
52
53 class HTTPResponse(io.IOBase):
54     """
55     HTTP Response container.
56
57     Backwards-compatible to httplib's HTTPResponse but the response ``body`` is
58     loaded and decoded on-demand when the ``data`` property is accessed.
59
60     Extra parameters for behaviour not present in httplib.HTTPResponse:
61
62     :param preload_content:
63         If True, the response's body will be preloaded during construction.
64
65     :param decode_content:
66         If True, attempts to decode specific content-encoding's based on headers
67         (like 'gzip' and 'deflate') will be skipped and raw data will be used
68         instead.
69
70     :param original_response:
71         When this HTTPResponse wrapper is generated from an httplib.HTTPResponse
72         object, it's convenient to include the original for debug purposes. It's
73         otherwise unused.
74     """
75
76     CONTENT_DECODERS = ['gzip', 'deflate']
77     REDIRECT_STATUSES = [301, 302, 303, 307, 308]
78
79     def __init__(self, body='', headers=None, status=0, version=0, reason=None,
80                  strict=0, preload_content=True, decode_content=True,
81                  original_response=None, pool=None, connection=None):
82         self.headers = headers or {}
83         self.status = status
84         self.version = version
85         self.reason = reason
86         self.strict = strict
87         self.decode_content = decode_content
88
89         self._decoder = None
90         self._body = body if body and isinstance(body, basestring) else None
91         self._fp = None
92         self._original_response = original_response
93         self._fp_bytes_read = 0
94
95         self._pool = pool
96         self._connection = connection
97
98         if hasattr(body, 'read'):
99             self._fp = body
100
101         if preload_content and not self._body:
102             self._body = self.read(decode_content=decode_content)
103
104     def get_redirect_location(self):
105         """
106         Should we redirect and where to?
107
108         :returns: Truthy redirect location string if we got a redirect status
109             code and valid location. ``None`` if redirect status and no
110             location. ``False`` if not a redirect status code.
111         """
112         if self.status in self.REDIRECT_STATUSES:
113             return self.headers.get('location')
114
115         return False
116
117     def release_conn(self):
118         if not self._pool or not self._connection:
119             return
120
121         self._pool._put_conn(self._connection)
122         self._connection = None
123
124     @property
125     def data(self):
126         # For backwords-compat with earlier urllib3 0.4 and earlier.
127         if self._body:
128             return self._body
129
130         if self._fp:
131             return self.read(cache_content=True)
132
133     def tell(self):
134         """
135         Obtain the number of bytes pulled over the wire so far. May differ from
136         the amount of content returned by :meth:``HTTPResponse.read`` if bytes
137         are encoded on the wire (e.g, compressed).
138         """
139         return self._fp_bytes_read
140
141     def read(self, amt=None, decode_content=None, cache_content=False):
142         """
143         Similar to :meth:`httplib.HTTPResponse.read`, but with two additional
144         parameters: ``decode_content`` and ``cache_content``.
145
146         :param amt:
147             How much of the content to read. If specified, caching is skipped
148             because it doesn't make sense to cache partial content as the full
149             response.
150
151         :param decode_content:
152             If True, will attempt to decode the body based on the
153             'content-encoding' header.
154
155         :param cache_content:
156             If True, will save the returned data such that the same result is
157             returned despite of the state of the underlying file object. This
158             is useful if you want the ``.data`` property to continue working
159             after having ``.read()`` the file object. (Overridden if ``amt`` is
160             set.)
161         """
162         # Note: content-encoding value should be case-insensitive, per RFC 2616
163         # Section 3.5
164         content_encoding = self.headers.get('content-encoding', '').lower()
165         if self._decoder is None:
166             if content_encoding in self.CONTENT_DECODERS:
167                 self._decoder = _get_decoder(content_encoding)
168         if decode_content is None:
169             decode_content = self.decode_content
170
171         if self._fp is None:
172             return
173
174         flush_decoder = False
175
176         try:
177             if amt is None:
178                 # cStringIO doesn't like amt=None
179                 data = self._fp.read()
180                 flush_decoder = True
181             else:
182                 cache_content = False
183                 data = self._fp.read(amt)
184                 if amt != 0 and not data:  # Platform-specific: Buggy versions of Python.
185                     # Close the connection when no data is returned
186                     #
187                     # This is redundant to what httplib/http.client _should_
188                     # already do.  However, versions of python released before
189                     # December 15, 2012 (http://bugs.python.org/issue16298) do not
190                     # properly close the connection in all cases. There is no harm
191                     # in redundantly calling close.
192                     self._fp.close()
193                     flush_decoder = True
194
195             self._fp_bytes_read += len(data)
196
197             try:
198                 if decode_content and self._decoder:
199                     data = self._decoder.decompress(data)
200             except (IOError, zlib.error) as e:
201                 raise DecodeError(
202                     "Received response with content-encoding: %s, but "
203                     "failed to decode it." % content_encoding,
204                     e)
205
206             if flush_decoder and decode_content and self._decoder:
207                 buf = self._decoder.decompress(binary_type())
208                 data += buf + self._decoder.flush()
209
210             if cache_content:
211                 self._body = data
212
213             return data
214
215         finally:
216             if self._original_response and self._original_response.isclosed():
217                 self.release_conn()
218
219     def stream(self, amt=2**16, decode_content=None):
220         """
221         A generator wrapper for the read() method. A call will block until
222         ``amt`` bytes have been read from the connection or until the
223         connection is closed.
224
225         :param amt:
226             How much of the content to read. The generator will return up to
227             much data per iteration, but may return less. This is particularly
228             likely when using compressed data. However, the empty string will
229             never be returned.
230
231         :param decode_content:
232             If True, will attempt to decode the body based on the
233             'content-encoding' header.
234         """
235         while not is_fp_closed(self._fp):
236             data = self.read(amt=amt, decode_content=decode_content)
237
238             if data:
239                 yield data
240
241
242     @classmethod
243     def from_httplib(ResponseCls, r, **response_kw):
244         """
245         Given an :class:`httplib.HTTPResponse` instance ``r``, return a
246         corresponding :class:`urllib3.response.HTTPResponse` object.
247
248         Remaining parameters are passed to the HTTPResponse constructor, along
249         with ``original_response=r``.
250         """
251
252         # Normalize headers between different versions of Python
253         headers = {}
254         for k, v in r.getheaders():
255             # Python 3: Header keys are returned capitalised
256             k = k.lower()
257
258             has_value = headers.get(k)
259             if has_value: # Python 3: Repeating header keys are unmerged.
260                 v = ', '.join([has_value, v])
261
262             headers[k] = v
263
264         # HTTPResponse objects in Python 3 don't have a .strict attribute
265         strict = getattr(r, 'strict', 0)
266         return ResponseCls(body=r,
267                            headers=headers,
268                            status=r.status,
269                            version=r.version,
270                            reason=r.reason,
271                            strict=strict,
272                            original_response=r,
273                            **response_kw)
274
275     # Backwards-compatibility methods for httplib.HTTPResponse
276     def getheaders(self):
277         return self.headers
278
279     def getheader(self, name, default=None):
280         return self.headers.get(name, default)
281
282     # Overrides from io.IOBase
283     def close(self):
284         if not self.closed:
285             self._fp.close()
286
287     @property
288     def closed(self):
289         if self._fp is None:
290             return True
291         elif hasattr(self._fp, 'closed'):
292             return self._fp.closed
293         elif hasattr(self._fp, 'isclosed'):  # Python 2
294             return self._fp.isclosed()
295         else:
296             return True
297
298     def fileno(self):
299         if self._fp is None:
300             raise IOError("HTTPResponse has no file to get a fileno from")
301         elif hasattr(self._fp, "fileno"):
302             return self._fp.fileno()
303         else:
304             raise IOError("The file-like object  this HTTPResponse is wrapped "
305                           "around has no file descriptor")
306
307     def flush(self):
308         if self._fp is not None and hasattr(self._fp, 'flush'):
309             return self._fp.flush()
310
311     def readable(self):
312         return True