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: client/third_party/google/auth/transport/urllib3.py

Issue 2953253003: Replace custom blob gRPC API with ByteStream (Closed)
Patch Set: Import ndb directly to test code Created 3 years, 5 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
OLDNEW
(Empty)
1 # Copyright 2016 Google Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """Transport adapter for urllib3."""
16
17 from __future__ import absolute_import
18
19 import logging
20
21
22 # Certifi is Mozilla's certificate bundle. Urllib3 needs a certificate bundle
23 # to verify HTTPS requests, and certifi is the recommended and most reliable
24 # way to get a root certificate bundle. See
25 # http://urllib3.readthedocs.io/en/latest/user-guide.html\
26 # #certificate-verification
27 # For more details.
28 try:
29 import certifi
30 except ImportError: # pragma: NO COVER
31 certifi = None
32
33 try:
34 import urllib3
35 except ImportError: # pragma: NO COVER
36 raise ImportError(
37 'The urllib3 library is not installed, please install the urllib3 '
38 'package to use the urllib3 transport.')
39 import urllib3.exceptions
40
41 from google.auth import exceptions
42 from google.auth import transport
43
44 _LOGGER = logging.getLogger(__name__)
45
46
47 class _Response(transport.Response):
48 """urllib3 transport response adapter.
49
50 Args:
51 response (urllib3.response.HTTPResponse): The raw urllib3 response.
52 """
53 def __init__(self, response):
54 self._response = response
55
56 @property
57 def status(self):
58 return self._response.status
59
60 @property
61 def headers(self):
62 return self._response.headers
63
64 @property
65 def data(self):
66 return self._response.data
67
68
69 class Request(transport.Request):
70 """urllib3 request adapter.
71
72 This class is used internally for making requests using various transports
73 in a consistent way. If you use :class:`AuthorizedHttp` you do not need
74 to construct or use this class directly.
75
76 This class can be useful if you want to manually refresh a
77 :class:`~google.auth.credentials.Credentials` instance::
78
79 import google.auth.transport.urllib3
80 import urllib3
81
82 http = urllib3.PoolManager()
83 request = google.auth.transport.urllib3.Request(http)
84
85 credentials.refresh(request)
86
87 Args:
88 http (urllib3.request.RequestMethods): An instance of any urllib3
89 class that implements :class:`~urllib3.request.RequestMethods`,
90 usually :class:`urllib3.PoolManager`.
91
92 .. automethod:: __call__
93 """
94 def __init__(self, http):
95 self.http = http
96
97 def __call__(self, url, method='GET', body=None, headers=None,
98 timeout=None, **kwargs):
99 """Make an HTTP request using urllib3.
100
101 Args:
102 url (str): The URI to be requested.
103 method (str): The HTTP method to use for the request. Defaults
104 to 'GET'.
105 body (bytes): The payload / body in HTTP request.
106 headers (Mapping[str, str]): Request headers.
107 timeout (Optional[int]): The number of seconds to wait for a
108 response from the server. If not specified or if None, the
109 urllib3 default timeout will be used.
110 kwargs: Additional arguments passed throught to the underlying
111 urllib3 :meth:`urlopen` method.
112
113 Returns:
114 google.auth.transport.Response: The HTTP response.
115
116 Raises:
117 google.auth.exceptions.TransportError: If any exception occurred.
118 """
119 # urllib3 uses a sentinel default value for timeout, so only set it if
120 # specified.
121 if timeout is not None:
122 kwargs['timeout'] = timeout
123
124 try:
125 _LOGGER.debug('Making request: %s %s', method, url)
126 response = self.http.request(
127 method, url, body=body, headers=headers, **kwargs)
128 return _Response(response)
129 except urllib3.exceptions.HTTPError as exc:
130 raise exceptions.TransportError(exc)
131
132
133 def _make_default_http():
134 if certifi is not None:
135 return urllib3.PoolManager(
136 cert_reqs='CERT_REQUIRED',
137 ca_certs=certifi.where())
138 else:
139 return urllib3.PoolManager()
140
141
142 class AuthorizedHttp(urllib3.request.RequestMethods):
143 """A urllib3 HTTP class with credentials.
144
145 This class is used to perform requests to API endpoints that require
146 authorization::
147
148 from google.auth.transport.urllib3 import AuthorizedHttp
149
150 authed_http = AuthorizedHttp(credentials)
151
152 response = authed_http.request(
153 'GET', 'https://www.googleapis.com/storage/v1/b')
154
155 This class implements :class:`urllib3.request.RequestMethods` and can be
156 used just like any other :class:`urllib3.PoolManager`.
157
158 The underlying :meth:`urlopen` implementation handles adding the
159 credentials' headers to the request and refreshing credentials as needed.
160
161 Args:
162 credentials (google.auth.credentials.Credentials): The credentials to
163 add to the request.
164 http (urllib3.PoolManager): The underlying HTTP object to
165 use to make requests. If not specified, a
166 :class:`urllib3.PoolManager` instance will be constructed with
167 sane defaults.
168 refresh_status_codes (Sequence[int]): Which HTTP status codes indicate
169 that credentials should be refreshed and the request should be
170 retried.
171 max_refresh_attempts (int): The maximum number of times to attempt to
172 refresh the credentials and retry the request.
173 """
174 def __init__(self, credentials, http=None,
175 refresh_status_codes=transport.DEFAULT_REFRESH_STATUS_CODES,
176 max_refresh_attempts=transport.DEFAULT_MAX_REFRESH_ATTEMPTS):
177
178 if http is None:
179 http = _make_default_http()
180
181 self.http = http
182 self.credentials = credentials
183 self._refresh_status_codes = refresh_status_codes
184 self._max_refresh_attempts = max_refresh_attempts
185 # Request instance used by internal methods (for example,
186 # credentials.refresh).
187 self._request = Request(self.http)
188
189 def urlopen(self, method, url, body=None, headers=None, **kwargs):
190 """Implementation of urllib3's urlopen."""
191
192 # Use a kwarg for this instead of an attribute to maintain
193 # thread-safety.
194 _credential_refresh_attempt = kwargs.pop(
195 '_credential_refresh_attempt', 0)
196
197 if headers is None:
198 headers = self.headers
199
200 # Make a copy of the headers. They will be modified by the credentials
201 # and we want to pass the original headers if we recurse.
202 request_headers = headers.copy()
203
204 self.credentials.before_request(
205 self._request, method, url, request_headers)
206
207 response = self.http.urlopen(
208 method, url, body=body, headers=request_headers, **kwargs)
209
210 # If the response indicated that the credentials needed to be
211 # refreshed, then refresh the credentials and re-attempt the
212 # request.
213 # A stored token may expire between the time it is retrieved and
214 # the time the request is made, so we may need to try twice.
215 # The reason urllib3's retries aren't used is because they
216 # don't allow you to modify the request headers. :/
217 if (response.status in self._refresh_status_codes
218 and _credential_refresh_attempt < self._max_refresh_attempts):
219
220 _LOGGER.info(
221 'Refreshing credentials due to a %s response. Attempt %s/%s.',
222 response.status, _credential_refresh_attempt + 1,
223 self._max_refresh_attempts)
224
225 self.credentials.refresh(self._request)
226
227 # Recurse. Pass in the original headers, not our modified set.
228 return self.urlopen(
229 method, url, body=body, headers=headers,
230 _credential_refresh_attempt=_credential_refresh_attempt + 1,
231 **kwargs)
232
233 return response
234
235 # Proxy methods for compliance with the urllib3.PoolManager interface
236
237 def __enter__(self):
238 """Proxy to ``self.http``."""
239 return self.http.__enter__()
240
241 def __exit__(self, exc_type, exc_val, exc_tb):
242 """Proxy to ``self.http``."""
243 return self.http.__exit__(exc_type, exc_val, exc_tb)
244
245 @property
246 def headers(self):
247 """Proxy to ``self.http``."""
248 return self.http.headers
249
250 @headers.setter
251 def headers(self, value):
252 """Proxy to ``self.http``."""
253 self.http.headers = value
OLDNEW
« no previous file with comments | « client/third_party/google/auth/transport/requests.py ('k') | client/third_party/google/oauth2/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698