| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- """运营 Web(/web/admin)JSON 请求体解析。
- 与 ApiCryptoMiddleware 配合:中间件未改写 body 时,在路由内解密 `{ enc, ts, nonce, edata }`
- 并剥 `{ data: ... }`,避免 FastAPI 声明式 Body 在校验阶段只看到密文信封而 422。
- """
- from __future__ import annotations
- import logging
- from typing import Any, Optional, Tuple
- from fastapi import Request
- from app.core.request_payload import resolve_request_payload
- _log = logging.getLogger("sqxp")
- async def parse_admin_request_json(
- request: Request,
- current_user: dict,
- *,
- source: str,
- ) -> Tuple[Any, Optional[str]]:
- """
- 读取 JSON body;dict 时走 resolve_request_payload(明文 / 密文 / data 包装)。
- Returns:
- (payload, None) 成功;
- (_, err_msg) 密文解密失败(此时 payload 为原始 raw,调用方可忽略)。
- """
- dw = source.startswith("delivery_warning")
- try:
- raw: Any = await request.json()
- except Exception as ex:
- if dw:
- _log.warning("parse_admin_request_json source=%s request.json() failed: %s", source, ex)
- raw = {}
- if isinstance(raw, dict):
- if dw:
- ed = raw.get("edata")
- _log.info(
- "parse_admin_request_json source=%s raw_keys=%s enc=%s edata_len=%s user_id=%s",
- source,
- sorted(raw.keys()),
- int(raw.get("enc", 0) or 0),
- len(ed) if isinstance(ed, str) else (len(str(ed)) if ed is not None else 0),
- current_user.get("user_id"),
- )
- resolved = resolve_request_payload(raw, current_user, source=source)
- if dw:
- if isinstance(resolved, dict):
- _log.info(
- "parse_admin_request_json source=%s resolved_keys=%s",
- source,
- sorted(resolved.keys()),
- )
- else:
- _log.info(
- "parse_admin_request_json source=%s resolved_type=%s",
- source,
- type(resolved).__name__,
- )
- if resolved == {} and int(raw.get("enc", 0) or 0) == 1:
- if dw:
- _log.warning(
- "parse_admin_request_json source=%s treating as decrypt failure (resolved empty, enc=1)",
- source,
- )
- return raw, "密文解密失败"
- return resolved, None
- if dw:
- _log.warning(
- "parse_admin_request_json source=%s raw_not_dict type=%s",
- source,
- type(raw).__name__,
- )
- return raw, None
|