p04.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. """
  2. FastAPI HTTP 代理服务
  3. 代理 HTTP://192.168.0.42:8005/mcp 接口
  4. """
  5. import httpx
  6. from fastapi import FastAPI, Request, Response
  7. from fastapi.responses import StreamingResponse
  8. import json
  9. app = FastAPI(
  10. title="HTTP Proxy Service",
  11. description="代理 MCP 接口到 192.168.0.42:8005",
  12. version="1.0.0"
  13. )
  14. # 目标服务地址
  15. TARGET_BASE_URL = "http://192.168.0.42:8005"
  16. def get_forwarded_headers(request: Request) -> dict:
  17. """获取需要转发的 headers"""
  18. headers = {}
  19. # 转发所有 headers,跳过一些不需要的
  20. skip_headers = {"host", "content-length", "transfer-encoding"}
  21. for key, value in request.headers.items():
  22. if key.lower() not in skip_headers:
  23. headers[key] = value
  24. return headers
  25. async def proxy_request(path: str, request: Request):
  26. """代理请求到目标服务"""
  27. url = f"{TARGET_BASE_URL}{path}"
  28. method = request.method
  29. headers = get_forwarded_headers(request)
  30. # 获取请求体
  31. body = await request.body()
  32. async with httpx.AsyncClient(timeout=60.0) as client:
  33. try:
  34. # 发送请求
  35. response = await client.request(
  36. method=method,
  37. url=url,
  38. headers=headers,
  39. content=body if body else None,
  40. params=request.query_params
  41. )
  42. # 构建响应头
  43. response_headers = {}
  44. for key, value in response.headers.items():
  45. if key.lower() not in {"content-length", "transfer-encoding", "connection"}:
  46. response_headers[key] = value
  47. # 返回响应
  48. return Response(
  49. content=response.content,
  50. status_code=response.status_code,
  51. headers=response_headers
  52. )
  53. except httpx.TimeoutException:
  54. return Response(
  55. content=json.dumps({"error": "请求超时"}).encode("utf-8"),
  56. status_code=504,
  57. media_type="application/json"
  58. )
  59. except httpx.ConnectError:
  60. return Response(
  61. content=json.dumps({"error": "无法连接到目标服务"}).encode("utf-8"),
  62. status_code=503,
  63. media_type="application/json"
  64. )
  65. except Exception as e:
  66. return Response(
  67. content=json.dumps({"error": f"代理请求失败: {str(e)}"}).encode("utf-8"),
  68. status_code=500,
  69. media_type="application/json"
  70. )
  71. @app.api_route("/mcp/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"])
  72. async def proxy_mcp(path: str, request: Request):
  73. """代理 /mcp 路径下的所有请求"""
  74. target_path = f"/mcp/{path}"
  75. return await proxy_request(target_path, request)
  76. @app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"])
  77. async def proxy_all(path: str, request: Request):
  78. """代理所有其他路径的请求"""
  79. return await proxy_request(f"/{path}", request)
  80. if __name__ == "__main__":
  81. import uvicorn
  82. uvicorn.run("p04:app", host="0.0.0.0", port=8000, reload=True)