This repository has been archived on 2026-10-02. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
NeteaseUrl/tests/test_root_mode.py
T
snowy-yang 8446166120 refactor!: uv 管理环境 + 彻底删除技术债(Flask 与 requests 全部移除)
## uv 环境管理
- pyproject.toml 声明 dependencies + [dependency-groups].dev,uv.lock 精确锁定
- 删除 requirements.txt / requirements-fastapi.txt / requirements-dev.txt
- .python-version = 3.12;Dockerfile 改用 uv sync --frozen(可复现构建)
- 新增 jinja2(首页渲染)

## 删除 Flask 技术债
- 从 main.py 用 ast 精确剥离 56 个 Flask 节点(路由/中间件/错误处理/启动),
  框架无关的服务层落为 services/runtime.py(MusicAPIService、下载/打包 worker、
  任务监控、缓存清扫),零 Flask 依赖
- 删除 main.py(4527 行)与 auth_routes.py(1050 行)
- auth_system.py 移除会话/请求上下文层(login_session/current_user/login_required/
  admin_required/_client_ip 等),保留数据与业务层
- 新增 core/net.py(IP 解析)、web/auth_state.py(登录锁定/2FA 票据/发码限流)
- FastAPI 侧改直接依赖 services.runtime,不再 import main
- web/app.py 去掉 Flask fallback;入口默认根路径模式(API_PREFIX 可选)

## 删除 requests 技术债
- 新增 core/sync_http.py:requests 风格的同步门面(底层 aiohttp 连接池,
  流式读取经有界队列背压),含 Session/headers/(connect,read) 元组超时兼容
- core/utils、auth_system、podcast_api、music_downloader、services 全部切换
- 实测真实下载 5.2MB 音频完整成功

## 质量门禁归零
- ruff:0 错误(B904 全部修复,不再忽略)
- pyright:0 错误(类型收窄修复)
- pytest:140/140(含 golden 契约回归、root 模式 66 项路径覆盖)
- 真实 uvicorn 启动:/health、/、/static、受保护端鉴权全部正确

新增 tests/golden/responses.json:删除 Flask 前捕获的 32 例响应快照,
FastAPI 逐字段复现——删除巨石后行为回归仍有硬证据。
2026-09-26 11:10:17 +08:00

68 lines
3.0 KiB
Python

# -*- coding: utf-8 -*-
"""纯 FastAPI 模式(api_prefix='')测试:前端全部路径由 FastAPI 服务。"""
import warnings
import pytest
from fastapi.testclient import TestClient
warnings.filterwarnings('ignore')
# 前端实际调用的路径(从 index.html / site_auth.js 抽取的代表集合)
FRONTEND_PATHS = [
'/', '/health', '/api/info', '/song', '/search', '/playlist', '/album',
'/toplist', '/artist_songs', '/comments',
'/auth/me', '/auth/login', '/auth/logout', '/auth/heartbeat', '/auth/register',
'/auth/send_code', '/auth/redeem', '/auth/forgot_password', '/auth/ann_seen',
'/auth/admin_login/email', '/auth/admin_login/verify',
'/user/status', '/user/logout', '/user/qr/create', '/user/qr/check',
'/user/playlists', '/user/playlist', '/user/collect', '/user/comment',
'/account/vip', '/global/playlists', '/global/playlist', '/api/playlist/play',
'/download', '/download/batch_zip', '/download/result', '/download/batch_zip/result',
'/podcast/parse', '/podcast/programs', '/podcast/search', '/podcast/hot',
'/podcast/download', '/podcast/download/batch_zip',
'/api/topen', '/api/queue', '/api/batch_progress', '/api/task/cancel',
'/api/task/heartbeat', '/api/task/list', '/api/fe_error', '/audio_stream',
'/admin/qr/create', '/admin/qr/check', '/admin/cookie/status', '/admin/cookie/delete',
'/admin/logs', '/admin/site/users', '/admin/site/logs', '/admin/site/cards/list',
'/admin/site/ann/get', '/admin/site/play_key/get', '/admin/site/backup/list',
'/admin/site/smtp/get', '/admin/site/user/cookie',
]
@pytest.fixture()
def root_client(tmp_path, monkeypatch):
"""root 模式应用(不挂 Flask 兜底、前缀为空)。"""
import auth_system as auth
import core.db as db
monkeypatch.setattr(auth, 'DATA_DIR', tmp_path)
monkeypatch.setattr(auth, 'DB_PATH', tmp_path / 'site.db')
monkeypatch.setattr(auth, 'BACKUP_DIR', tmp_path / 'backups')
monkeypatch.setattr(auth, 'SECRET_KEY_PATH', tmp_path / 'secret.key')
monkeypatch.setattr(db, 'DATA_DIR', tmp_path)
monkeypatch.setattr(db, 'DB_PATH', tmp_path / 'site.db')
auth.init_db()
monkeypatch.setattr('web.deps.secret_key', lambda: 'root-mode-secret')
from web.app import create_app
return TestClient(create_app(api_prefix=''))
@pytest.mark.parametrize('path', FRONTEND_PATHS)
def test_frontend_path_not_404(root_client, path):
"""前端调用的每条路径都必须有 FastAPI 路由(不得 404)。"""
r = root_client.post(path, json={})
assert r.status_code != 404, f'{path} 在纯 FastAPI 模式下 404'
def test_root_page_served(root_client):
r = root_client.get('/')
assert r.status_code == 200
assert r.headers.get('cache-control', '').startswith('no-cache')
def test_no_api_v1_prefix_in_root_mode(root_client):
"""根路径模式下不再有 /api/v1 前缀(Flask 时代的比对前缀已废弃)。"""
r = root_client.post('/api/v1/song', json={})
assert r.status_code == 404