| 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 |