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/web/errors.py
T
snowy-yang 2c55b55e03 feat(routes): 迁移查询类路由到 FastAPI + 会话互通 + 统一错误/限流
会话互通(迁移关键):
- core/session.py:itsdangerous 兼容的签名 Cookie 编解码(同密钥/同 salt/同
  时间戳编码),Flask 与 FastAPI 双向可读——实测 F->core 与 core->F 双向解出一致,
  篡改/错密钥返回 None

FastAPI 基础设施:
- web/deps.py    会话→当前用户(封禁/顶号校验,口径同 auth_system.current_user)
- web/errors.py  AppError + 全局异常处理,404/405/400 统一为本站包体
- web/ratelimit.py 复用 core.state 同一批限流桶(跨栈共享,避免绕框架绕过限流)
- core/repo.py  补 get_user_by_id(异步)

迁移路由(/api/v1/*,与 Flask 同端点逐字段对齐):
- toplist / artist_songs / comments / search,走 music_api 异步方法
- search 的服务器昵称遮蔽改为 FastAPI 侧异步实现(不再依赖 main)

契约奇偶校验:扩展至 7 项(含登录会话互通 + 未登录 401),全 OK;
CDN 分片主机差异归一化(上游易变值,非契约漂移)。

验证:pytest 33/33;ruff All checks passed;pyright 0 errors;
uvicorn 实跑未登录 401 包体与 Flask 一致。
2026-09-26 01:09:01 +08:00

41 lines
1.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""统一应用异常与错误响应。
FastAPI 依赖里无法直接「返回响应短路」,因此用抛出 AppError + 全局异常处理器
的方式,产出与 Flask 侧同形的 JSON 包体({status, success, message, error_code})。
"""
from typing import Any
from fastapi import Request
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException
from web.response import error
class AppError(Exception):
"""业务异常:携带 HTTP 状态码与可选 error_code。"""
def __init__(self, message: str, status_code: int = 400, error_code: str | None = None):
super().__init__(message)
self.message = message
self.status_code = status_code
self.error_code = error_code
def install_error_handlers(app) -> None:
@app.exception_handler(AppError)
async def _app_error(_request: Request, exc: AppError):
return error(exc.message, exc.status_code, exc.error_code)
@app.exception_handler(StarletteHTTPException)
async def _http_error(_request: Request, exc: StarletteHTTPException) -> Any:
# 404/405 等也统一为本站包体(Flask 侧 404 返回 {'success': False, ...})
msg = {404: '请求的资源不存在', 405: '请求方法不允许'}.get(exc.status_code,
str(exc.detail or '请求错误'))
return error(msg, exc.status_code)
@app.exception_handler(RequestValidationError)
async def _validation_error(_request: Request, exc: RequestValidationError):
return error('请求参数错误', 400)