Archived
feat(routes): 迁移解析端点 /song /playlist /album + 响应卫生中间件
迁移路由(/api/v1/*,与 Flask 同端点逐字段对齐): - song(type: url/name/lyric/json)、playlist、album 个人账号路径实现全局账号冒用拦截(同 Flask 口径);json 模式 asyncio.gather 并发 song/url/lyric(歌词失败不阻断,与 Flask 线程池语义一致) - core/media.py:format_file_size/quality_display_name/parse_cookie_str 纯函数复用 web/middleware.py(镜像 Flask after_request): - 音频直链 → HMAC 签名代理地址(密钥同源,两栈 token 互认) - 安全头 nosniff/DENY/Referrer-Policy/CSP 基线;Server 抹为 NeteaseUrl;429 带 Retry-After - 纯 ASGI 逐段转发(不破坏流式下载);JSON 200 延迟 start 并**重算 Content-Length** ——修实测 IncompleteRead(原实现转发旧长度 + 新 body) 契约奇偶校验:12 项全 OK(新增 album/playlist/song×3); token/CDN 主机归一化(均为易变值,非契约漂移)。 验证:pytest 36/36;ruff All checks passed;pyright 0 errors; uvicorn 实跑 /api/v1/song 直链已代理、CSP/Server 头正确。
This commit is contained in:
1 parent
2c55b55e03
commit
a2758aa0da
5 files changed
+452
-8
No files matched your search
@@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""媒体相关的纯函数(文件大小/音质显示名/Cookie 串解析)——框架无关。
|
||||
|
||||
与 main.MusicAPIService 上的同名方法保持逐字一致的实现,
|
||||
供 FastAPI 栈直接复用,避免两栈各写一份而漂移。
|
||||
"""
|
||||
|
||||
|
||||
def format_file_size(size_bytes) -> str:
|
||||
"""格式化文件大小(上游 size 可能为 null/垃圾值:容错返回"大小未知"而非 500)"""
|
||||
try:
|
||||
size = float(size_bytes or 0)
|
||||
except (TypeError, ValueError):
|
||||
return "大小未知"
|
||||
if size <= 0:
|
||||
return "0B"
|
||||
|
||||
units = ["B", "KB", "MB", "GB", "TB"]
|
||||
unit_index = 0
|
||||
while size >= 1024.0 and unit_index < len(units) - 1:
|
||||
size /= 1024.0
|
||||
unit_index += 1
|
||||
return f"{size:.2f}{units[unit_index]}"
|
||||
|
||||
|
||||
_QUALITY_NAMES = {
|
||||
'standard': '标准音质',
|
||||
'exhigh': '极高音质',
|
||||
'lossless': '无损音质',
|
||||
'hires': 'Hi-Res音质',
|
||||
'sky': '沉浸环绕声',
|
||||
'jyeffect': '高清环绕声',
|
||||
'jymaster': '超清母带',
|
||||
'dolby': '杜比全景声',
|
||||
}
|
||||
|
||||
|
||||
def quality_display_name(quality: str) -> str:
|
||||
return _QUALITY_NAMES.get(quality, f"未知音质({quality})")
|
||||
|
||||
|
||||
def parse_cookie_str(raw) -> dict[str, str]:
|
||||
"""将 'k=v;k2=v2' 格式的 Cookie 字符串解析为字典"""
|
||||
cookies: dict[str, str] = {}
|
||||
if not raw:
|
||||
return cookies
|
||||
for part in str(raw).split(';'):
|
||||
if '=' in part:
|
||||
k, v = part.strip().split('=', 1)
|
||||
if k:
|
||||
cookies[k] = v
|
||||
return cookies
|
||||
Reference in new issue
Block a user