from __future__ import annotations import fnmatch from collections.abc import Iterable from typing import Any, Callable from fastapi import Request RAW_RESPONSE_ATTR = "__iti_raw_response__" ENVELOPE_FIELDS = {"data", "code", "message"} def raw_response(func: Callable) -> Callable: setattr(func, RAW_RESPONSE_ATTR, True) return func def is_envelope_payload(value: Any) -> bool: return isinstance(value, dict) and ENVELOPE_FIELDS.issubset(value.keys()) def is_raw_response_request(request: Request, raw_paths: Iterable[str]) -> bool: endpoint = request.scope.get("endpoint") if endpoint is not None and getattr(endpoint, RAW_RESPONSE_ATTR, False): return True path = request.url.path for pattern in raw_paths: if pattern == path or fnmatch.fnmatch(path, pattern): return True return False