File size: 4,637 Bytes
2446f5f 500ef17 2446f5f 56d0fcf 6b64125 56d0fcf e50ca24 56d0fcf 2446f5f 1c864be 500ef17 e50ca24 6b64125 2446f5f 1c864be e50ca24 2446f5f 326f1b4 500ef17 2446f5f 500ef17 2446f5f e50ca24 6b64125 e50ca24 6b64125 2446f5f e50ca24 6b64125 e50ca24 2446f5f 1c864be 500ef17 1c864be e50ca24 500ef17 e50ca24 500ef17 56d0fcf 500ef17 56d0fcf 500ef17 e50ca24 500ef17 56d0fcf 2446f5f 56d0fcf |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
import httpx
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import StreamingResponse
import json
import random
import logging
import ipaddress
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
app = FastAPI()
# List of API URLs to be randomized
API_URLS = [
"https://api.deepinfra.com/v1/openai/chat/completions",
"https://stage.api.deepinfra.com/v1/openai/chat/completions",
]
# A pool of User-Agents (you can expand this list)
USER_AGENTS = [
# Chrome (Windows)
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
# Firefox (Windows)
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0",
# Safari (macOS)
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15",
# Edge (Windows)
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0",
# Chrome (Android)
"Mozilla/5.0 (Linux; Android 14; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Mobile Safari/537.36",
# Safari (iOS)
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
]
def generate_random_ip() -> str:
"""Generate a random IPv4 address, avoiding reserved ranges."""
while True:
ip = ipaddress.IPv4Address(random.getrandbits(32))
if not (ip.is_private or ip.is_multicast or ip.is_reserved or ip.is_loopback):
return str(ip)
@app.post("/v1/openai/chat/completions")
async def proxy_deepinfra(request: Request):
"""
Proxies chat completion requests to the DeepInfra API.
Randomizes API URLs, spoofed random IP, fake headers, and User-Agent rotation.
"""
try:
body = await request.json()
except json.JSONDecodeError:
raise HTTPException(status_code=400, detail="Invalid JSON in request body")
# Random spoofed IP + random User-Agent
random_ip = generate_random_ip()
user_agent = random.choice(USER_AGENTS)
headers = {
# Browser/device headers
"User-Agent": user_agent,
"accept": "text/event-stream",
"sec-ch-ua": '"Chromium";v="140", "Not=A?Brand";v="24", "Google Chrome";v="140"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"Referer": "https://deepinfra.com/",
"Origin": "https://deepinfra.com",
# Spoofed IP headers
"X-Forwarded-For": random_ip,
"X-Real-IP": random_ip,
"Forwarded": f"for={random_ip};proto=https",
# Extra fake headers
"DNT": "1",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Accept-Language": "en-US,en;q=0.9,fr;q=0.8,de;q=0.7",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
# Deepinfra-specific
"X-Deepinfra-Source": request.headers.get("X-Deepinfra-Source", "web-embed"),
"Content-Type": "application/json",
}
shuffled_urls = random.sample(API_URLS, len(API_URLS))
async def stream_generator():
last_error = None
for url in shuffled_urls:
logging.info(
f"Attempting to connect to: {url} with spoofed IP {random_ip} and UA {user_agent}"
)
try:
async with httpx.AsyncClient() as client:
async with client.stream(
"POST", url, headers=headers, json=body, timeout=None
) as response:
response.raise_for_status()
logging.info(f"Successfully connected. Streaming from: {url}")
async for chunk in response.aiter_bytes():
yield chunk
return
except (httpx.RequestError, httpx.HTTPStatusError) as e:
last_error = e
logging.warning(
f"Failed to connect to {url}: {e}. Trying next URL."
)
continue
if last_error:
logging.error(f"All API endpoints failed. Last error: {last_error}")
return StreamingResponse(stream_generator(), media_type="text-event-stream")
|