~rcj/vmbuilder/jenkins_kvm-test

« back to all changes in this revision

Viewing changes to pylib/requests/packages/urllib3/response.py

  • Committer: Ben Howard
  • Date: 2014-08-19 20:30:00 UTC
  • Revision ID: ben.howard@ubuntu.com-20140819203000-9gfgaryo1w41orxu
12.04 does not ship with a version of python3-requests, so we need
to provided it.

Show diffs side-by-side

added added

removed removed

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