main.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. """
  2. 主应用入口
  3. """
  4. from fastapi import FastAPI, WebSocket
  5. from fastapi.middleware.cors import CORSMiddleware
  6. from config import settings, get_dashscope_domain
  7. from websocket_handler import WebSocketHandler
  8. app = FastAPI(title="Tolan Backend API")
  9. # 配置CORS
  10. app.add_middleware(
  11. CORSMiddleware,
  12. allow_origins=["*"], # 生产环境应该限制具体域名
  13. allow_credentials=True,
  14. allow_methods=["*"],
  15. allow_headers=["*"],
  16. )
  17. @app.get("/")
  18. async def root():
  19. """健康检查"""
  20. return {"status": "ok", "message": "Tolan Backend API"}
  21. @app.websocket("/ws")
  22. async def websocket_endpoint(websocket: WebSocket):
  23. """WebSocket端点"""
  24. handler = WebSocketHandler(websocket)
  25. await handler.handle_connection()
  26. if __name__ == "__main__":
  27. import uvicorn
  28. import os
  29. import socket
  30. from pathlib import Path
  31. # 🔥 DNS预解析(减少首次连接延迟)
  32. dashscope_domain = get_dashscope_domain()
  33. print(f"🔧 预解析DNS ({dashscope_domain})...")
  34. try:
  35. socket.getaddrinfo(dashscope_domain, 443)
  36. print("✅ DNS预解析完成\n")
  37. except Exception as e:
  38. print(f"⚠️ DNS预解析失败(不影响正常使用): {e}\n")
  39. # 打印启动配置
  40. print("="*50)
  41. print("Tolan 后端服务启动")
  42. print("="*50)
  43. print(f"主机: {settings.HOST}")
  44. print(f"端口: {settings.PORT}")
  45. # SSL证书路径配置
  46. # 优先使用环境变量配置的证书路径(生产环境)
  47. ssl_keyfile = settings.SSL_KEYFILE
  48. ssl_certfile = settings.SSL_CERTFILE
  49. # 如果环境变量未配置,使用本地开发证书
  50. if not ssl_keyfile or not ssl_certfile:
  51. ssl_dir = Path(__file__).parent.parent / "ssl"
  52. ssl_keyfile = str(ssl_dir / "key.pem")
  53. ssl_certfile = str(ssl_dir / "cert.pem")
  54. # 检查证书是否存在
  55. if ssl_keyfile and ssl_certfile:
  56. if not os.path.exists(ssl_keyfile) or not os.path.exists(ssl_certfile):
  57. print(f"⚠️ SSL证书不存在")
  58. print(f" 证书: {ssl_certfile}")
  59. print(f" 私钥: {ssl_keyfile}")
  60. print(" 将以HTTP模式启动")
  61. ssl_keyfile = None
  62. ssl_certfile = None
  63. else:
  64. print(f"✅ 使用SSL证书:")
  65. print(f" 证书: {ssl_certfile}")
  66. print(f" 私钥: {ssl_keyfile}")
  67. # 显示访问地址
  68. protocol = "https" if ssl_keyfile and ssl_certfile else "http"
  69. ws_protocol = "wss" if ssl_keyfile and ssl_certfile else "ws"
  70. print(f"\n访问地址:")
  71. print(f" HTTP: {protocol}://{settings.HOST}:{settings.PORT}")
  72. print(f" WebSocket: {ws_protocol}://{settings.HOST}:{settings.PORT}/ws")
  73. print("="*50 + "\n")
  74. uvicorn.run(
  75. "main:app",
  76. host=settings.host,
  77. port=settings.port,
  78. reload=True,
  79. ssl_keyfile=ssl_keyfile,
  80. ssl_certfile=ssl_certfile,
  81. )