settings.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. from dataclasses import dataclass, field
  2. import math
  3. from urllib.parse import urlsplit
  4. import config
  5. @dataclass(frozen=True)
  6. class ResultPlatformSettings:
  7. # 完整的接收接口 URL,不假设正式平台的路径。
  8. url: str
  9. token: str = field(default="", repr=False)
  10. auth_header: str = "Authorization"
  11. auth_scheme: str = "Bearer"
  12. timeout: float = 30
  13. success_field: str = "code"
  14. success_values: tuple[str, ...] = ("0", "200")
  15. def __post_init__(self):
  16. parts = urlsplit(self.url)
  17. if (parts.scheme not in {"http", "https"} or not parts.netloc or parts.username
  18. or parts.password or parts.query or parts.fragment):
  19. raise ValueError("RESULT_PLATFORM_URL 必须是无内嵌凭证、查询串和片段的 HTTP(S) 接收接口地址")
  20. if self.auth_header and not self.token.strip():
  21. raise ValueError("结果平台鉴权需要 RESULT_PLATFORM_TOKEN;无鉴权接口应设置 RESULT_PLATFORM_AUTH_HEADER=none")
  22. if any("\r" in value or "\n" in value for value in (self.token, self.auth_header, self.auth_scheme)):
  23. raise ValueError("结果平台鉴权配置不能包含换行")
  24. if not math.isfinite(self.timeout) or self.timeout <= 0:
  25. raise ValueError("结果平台超时必须大于零")
  26. if not self.success_field or not self.success_values:
  27. raise ValueError("结果平台需要配置成功回执字段及成功值")
  28. @classmethod
  29. def from_config(cls):
  30. header = config.get_str("RESULT_PLATFORM_AUTH_HEADER", "Authorization").strip()
  31. scheme = config.get_str("RESULT_PLATFORM_AUTH_SCHEME", "Bearer").strip()
  32. return cls(
  33. url=config.get_str("RESULT_PLATFORM_URL").strip(),
  34. token=config.get_str("RESULT_PLATFORM_TOKEN"),
  35. auth_header="" if header.lower() == "none" else header,
  36. auth_scheme="" if scheme.lower() == "none" else scheme,
  37. timeout=config.get_float("RESULT_PLATFORM_TIMEOUT", 30),
  38. success_field=config.get_str("RESULT_PLATFORM_SUCCESS_FIELD", "code"),
  39. success_values=tuple(s.strip() for s in config.get_str("RESULT_PLATFORM_SUCCESS_VALUES", "0,200").split(",") if s.strip()),
  40. )