diff --git a/lighter/configuration.py b/lighter/configuration.py index ff0507e..6720c47 100644 --- a/lighter/configuration.py +++ b/lighter/configuration.py @@ -190,6 +190,10 @@ def __init__(self, host=None, self.proxy: Optional[str] = None """Proxy URL """ + self.proxy_list: Optional[list[str]] = None + """List of proxy URLs for rotation. When set, requests will round-robin + through these proxies. Takes precedence over self.proxy. + """ self.proxy_headers = None """Proxy headers """ diff --git a/lighter/rest.py b/lighter/rest.py index e996812..9d5b687 100644 --- a/lighter/rest.py +++ b/lighter/rest.py @@ -14,6 +14,8 @@ import io import json +import logging +import random import re import ssl from typing import Optional, Union @@ -23,6 +25,9 @@ from lighter.exceptions import ApiException, ApiValueError +logger = logging.getLogger(__name__) +PROXY_USAGE_PROBABILITY = 0.5 + RESTResponseType = aiohttp.ClientResponse ALLOW_RETRY_METHODS = frozenset({'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PUT', 'TRACE'}) @@ -74,6 +79,8 @@ def __init__(self, configuration) -> None: ) self.proxy = configuration.proxy + self.proxy_list = configuration.proxy_list + self._proxy_index = 0 self.proxy_headers = configuration.proxy_headers # https pool manager @@ -156,7 +163,13 @@ async def request( "headers": headers } - if self.proxy: + # Proxy rotation with probability control + if self.proxy_list and random.random() < PROXY_USAGE_PROBABILITY: + proxy = self.proxy_list[self._proxy_index % len(self.proxy_list)] + self._proxy_index += 1 + args["proxy"] = proxy + logger.info(f"Lighter request via proxy: {proxy}") + elif self.proxy: args["proxy"] = self.proxy if self.proxy_headers: args["proxy_headers"] = self.proxy_headers