File size: 3,376 Bytes
2ee3bb2 2280bd6 cb2432b b1049e3 2ee3bb2 3b27764 2ee3bb2 cb2432b 2ee3bb2 cb2432b 2ee3bb2 cb2432b 2ee3bb2 cb2432b 3b27764 2ee3bb2 | 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 | from fastapi import FastAPI, Request, Response
from fastapi.responses import StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
import httpx
import asyncio
from typing import Optional
app = FastAPI()
# 添加 CORS 支持
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 目标网站
TARGET_URL = "http://beibeioo.top"
# 创建一个全局的 httpx 客户端
async def get_http_client():
return httpx.AsyncClient(
timeout=30.0, # 30秒超时
follow_redirects=True,
http2=True
)
@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "PATCH"])
async def proxy(path: str, request: Request):
try:
# 构建目标URL
url = f"{TARGET_URL}/{path}"
# 获取并处理请求头
headers = dict(request.headers)
# 删除可能导致问题的头部
headers.pop('host', None)
headers.pop('connection', None)
headers.pop('content-length', None)
headers.pop('transfer-encoding', None)
# 如果有 referer,修改它
if 'referer' in headers:
headers['referer'] = headers['referer'].replace(str(request.base_url), TARGET_URL)
# 获取查询参数
params = dict(request.query_params)
# 获取请求体
body = await request.body()
async with await get_http_client() as client:
response = await client.request(
method=request.method,
url=url,
params=params,
headers=headers,
content=body if body else None,
)
# 处理响应头
response_headers = dict(response.headers)
# 删除可能导致问题的响应头
response_headers.pop('transfer-encoding', None)
response_headers.pop('content-encoding', None)
# 修改所有涉及原始域名的响应头
for key, value in response_headers.items():
if isinstance(value, str) and TARGET_URL in value:
response_headers[key] = value.replace(TARGET_URL, str(request.base_url).rstrip('/'))
# 返回响应
return StreamingResponse(
response.iter_bytes(),
status_code=response.status_code,
headers=response_headers,
media_type=response.headers.get('content-type')
)
except httpx.TimeoutException:
return Response(
content="请求超时",
status_code=504,
media_type="text/plain"
)
except httpx.RequestError:
return Response(
content="无法连接到目标服务器",
status_code=502,
media_type="text/plain"
)
except Exception as e:
return Response(
content=f"服务器错误: {str(e)}",
status_code=500,
media_type="text/plain"
)
@app.get("/healthcheck")
async def healthcheck():
"""健康检查端点"""
return {"status": "healthy"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860) |