2222from __future__ import unicode_literals
2323
2424import http .client
25- from typing import Dict
25+ from typing import Optional , Dict
2626from typing import Union
2727import warnings
2828
@@ -476,22 +476,37 @@ def from_http_status(status_code, message, **kwargs):
476476 return error
477477
478478
479- def from_http_response (response ):
480- """Create a :class:`GoogleAPICallError` from a :class:`requests.Response`.
479+ def _format_rest_error_message (error , method , url ):
480+ method = method .upper () if method else None
481+ message = "{method} {url}: {error}" .format (
482+ method = method ,
483+ url = url ,
484+ error = error ,
485+ )
486+ return message
487+
488+
489+ # NOTE: We're moving away from `from_http_status` because it expects an aiohttp response compared
490+ # to `format_http_response_error` which expects a more abstract response from google.auth and is
491+ # compatible with both sync and async response types.
492+ # TODO(https://github.com/googleapis/python-api-core/issues/691): Add type hint for response.
493+ def format_http_response_error (
494+ response , method : str , url : str , payload : Optional [Dict ] = None
495+ ):
496+ """Create a :class:`GoogleAPICallError` from a google auth rest response.
481497
482498 Args:
483- response (requests.Response): The HTTP response.
499+ response Union[google.auth.transport.Response, google.auth.aio.transport.Response]: The HTTP response.
500+ method Optional(str): The HTTP request method.
501+ url Optional(str): The HTTP request url.
502+ payload Optional(dict): The HTTP response payload. If not passed in, it is read from response for a response type of google.auth.transport.Response.
484503
485504 Returns:
486505 GoogleAPICallError: An instance of the appropriate subclass of
487506 :class:`GoogleAPICallError`, with the message and errors populated
488507 from the response.
489508 """
490- try :
491- payload = response .json ()
492- except ValueError :
493- payload = {"error" : {"message" : response .text or "unknown error" }}
494-
509+ payload = {} if not payload else payload
495510 error_message = payload .get ("error" , {}).get ("message" , "unknown error" )
496511 errors = payload .get ("error" , {}).get ("errors" , ())
497512 # In JSON, details are already formatted in developer-friendly way.
@@ -504,12 +519,7 @@ def from_http_response(response):
504519 )
505520 )
506521 error_info = error_info [0 ] if error_info else None
507-
508- message = "{method} {url}: {error}" .format (
509- method = response .request .method ,
510- url = response .request .url ,
511- error = error_message ,
512- )
522+ message = _format_rest_error_message (error_message , method , url )
513523
514524 exception = from_http_status (
515525 response .status_code ,
@@ -522,6 +532,26 @@ def from_http_response(response):
522532 return exception
523533
524534
535+ def from_http_response (response ):
536+ """Create a :class:`GoogleAPICallError` from a :class:`requests.Response`.
537+
538+ Args:
539+ response (requests.Response): The HTTP response.
540+
541+ Returns:
542+ GoogleAPICallError: An instance of the appropriate subclass of
543+ :class:`GoogleAPICallError`, with the message and errors populated
544+ from the response.
545+ """
546+ try :
547+ payload = response .json ()
548+ except ValueError :
549+ payload = {"error" : {"message" : response .text or "unknown error" }}
550+ return format_http_response_error (
551+ response , response .request .method , response .request .url , payload
552+ )
553+
554+
525555def exception_class_for_grpc_status (status_code ):
526556 """Return the exception class for a specific :class:`grpc.StatusCode`.
527557
0 commit comments