Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: third_party/requests/packages/urllib3/response.py

Issue 24076010: Add 'requests' library to third_party. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/swarm_client
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # urllib3/response.py
2 # Copyright 2008-2012 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
11 from .exceptions import DecodeError
12 from .packages.six import string_types as basestring, binary_type
13
14
15 log = logging.getLogger(__name__)
16
17
18 class DeflateDecoder(object):
19
20 def __init__(self):
21 self._first_try = True
22 self._data = binary_type()
23 self._obj = zlib.decompressobj()
24
25 def __getattr__(self, name):
26 return getattr(self._obj, name)
27
28 def decompress(self, data):
29 if not self._first_try:
30 return self._obj.decompress(data)
31
32 self._data += data
33 try:
34 return self._obj.decompress(data)
35 except zlib.error:
36 self._first_try = False
37 self._obj = zlib.decompressobj(-zlib.MAX_WBITS)
38 try:
39 return self.decompress(self._data)
40 finally:
41 self._data = None
42
43
44 def _get_decoder(mode):
45 if mode == 'gzip':
46 return zlib.decompressobj(16 + zlib.MAX_WBITS)
47
48 return DeflateDecoder()
49
50
51 class HTTPResponse(object):
52 """
53 HTTP Response container.
54
55 Backwards-compatible to httplib's HTTPResponse but the response ``body`` is
56 loaded and decoded on-demand when the ``data`` property is accessed.
57
58 Extra parameters for behaviour not present in httplib.HTTPResponse:
59
60 :param preload_content:
61 If True, the response's body will be preloaded during construction.
62
63 :param decode_content:
64 If True, attempts to decode specific content-encoding's based on headers
65 (like 'gzip' and 'deflate') will be skipped and raw data will be used
66 instead.
67
68 :param original_response:
69 When this HTTPResponse wrapper is generated from an httplib.HTTPResponse
70 object, it's convenient to include the original for debug purposes. It's
71 otherwise unused.
72 """
73
74 CONTENT_DECODERS = ['gzip', 'deflate']
75
76 def __init__(self, body='', headers=None, status=0, version=0, reason=None,
77 strict=0, preload_content=True, decode_content=True,
78 original_response=None, pool=None, connection=None):
79 self.headers = headers or {}
80 self.status = status
81 self.version = version
82 self.reason = reason
83 self.strict = strict
84 self.decode_content = decode_content
85
86 self._decoder = None
87 self._body = body if body and isinstance(body, basestring) else None
88 self._fp = None
89 self._original_response = original_response
90
91 self._pool = pool
92 self._connection = connection
93
94 if hasattr(body, 'read'):
95 self._fp = body
96
97 if preload_content and not self._body:
98 self._body = self.read(decode_content=decode_content)
99
100 def get_redirect_location(self):
101 """
102 Should we redirect and where to?
103
104 :returns: Truthy redirect location string if we got a redirect status
105 code and valid location. ``None`` if redirect status and no
106 location. ``False`` if not a redirect status code.
107 """
108 if self.status in [301, 302, 303, 307]:
109 return self.headers.get('location')
110
111 return False
112
113 def release_conn(self):
114 if not self._pool or not self._connection:
115 return
116
117 self._pool._put_conn(self._connection)
118 self._connection = None
119
120 @property
121 def data(self):
122 # For backwords-compat with earlier urllib3 0.4 and earlier.
123 if self._body:
124 return self._body
125
126 if self._fp:
127 return self.read(cache_content=True)
128
129 def read(self, amt=None, decode_content=None, cache_content=False):
130 """
131 Similar to :meth:`httplib.HTTPResponse.read`, but with two additional
132 parameters: ``decode_content`` and ``cache_content``.
133
134 :param amt:
135 How much of the content to read. If specified, caching is skipped
136 because it doesn't make sense to cache partial content as the full
137 response.
138
139 :param decode_content:
140 If True, will attempt to decode the body based on the
141 'content-encoding' header.
142
143 :param cache_content:
144 If True, will save the returned data such that the same result is
145 returned despite of the state of the underlying file object. This
146 is useful if you want the ``.data`` property to continue working
147 after having ``.read()`` the file object. (Overridden if ``amt`` is
148 set.)
149 """
150 # Note: content-encoding value should be case-insensitive, per RFC 2616
151 # Section 3.5
152 content_encoding = self.headers.get('content-encoding', '').lower()
153 if self._decoder is None:
154 if content_encoding in self.CONTENT_DECODERS:
155 self._decoder = _get_decoder(content_encoding)
156 if decode_content is None:
157 decode_content = self.decode_content
158
159 if self._fp is None:
160 return
161
162 flush_decoder = False
163
164 try:
165 if amt is None:
166 # cStringIO doesn't like amt=None
167 data = self._fp.read()
168 flush_decoder = True
169 else:
170 cache_content = False
171 data = self._fp.read(amt)
172 if amt != 0 and not data: # Platform-specific: Buggy versions o f Python.
173 # Close the connection when no data is returned
174 #
175 # This is redundant to what httplib/http.client _should_
176 # already do. However, versions of python released before
177 # December 15, 2012 (http://bugs.python.org/issue16298) do n ot
178 # properly close the connection in all cases. There is no ha rm
179 # in redundantly calling close.
180 self._fp.close()
181 flush_decoder = True
182
183 try:
184 if decode_content and self._decoder:
185 data = self._decoder.decompress(data)
186 except (IOError, zlib.error):
187 raise DecodeError("Received response with content-encoding: %s, but "
188 "failed to decode it." % content_encoding)
189
190 if flush_decoder and self._decoder:
191 buf = self._decoder.decompress(binary_type())
192 data += buf + self._decoder.flush()
193
194 if cache_content:
195 self._body = data
196
197 return data
198
199 finally:
200 if self._original_response and self._original_response.isclosed():
201 self.release_conn()
202
203 @classmethod
204 def from_httplib(ResponseCls, r, **response_kw):
205 """
206 Given an :class:`httplib.HTTPResponse` instance ``r``, return a
207 corresponding :class:`urllib3.response.HTTPResponse` object.
208
209 Remaining parameters are passed to the HTTPResponse constructor, along
210 with ``original_response=r``.
211 """
212
213 # Normalize headers between different versions of Python
214 headers = {}
215 for k, v in r.getheaders():
216 # Python 3: Header keys are returned capitalised
217 k = k.lower()
218
219 has_value = headers.get(k)
220 if has_value: # Python 3: Repeating header keys are unmerged.
221 v = ', '.join([has_value, v])
222
223 headers[k] = v
224
225 # HTTPResponse objects in Python 3 don't have a .strict attribute
226 strict = getattr(r, 'strict', 0)
227 return ResponseCls(body=r,
228 headers=headers,
229 status=r.status,
230 version=r.version,
231 reason=r.reason,
232 strict=strict,
233 original_response=r,
234 **response_kw)
235
236 # Backwards-compatibility methods for httplib.HTTPResponse
237 def getheaders(self):
238 return self.headers
239
240 def getheader(self, name, default=None):
241 return self.headers.get(name, default)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698