nikeshn commited on
Commit
04fb378
·
verified ·
1 Parent(s): 712f62b

Upload http_client.py

Browse files
Files changed (1) hide show
  1. src/services/http_client.py +39 -0
src/services/http_client.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Shared outbound HTTP client factory.
2
+
3
+ Hugging Face Spaces resolve some hosts to IPv6 addresses they cannot actually
4
+ route, which surfaces as httpx.ConnectTimeout('') with no message - the socket
5
+ never opens. Binding the local address to 0.0.0.0 forces IPv4 and avoids the
6
+ dead AAAA path. Transport-level retries cover transient DNS/SYN loss.
7
+
8
+ Use make_client() for every outbound call to infrastructure we control
9
+ (the Cloudflare Worker). Third-party APIs that already work are unaffected.
10
+ """
11
+ import logging
12
+ from typing import Optional
13
+
14
+ import httpx
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ # Set to None to let the OS choose (dual-stack); "0.0.0.0" forces IPv4.
19
+ FORCE_IPV4_LOCAL_ADDRESS: Optional[str] = "0.0.0.0"
20
+
21
+
22
+ def make_transport(retries: int = 2) -> httpx.AsyncHTTPTransport:
23
+ try:
24
+ return httpx.AsyncHTTPTransport(
25
+ local_address=FORCE_IPV4_LOCAL_ADDRESS,
26
+ retries=retries,
27
+ )
28
+ except Exception as exc: # very old httpx without local_address
29
+ logger.warning(f"IPv4-forcing transport unavailable ({exc}); using default")
30
+ return httpx.AsyncHTTPTransport(retries=retries)
31
+
32
+
33
+ def make_client(timeout: float = 8.0, retries: int = 2) -> httpx.AsyncClient:
34
+ """AsyncClient pinned to IPv4 with transport retries."""
35
+ return httpx.AsyncClient(
36
+ timeout=timeout,
37
+ transport=make_transport(retries=retries),
38
+ follow_redirects=True,
39
+ )