OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # coding: utf-8 | 2 # coding: utf-8 |
3 # | 3 # |
4 # Copyright 2007 Google Inc. | 4 # Copyright 2007 Google Inc. |
5 # | 5 # |
6 # Licensed under the Apache License, Version 2.0 (the "License"); | 6 # Licensed under the Apache License, Version 2.0 (the "License"); |
7 # you may not use this file except in compliance with the License. | 7 # you may not use this file except in compliance with the License. |
8 # You may obtain a copy of the License at | 8 # You may obtain a copy of the License at |
9 # | 9 # |
10 # http://www.apache.org/licenses/LICENSE-2.0 | 10 # http://www.apache.org/licenses/LICENSE-2.0 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 # reason is a property on python 2.7 but a member variable on <=2.6. | 191 # reason is a property on python 2.7 but a member variable on <=2.6. |
192 # self.args is modified so it cannot be used as-is so save the value in | 192 # self.args is modified so it cannot be used as-is so save the value in |
193 # self._reason. | 193 # self._reason. |
194 return self._reason | 194 return self._reason |
195 | 195 |
196 | 196 |
197 class AbstractRpcServer(object): | 197 class AbstractRpcServer(object): |
198 """Provides a common interface for a simple RPC server.""" | 198 """Provides a common interface for a simple RPC server.""" |
199 | 199 |
200 def __init__(self, host, auth_function, host_override=None, | 200 def __init__(self, host, auth_function, host_override=None, |
201 extra_headers=None, save_cookies=False, | 201 request_path_prefix=None, extra_headers=None, |
202 account_type=AUTH_ACCOUNT_TYPE): | 202 save_cookies=False, account_type=AUTH_ACCOUNT_TYPE): |
203 """Creates a new AbstractRpcServer. | 203 """Creates a new AbstractRpcServer. |
204 | 204 |
205 Args: | 205 Args: |
206 host: The host to send requests to. | 206 host: The host to send requests to. |
207 auth_function: A function that takes no arguments and returns an | 207 auth_function: A function that takes no arguments and returns an |
208 (email, password) tuple when called. Will be called if authentication | 208 (email, password) tuple when called. Will be called if authentication |
209 is required. | 209 is required. |
210 host_override: The host header to send to the server (defaults to host). | 210 host_override: The host header to send to the server (defaults to host). |
| 211 request_path_prefix: A string to prefix all URL paths with (e.g. 'bots/'). |
211 extra_headers: A dict of extra headers to append to every request. | 212 extra_headers: A dict of extra headers to append to every request. |
212 save_cookies: If True, save the authentication cookies to local disk. | 213 save_cookies: If True, save the authentication cookies to local disk. |
213 If False, use an in-memory cookiejar instead. Subclasses must | 214 If False, use an in-memory cookiejar instead. Subclasses must |
214 implement this functionality. Defaults to False. | 215 implement this functionality. Defaults to False. |
215 account_type: Account type used for authentication. Defaults to | 216 account_type: Account type used for authentication. Defaults to |
216 AUTH_ACCOUNT_TYPE. | 217 AUTH_ACCOUNT_TYPE. |
217 """ | 218 """ |
218 self.host = host | 219 self.host = host |
219 if (not self.host.startswith("http://") and | 220 if (not self.host.startswith("http://") and |
220 not self.host.startswith("https://")): | 221 not self.host.startswith("https://")): |
221 self.host = "http://" + self.host | 222 self.host = "http://" + self.host |
222 self.host_override = host_override | 223 self.host_override = host_override |
| 224 self.request_path_prefix = request_path_prefix or '' |
223 self.auth_function = auth_function | 225 self.auth_function = auth_function |
224 self.authenticated = False | 226 self.authenticated = False |
225 self.extra_headers = extra_headers or {} | 227 self.extra_headers = extra_headers or {} |
226 self.save_cookies = save_cookies | 228 self.save_cookies = save_cookies |
227 self.account_type = account_type | 229 self.account_type = account_type |
228 self.opener = self._GetOpener() | 230 self.opener = self._GetOpener() |
229 if self.host_override: | 231 if self.host_override: |
230 LOGGER.info("Server: %s; Host: %s", self.host, self.host_override) | 232 LOGGER.info("Server: %s; Host: %s", self.host, self.host_override) |
231 else: | 233 else: |
232 LOGGER.info("Server: %s", self.host) | 234 LOGGER.info("Server: %s", self.host) |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 self._Authenticate(force_refresh=False) | 427 self._Authenticate(force_refresh=False) |
426 | 428 |
427 old_timeout = socket.getdefaulttimeout() | 429 old_timeout = socket.getdefaulttimeout() |
428 socket.setdefaulttimeout(timeout) | 430 socket.setdefaulttimeout(timeout) |
429 auth_attempted = False | 431 auth_attempted = False |
430 try: | 432 try: |
431 tries = 0 | 433 tries = 0 |
432 while True: | 434 while True: |
433 tries += 1 | 435 tries += 1 |
434 args = dict(kwargs) | 436 args = dict(kwargs) |
435 url = "%s%s" % (self.host, request_path) | 437 url = "%s%s%s" % (self.host, self.request_path_prefix, request_path) |
436 if args: | 438 if args: |
437 url += "?" + urllib.urlencode(args) | 439 url += "?" + urllib.urlencode(args) |
438 req = self._CreateRequest(url=url, data=payload) | 440 req = self._CreateRequest(url=url, data=payload) |
439 req.add_header("Content-Type", content_type) | 441 req.add_header("Content-Type", content_type) |
440 if extra_headers: | 442 if extra_headers: |
441 for header, value in extra_headers.items(): | 443 for header, value in extra_headers.items(): |
442 req.add_header(header, value) | 444 req.add_header(header, value) |
443 try: | 445 try: |
444 f = self.opener.open(req, timeout=70) | 446 f = self.opener.open(req, timeout=70) |
445 response = f.read() | 447 response = f.read() |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 account_type=AUTH_ACCOUNT_TYPE) | 763 account_type=AUTH_ACCOUNT_TYPE) |
762 # Don't try to talk to ClientLogin. | 764 # Don't try to talk to ClientLogin. |
763 server.authenticated = True | 765 server.authenticated = True |
764 return server | 766 return server |
765 | 767 |
766 if auth_config.use_oauth2: | 768 if auth_config.use_oauth2: |
767 auth_func = auth.get_authenticator_for_host(server, auth_config) | 769 auth_func = auth.get_authenticator_for_host(server, auth_config) |
768 else: | 770 else: |
769 auth_func = KeyringCreds(server, host, email).GetUserCredentials | 771 auth_func = KeyringCreds(server, host, email).GetUserCredentials |
770 | 772 |
| 773 # HACK(crbug.com/476690): Internal Rietveld is configured to require cookie |
| 774 # auth for all paths except /bots/* (requests to /bots/* are authenticated |
| 775 # with OAuth). /bots/* paths expose exact same API as /* (at least enough of |
| 776 # it for depot_tools to work). So when using OAuth with internal Rietveld, |
| 777 # silently prefix all requests with '/bots'. |
| 778 request_path_prefix = '' |
| 779 if auth_config.use_oauth2: |
| 780 if not host.startswith(('http://', 'https://')): |
| 781 host = 'https://' + host |
| 782 parsed = urlparse.urlparse(host) |
| 783 if parsed.netloc.endswith('.googleplex.com'): |
| 784 request_path_prefix = '/bots' |
| 785 |
771 return HttpRpcServer( | 786 return HttpRpcServer( |
772 server, | 787 server, |
773 auth_func, | 788 auth_func, |
| 789 request_path_prefix=request_path_prefix, |
774 save_cookies=auth_config.save_cookies, | 790 save_cookies=auth_config.save_cookies, |
775 account_type=AUTH_ACCOUNT_TYPE) | 791 account_type=AUTH_ACCOUNT_TYPE) |
776 | 792 |
777 | 793 |
778 def EncodeMultipartFormData(fields, files): | 794 def EncodeMultipartFormData(fields, files): |
779 """Encode form fields for multipart/form-data. | 795 """Encode form fields for multipart/form-data. |
780 | 796 |
781 Args: | 797 Args: |
782 fields: A sequence of (name, value) elements for regular form fields. | 798 fields: A sequence of (name, value) elements for regular form fields. |
783 files: A sequence of (name, filename, value) elements for data to be | 799 files: A sequence of (name, filename, value) elements for data to be |
(...skipping 1743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2527 print | 2543 print |
2528 StatusUpdate("Interrupted.") | 2544 StatusUpdate("Interrupted.") |
2529 sys.exit(1) | 2545 sys.exit(1) |
2530 except auth.AuthenticationError as e: | 2546 except auth.AuthenticationError as e: |
2531 print >> sys.stderr, e | 2547 print >> sys.stderr, e |
2532 sys.exit(1) | 2548 sys.exit(1) |
2533 | 2549 |
2534 | 2550 |
2535 if __name__ == "__main__": | 2551 if __name__ == "__main__": |
2536 main() | 2552 main() |
OLD | NEW |