From bb3b594039bec468f046c31bad9b3b43fdfebcf1 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 9 Dec 2025 15:35:49 +0000 Subject: [PATCH] Initial commit from GitAgent --- firebase_admin/_http_client.py | 50 +++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/firebase_admin/_http_client.py b/firebase_admin/_http_client.py index 6d258229..fab0404a 100644 --- a/firebase_admin/_http_client.py +++ b/firebase_admin/_http_client.py @@ -19,6 +19,8 @@ from __future__ import annotations import logging +import time +import asyncio from typing import Any, Dict, Generator, Optional, Tuple, Union import httpx import requests.adapters @@ -46,7 +48,6 @@ DEFAULT_HTTPX_RETRY_CONFIG = HttpxRetry( max_retries=4, status_forcelist=[500, 503], backoff_factor=0.5) - DEFAULT_TIMEOUT_SECONDS = 120 METRICS_HEADERS = { @@ -132,9 +133,26 @@ class call this method to send HTTP requests out. Refer to if 'timeout' not in kwargs: kwargs['timeout'] = self.timeout kwargs.setdefault('headers', {}).update(METRICS_HEADERS) - resp = self._session.request(method, self.base_url + url, **kwargs) - resp.raise_for_status() - return resp + + retries = 0 + max_retries = 4 + backoff_factor = 0.5 + + while retries <= max_retries: + try: + resp = self._session.request(method, self.base_url + url, **kwargs) + resp.raise_for_status() + return resp + except requests.exceptions.HTTPError as http_err: + if resp.status_code in [400, 401, 403]: + retries += 1 + if retries > max_retries: + raise + retry_after = int(resp.headers.get('Retry-After', 0)) + sleep_time = backoff_factor * (2 ** (retries - 1)) + retry_after + time.sleep(sleep_time) + else: + raise def headers(self, method, url, **kwargs): resp = self.request(method, url, **kwargs) @@ -329,8 +347,26 @@ class call this method to send HTTP requests out. Refer to """ if 'timeout' not in kwargs: kwargs['timeout'] = self.timeout - resp = await self._async_client.request(method, self.base_url + url, **kwargs) - return resp.raise_for_status() + + retries = 0 + max_retries = 4 + backoff_factor = 0.5 + + while retries <= max_retries: + try: + resp = await self._async_client.request(method, self.base_url + url, **kwargs) + resp.raise_for_status() + return resp + except httpx.HTTPStatusError as http_err: + if resp.status_code in [400, 401, 403]: + retries += 1 + if retries > max_retries: + raise + retry_after = int(resp.headers.get('Retry-After', 0)) + sleep_time = backoff_factor * (2 ** (retries - 1)) + retry_after + await asyncio.sleep(sleep_time) + else: + raise async def headers(self, method: str, url: str, **kwargs: Any) -> httpx.Headers: resp = await self.request(method, url, **kwargs) @@ -354,4 +390,4 @@ def parse_body(self, resp: httpx.Response) -> Any: return resp.json() async def aclose(self) -> None: - await self._async_client.aclose() + await self._async_client.aclose() \ No newline at end of file