feat(http): add proxy support in HTTP client configuration

This commit is contained in:
ZhymabekRoman 2024-11-10 18:25:54 +05:00
parent e6684c71c0
commit ced3b1ea19
4 changed files with 66 additions and 5 deletions

View file

@ -5,7 +5,7 @@
groups = ["default", "dev"]
strategy = ["inherit_metadata"]
lock_version = "4.5.0"
content_hash = "sha256:f33cda53180165f833ddded2b624db8f9a24af2e825c9e137db33c5813de495d"
content_hash = "sha256:0a0ad998a9bb20803cebe4b225c0ba40df6c4fd880cda5bfad973483a0d9ef35"
[[metadata.targets]]
requires_python = "==3.12.*"
@ -183,6 +183,22 @@ files = [
{file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"},
]
[[package]]
name = "httpx"
version = "0.27.2"
extras = ["socks"]
requires_python = ">=3.8"
summary = "The next generation HTTP client."
groups = ["default"]
dependencies = [
"httpx==0.27.2",
"socksio==1.*",
]
files = [
{file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"},
{file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"},
]
[[package]]
name = "identify"
version = "2.6.1"
@ -643,6 +659,17 @@ files = [
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
]
[[package]]
name = "socksio"
version = "1.0.0"
requires_python = ">=3.6"
summary = "Sans-I/O implementation of SOCKS4, SOCKS4A, and SOCKS5."
groups = ["default"]
files = [
{file = "socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3"},
{file = "socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac"},
]
[[package]]
name = "time-machine"
version = "2.16.0"

View file

@ -11,6 +11,7 @@ dependencies = [
"orjson>=3.10.11",
"pendulum>=3.0.0",
"ujson>=5.10.0",
"httpx[socks]>=0.27.2",
]
requires-python = "==3.12.*"
readme = "README.md"

View file

@ -1,6 +1,6 @@
import warnings
from dataclasses import dataclass
from typing import Any, Dict, Optional
from typing import Any, Dict, Literal, Optional
from httpx import (
AsyncClient,
@ -12,10 +12,33 @@ from httpx import (
)
@dataclass
class RequestProxyConfig:
type: Literal["http", "https", "socks5"]
host: str
port: int
username: Optional[str] = None
password: Optional[str] = None
@property
def url(self) -> str:
type = self.type.replace(
"https", "http"
) # See: https://www.python-httpx.org/advanced/proxies/
proxy_url = f"{type}://"
if self.username and self.password:
proxy_url += f"{self.username}:{self.password}@"
proxy_url += f"{self.host}:{self.port}"
return proxy_url
@dataclass
class RequestConfig:
timeout: int = 6
retries: int = 3
proxy: Optional[RequestProxyConfig] = None
# backoff_factor: float = 0.1 # not possible. Default value: 0.5. https://github.com/encode/httpx/discussions/1895
@ -30,13 +53,20 @@ class Request:
stacklevel=2,
)
@property
def proxy_url(self) -> Optional[str]:
return self.config.proxy.url if self.config.proxy else None
@property
def _transport(self) -> HTTPTransport:
return HTTPTransport(retries=self.config.retries)
@property
def _client(self) -> Client:
return Client(transport=self._transport)
return Client(
transport=self._transport,
proxies=self.proxy_url,
)
@property
def _async_transport(self) -> AsyncHTTPTransport:
@ -44,7 +74,10 @@ class Request:
@property
def _async_client(self) -> AsyncClient:
return AsyncClient(transport=self._async_transport)
return AsyncClient(
transport=self._async_transport,
proxies=self.proxy_url,
)
@property
def _timeout_client(self) -> Timeout:
@ -67,7 +100,7 @@ class Request:
def __del__(self):
self._client.close()
# asyncio.run(self._async_client.aclose()) # TODO: doesnt works
# asyncio.run(self._async_client.aclose()) # TODO: doesn't work
def _check_context_manager(self):
if not self._in_context_manager: