From e70c197d6512c9f80dcd89387b5b8234b5fdc23a Mon Sep 17 00:00:00 2001 From: MingxuanGame Date: Tue, 12 Aug 2025 09:01:10 +0000 Subject: [PATCH] feat(app): add frontend url configuration --- .env.example | 2 ++ README.md | 1 + app/config.py | 1 + app/router/__init__.py | 2 ++ app/router/redirect.py | 23 +++++++++++++++++++++++ main.py | 4 ++++ 6 files changed, 33 insertions(+) create mode 100644 app/router/redirect.py diff --git a/.env.example b/.env.example index f73f754..4bdee9e 100644 --- a/.env.example +++ b/.env.example @@ -22,6 +22,8 @@ PORT=8000 SERVER_URL="http://localhost:8000" # 额外的 CORS 允许的域名列表 CORS_URLS='[]' +# 前端 URL,当访问从游戏打开的 URL 时会重定向到这个 URL,为空表示不重定向 +FRONTEND_URL # 调试模式,生产环境请设置为 false DEBUG=false # 私有 API 密钥,用于前后端 API 调用,使用 openssl rand -hex 32 生成 diff --git a/README.md b/README.md index 9293b97..f0f754f 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ docker-compose -f docker-compose-osurx.yml up -d | `DEBUG` | 调试模式 | `false` | | `SERVER_URL` | 服务器 URL | `http://localhost:8000` | | `CORS_URLS` | 额外的 CORS 允许的域名列表 (JSON 格式) | `[]` | +| `FRONTEND_URL` | 前端 URL,当访问从游戏打开的 URL 时会重定向到这个 URL,为空表示不重定向 | `` | | `PRIVATE_API_SECRET` | 私有 API 密钥,用于前后端 API 调用 | `your_private_api_secret_here` | ### OAuth 设置 diff --git a/app/config.py b/app/config.py index ff1bec8..008172b 100644 --- a/app/config.py +++ b/app/config.py @@ -67,6 +67,7 @@ class Settings(BaseSettings): private_api_secret: str = "your_private_api_secret_here" cors_urls: list[HttpUrl] = [] server_url: HttpUrl = HttpUrl("http://localhost:8000") + frontend_url: HttpUrl | None = None # SignalR 设置 signalr_negotiate_timeout: int = 30 diff --git a/app/router/__init__.py b/app/router/__init__.py index c5b5b79..32248cb 100644 --- a/app/router/__init__.py +++ b/app/router/__init__.py @@ -6,6 +6,7 @@ from .auth import router as auth_router from .fetcher import fetcher_router as fetcher_router from .file import file_router as file_router from .private import private_router as private_router +from .redirect import redirect_router as redirect_router from .v2.router import router as api_v2_router __all__ = [ @@ -14,5 +15,6 @@ __all__ = [ "fetcher_router", "file_router", "private_router", + "redirect_router", "signalr_router", ] diff --git a/app/router/redirect.py b/app/router/redirect.py new file mode 100644 index 0000000..dd5122f --- /dev/null +++ b/app/router/redirect.py @@ -0,0 +1,23 @@ +from __future__ import annotations + +import urllib.parse + +from app.config import settings + +from fastapi import APIRouter, Request +from fastapi.responses import RedirectResponse + +redirect_router = APIRouter(include_in_schema=False) + + +@redirect_router.get("/users/{user_id}") +@redirect_router.get("/u/{user_id}") +@redirect_router.get("/b/{beatmap_id}") +@redirect_router.get("/s/{beatmapset_id}") +@redirect_router.get("/beatmapsets/{path:path}") +@redirect_router.get("/multiplayer/rooms/{room_id}") +async def redirect(request: Request): + return RedirectResponse( + urllib.parse.urljoin(str(settings.frontend_url), request.url.path), + status_code=301, + ) diff --git a/main.py b/main.py index cebc626..cebdcd5 100644 --- a/main.py +++ b/main.py @@ -16,6 +16,7 @@ from app.router import ( private_router, signalr_router, ) +from app.router.redirect import redirect_router from app.service.daily_challenge import daily_challenge_job from app.service.osu_rx_statistics import create_rx_statistics @@ -60,6 +61,9 @@ app.add_middleware( allow_headers=["*"], ) +if settings.frontend_url is not None: + app.include_router(redirect_router) + @app.get("/", include_in_schema=False) async def root():