system_browser.py 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. """
  2. 桌面 / exe 场景:由后端唤起系统默认浏览器打开外链。
  3. 部分环境下前端 window.open 会被拦截;与 run_exe.py 中 webbrowser.open 打开仪表盘一致。
  4. """
  5. from __future__ import annotations
  6. import asyncio
  7. import webbrowser
  8. from urllib.parse import urlparse
  9. from fastapi import APIRouter
  10. from pydantic import BaseModel, Field
  11. from app.utils.response import error_response, success_response
  12. router = APIRouter(prefix="/system", tags=["系统"])
  13. class OpenExternalUrlBody(BaseModel):
  14. url: str = Field(..., min_length=8, max_length=4096)
  15. def _normalize_http_url(url: str) -> str | None:
  16. s = url.strip()
  17. if len(s) > 4096:
  18. return None
  19. parsed = urlparse(s)
  20. if parsed.scheme not in ("http", "https"):
  21. return None
  22. if not parsed.netloc:
  23. return None
  24. return s
  25. @router.post("/open-external-url")
  26. async def open_external_url(body: OpenExternalUrlBody):
  27. """在本机默认浏览器中打开 http(s) 链接。"""
  28. ok_url = _normalize_http_url(body.url)
  29. if not ok_url:
  30. return error_response(400, "仅允许有效的 http(s) 外链")
  31. opened = await asyncio.to_thread(webbrowser.open, ok_url)
  32. return success_response(data={"opened": bool(opened)})