1# Copyright 2024 Google LLC 
    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 - Asynchronous HTTP client library support. 
    16 
    17:mod:`google.auth.aio` is designed to work with various asynchronous client libraries such 
    18as aiohttp. In order to work across these libraries with different 
    19interfaces some abstraction is needed. 
    20 
    21This module provides two interfaces that are implemented by transport adapters 
    22to support HTTP libraries. :class:`Request` defines the interface expected by 
    23:mod:`google.auth` to make asynchronous requests. :class:`Response` defines the interface 
    24for the return value of :class:`Request`. 
    25""" 
    26 
    27import abc 
    28from typing import AsyncGenerator, Mapping, Optional 
    29 
    30import google.auth.transport 
    31 
    32 
    33_DEFAULT_TIMEOUT_SECONDS = 180 
    34 
    35DEFAULT_RETRYABLE_STATUS_CODES = google.auth.transport.DEFAULT_RETRYABLE_STATUS_CODES 
    36"""Sequence[int]:  HTTP status codes indicating a request can be retried. 
    37""" 
    38 
    39 
    40DEFAULT_MAX_RETRY_ATTEMPTS = 3 
    41"""int: How many times to retry a request.""" 
    42 
    43 
    44class Response(metaclass=abc.ABCMeta): 
    45    """Asynchronous HTTP Response Interface.""" 
    46 
    47    @property 
    48    @abc.abstractmethod 
    49    def status_code(self) -> int: 
    50        """ 
    51        The HTTP response status code. 
    52 
    53        Returns: 
    54            int: The HTTP response status code. 
    55 
    56        """ 
    57        raise NotImplementedError("status_code must be implemented.") 
    58 
    59    @property 
    60    @abc.abstractmethod 
    61    def headers(self) -> Mapping[str, str]: 
    62        """The HTTP response headers. 
    63 
    64        Returns: 
    65            Mapping[str, str]: The HTTP response headers. 
    66        """ 
    67        raise NotImplementedError("headers must be implemented.") 
    68 
    69    @abc.abstractmethod 
    70    async def content(self, chunk_size: int) -> AsyncGenerator[bytes, None]: 
    71        """The raw response content. 
    72 
    73        Args: 
    74            chunk_size (int): The size of each chunk. 
    75 
    76        Yields: 
    77            AsyncGenerator[bytes, None]: An asynchronous generator yielding 
    78            response chunks as bytes. 
    79        """ 
    80        raise NotImplementedError("content must be implemented.") 
    81 
    82    @abc.abstractmethod 
    83    async def read(self) -> bytes: 
    84        """Read the entire response content as bytes. 
    85 
    86        Returns: 
    87            bytes: The entire response content. 
    88        """ 
    89        raise NotImplementedError("read must be implemented.") 
    90 
    91    @abc.abstractmethod 
    92    async def close(self): 
    93        """Close the response after it is fully consumed to resource.""" 
    94        raise NotImplementedError("close must be implemented.") 
    95 
    96 
    97class Request(metaclass=abc.ABCMeta): 
    98    """Interface for a callable that makes HTTP requests. 
    99 
    100    Specific transport implementations should provide an implementation of 
    101    this that adapts their specific request / response API. 
    102 
    103    .. automethod:: __call__ 
    104    """ 
    105 
    106    @abc.abstractmethod 
    107    async def __call__( 
    108        self, 
    109        url: str, 
    110        method: str, 
    111        body: Optional[bytes], 
    112        headers: Optional[Mapping[str, str]], 
    113        timeout: float, 
    114        **kwargs 
    115    ) -> Response: 
    116        """Make an HTTP request. 
    117 
    118        Args: 
    119            url (str): The URI to be requested. 
    120            method (str): The HTTP method to use for the request. Defaults 
    121                to 'GET'. 
    122            body (Optional[bytes]): The payload / body in HTTP request. 
    123            headers (Mapping[str, str]): Request headers. 
    124            timeout (float): The number of seconds to wait for a 
    125                response from the server. If not specified or if None, the 
    126                transport-specific default timeout will be used. 
    127            kwargs: Additional arguments passed on to the transport's 
    128                request method. 
    129 
    130        Returns: 
    131            google.auth.aio.transport.Response: The HTTP response. 
    132 
    133        Raises: 
    134            google.auth.exceptions.TransportError: If any exception occurred. 
    135        """ 
    136        # pylint: disable=redundant-returns-doc, missing-raises-doc 
    137        # (pylint doesn't play well with abstract docstrings.) 
    138        raise NotImplementedError("__call__ must be implemented.") 
    139 
    140    async def close(self) -> None: 
    141        """ 
    142        Close the underlying session. 
    143        """ 
    144        raise NotImplementedError("close must be implemented.")