tg_proxy / app.py
#zhbanovva
Update app.py
1c4f166
Raw
History Blame Contribute Delete
5.59 kB
import httpx
import asyncio
from websockets import ClientConnection
from websockets.asyncio.client import connect
from fastapi import FastAPI, Request, Response, WebSocket
from fastapi.responses import JSONResponse
app = FastAPI(title="Telegram Proxy")
TELEGRAM_HOST = 'square-term-f712.valerazbanovqs.workers.dev'
async def autocancel(request, coroutine):
async def listen_for_disconnect():
while True:
message = await request.receive()
if message["type"] == "http.disconnect":
break
await asyncio.sleep(1)
return JSONResponse(
status_code=499,
content=dict(user_message="Запрос был отменен"),
)
async def process_request():
return await coroutine
process_request_task = asyncio.create_task(process_request())
tasks = [
process_request_task,
asyncio.create_task(listen_for_disconnect()),
]
tasks = [task for task in tasks if task is not None]
done, pending = await asyncio.wait(
tasks,
return_when=asyncio.FIRST_COMPLETED
)
for task in pending:
task.cancel()
for task in pending:
try:
await task
except asyncio.CancelledError:
...
except:
pass
return next(iter(done)).result()
def _prepare_headers(headers: dict):
if "authorization" in headers: del headers["authorization"]
headers["host"] = TELEGRAM_HOST
return headers
async def _proxy_request(request: Request) -> Response:
base_url = f'https://{TELEGRAM_HOST}/'
url = '/' + request.path_params['url']
headers = _prepare_headers(dict(request.headers))
query_params = dict(request.query_params)
content = await request.body()
async with httpx.AsyncClient(base_url=base_url, trust_env=False) as session:
response = await session.request(
method=request.method,
url=url,
headers=headers,
params=query_params,
content=content,
timeout=None,
)
return Response(
content=response.content,
status_code=response.status_code,
headers=dict(response.headers)
)
async def proxy_request(request):
return await autocancel(request, _proxy_request(request))
@app.get("/base/telegram_api/{url:path}", summary='Проксирует все методы get в телеграм апи')
async def get_base_service_path(
request: Request,
url: str,
):
return await proxy_request(request)
@app.post("/base/telegram_api/{url:path}", summary='Проксирует все методы post в телеграм апи')
async def post_base_service_path(
request: Request,
url: str,
):
return await proxy_request(request)
@app.put("/base/telegram_api/{url:path}", summary='Проксирует все методы put в телеграм апи')
async def put_base_service_path(
request: Request,
url: str,
):
return await proxy_request(request)
@app.delete("/base/telegram_api/{url:path}", summary='Проксирует все методы delete в телеграм апи')
async def delete_base_service_path(
request: Request,
url: str,
):
return await proxy_request(request)
@app.patch("/base/telegram_api/{url:path}", summary='Проксирует все методы patch в телеграм апи')
async def patch_base_service_path(
request: Request,
url: str,
):
return await proxy_request(request)
@app.options("/base/telegram_api/{url:path}", summary='Проксирует все методы options в телеграм апи')
async def options_base_service_path(
request: Request,
url: str,
):
return await proxy_request(request)
@app.head("/base/telegram_api/{url:path}", summary='Проксирует все методы head в телеграм апи')
async def head_base_service_path(
request: Request,
url: str,
):
return await proxy_request(request)
@app.websocket("/base/telegram_api/{url:path}")
async def proxy_websocket(websocket: WebSocket, url: str):
await websocket.accept()
target_url = f"wss://{TELEGRAM_IP}/{url}"
headers = _prepare_headers(dict(websocket.headers))
async def forward(source: ClientConnection, destination: ClientConnection):
async for message in source:
await destination.send(message)
try:
async with connect(target_url, additional_headers=headers, server_hostname=TELEGRAM_HOST) as target_ws:
await asyncio.gather(
forward(websocket, target_ws),
forward(target_ws, websocket)
)
finally:
await websocket.close()
@app.get("/test-connection-google")
async def test_connection_google():
try:
async with httpx.AsyncClient() as client:
resp = await client.get("https://google.com", timeout=5.0)
return {"status": "google_ok", "code": resp.status_code}
except Exception as e:
return {"status": "error", "message": str(e)}
@app.get("/test-connection-telegram")
async def test_connection_telegram():
try:
async with httpx.AsyncClient() as client:
resp = await client.get("https://api.telegram.org", timeout=5.0)
return {"status": "telegram_ok", "code": resp.status_code}
except Exception as e:
return {"status": "error", "message": str(e)}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=7860)