Skip to content

Commit 2033761

Browse files
committed
Add:py_proxy
1 parent d4afe73 commit 2033761

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

proxy.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
from fastapi import FastAPI, Request, HTTPException
2+
from fastapi.responses import StreamingResponse
3+
from fastapi.middleware.cors import CORSMiddleware
4+
import httpx
5+
6+
app = FastAPI()
7+
8+
# 设置跨域支持
9+
app.add_middleware(
10+
CORSMiddleware,
11+
allow_origins=["*"], # 允许所有域名访问,生产环境中可以指定具体域名
12+
allow_credentials=True,
13+
allow_methods=["*"], # 允许所有方法
14+
allow_headers=["*"], # 允许所有请求头
15+
)
16+
17+
18+
@app.api_route('/proxy/{full_url:path}', methods=['GET', 'POST', 'PUT', 'DELETE'])
19+
async def proxy(request: Request, full_url: str):
20+
target_url = full_url if full_url.startswith("http") else f"http://{full_url}"
21+
timeout = httpx.Timeout(60.0, read=120.0)
22+
23+
async with httpx.AsyncClient(timeout=timeout) as client:
24+
try:
25+
# 处理 GET 请求
26+
if request.method == "GET":
27+
response = await client.get(target_url, headers=request.headers, params=request.query_params,
28+
stream=True)
29+
30+
# 处理 POST 请求
31+
elif request.method == "POST":
32+
content_type = request.headers.get('content-type', '') # 默认空字符串
33+
34+
# 处理 JSON 数据
35+
if 'application/json' in content_type:
36+
json_data = await request.json()
37+
response = await client.post(target_url, json=json_data, headers=request.headers, stream=True)
38+
39+
# 处理 URL 编码的表单数据
40+
elif 'application/x-www-form-urlencoded' in content_type:
41+
form_data = dict(await request.form())
42+
response = await client.post(target_url, data=form_data, headers=request.headers, stream=True)
43+
44+
# 处理 multipart/form-data 表单数据
45+
elif 'multipart/form-data' in content_type:
46+
form = await request.form()
47+
files = {key: (form[key].filename, await form[key].read()) for key in form if
48+
isinstance(form[key], UploadFile)}
49+
fields = {key: form[key] for key in form if not isinstance(form[key], UploadFile)}
50+
response = await client.post(target_url, data=fields, files=files, headers=request.headers,
51+
stream=True)
52+
53+
# 如果没有指定 Content-Type,处理默认的 URL 编码表单数据
54+
elif content_type == '' or 'text/plain' in content_type:
55+
form_data = dict(await request.form())
56+
response = await client.post(target_url, data=form_data, headers=request.headers, stream=True)
57+
58+
else:
59+
raise HTTPException(status_code=400, detail="Unsupported Content-Type for POST request")
60+
61+
# 处理 PUT 请求
62+
elif request.method == "PUT":
63+
json_data = await request.json()
64+
response = await client.put(target_url, json=json_data, headers=request.headers, stream=True)
65+
66+
# 处理 DELETE 请求
67+
elif request.method == "DELETE":
68+
response = await client.delete(target_url, headers=request.headers, stream=True)
69+
70+
else:
71+
raise HTTPException(status_code=405, detail="Method not allowed")
72+
73+
except httpx.RequestError as e:
74+
raise HTTPException(status_code=500, detail=str(e))
75+
76+
return StreamingResponse(response.aiter_bytes(), status_code=response.status_code, headers=dict(response.headers))
77+
78+
79+
if __name__ == "__main__":
80+
import uvicorn
81+
82+
uvicorn.run(app, host="0.0.0.0", port=8000)

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fastapi
2+
httpx
3+
uvicorn

0 commit comments

Comments
 (0)