fix: IP格式校验用field_validator替代model_validator
model_validator(mode='after')抛出ValueError时FastAPI不能正确序列化为422 → 导致500 TypeError: Object of type ValueError is not JSON serializable 改用field_validator(mode='before')由Pydantic正常捕获返回422
This commit is contained in:
+11
-9
@@ -14,7 +14,7 @@ import socket
|
||||
|
||||
import bcrypt
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
from server.api.dependencies import get_db
|
||||
from server.api.auth_jwt import get_current_admin
|
||||
@@ -841,15 +841,16 @@ _DOMAIN_RE = re.compile(r"^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-
|
||||
class IpAllowlistRequest(BaseModel):
|
||||
ips: list[str] = Field(..., min_length=1, max_length=100, description="IP or hostname list")
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_ips(self):
|
||||
for raw in self.ips:
|
||||
@field_validator("ips", mode="before")
|
||||
@classmethod
|
||||
def validate_ips(cls, v: list[str]) -> list[str]:
|
||||
for raw in v:
|
||||
ip = raw.strip()
|
||||
if not ip:
|
||||
continue
|
||||
if not (_IP_RE.match(ip) or _DOMAIN_RE.match(ip)):
|
||||
raise ValueError(f"无效的 IP/CIDR/域名: {ip}")
|
||||
return self
|
||||
return v
|
||||
|
||||
|
||||
class SubscriptionParseRequest(BaseModel):
|
||||
@@ -938,15 +939,16 @@ class IpAllowlistSaveRequest(BaseModel):
|
||||
subscription_url: Optional[str] = None # None = don't change; "" = clear
|
||||
enabled: Optional[bool] = None # None = don't change
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_manual_ips(self):
|
||||
for raw in self.manual_ips:
|
||||
@field_validator("manual_ips", mode="before")
|
||||
@classmethod
|
||||
def validate_manual_ips(cls, v: list[str]) -> list[str]:
|
||||
for raw in v:
|
||||
ip = raw.strip()
|
||||
if not ip:
|
||||
continue
|
||||
if not (_IP_RE.match(ip) or _DOMAIN_RE.match(ip)):
|
||||
raise ValueError(f"无效的 IP/CIDR/域名: {ip}")
|
||||
return self
|
||||
return v
|
||||
|
||||
|
||||
@router.post("/ip-allowlist", response_model=dict)
|
||||
|
||||
Reference in New Issue
Block a user