사용자 지정 fastapi 쿼리 매개 변수 유효성 검사
FastAPI 쿼리 파라미터에 사용자 지정 유효성 검사 로직을 가질 수 있는 방법이 있습니까?
예
나는 다수의 요청 핸들러가 구성 요소를 쿼리 매개 변수로 사용하는 앱을 가지고 있다. 예를 들어 다음과 같습니다:
def _raise_if_non_relative_path(path: Path):
if path.is_absolute():
raise HTTPException(
status_code=409,
detail=f"Absolute paths are not allowed, {path} is absolute."
)
@app.get("/new",)
def new_file(where: Path):
_raise_if_non_relative_path(where)
# do save a file
return Response(status_code=requests.codes.ok)
@app.get("/new",)
def delete_file(where: Path):
_raise_if_non_relative_path(where)
# do save a file
return Response(status_code=requests.codes.ok)
주어진 파일 경로가 절대적일 때 핸들러가 호출되지 않도록 하는 방법이 있는지 궁금합니다. 이제 나는 모든 곳에서 나 자신을 반복해야 한다.
내가 해본것
- : 이것은 매우 기본적인 검증(스트링 길이와 regex)만 가능하다. 나는 이 예에서 a를 정의할 수 있다. 하지만 regex 솔루션은 정말 일반적이지 않아요, 맞춤형 기능으로 검증하고 싶어요.
- 유효성 검사 로직이 있는 하위 클래스 : 이것은 작동하지 않으며, 형식 서명에 주어진 유형은 무시되며, 내 핸들러의 객체는 일반적인 것입니다.
- 사용 : 이것은 작동할 수 있지만 내 요청 핸들러가 모두 개체를 다루는 것은 아니기 때문에 과도한 것으로 보입니다.
- : 즉, 원하는 대로 검증할 수 있는 단일 필드로 클래스를 정의합니다. 안타깝게도 쿼리 매개 변수에는 적용되지 않습니다. 이렇게 하면 요청 처리자가 json content body를 갖자고 주장합니다. 아니면 적어도 그것이 그 으스대는 의사들이 말하는 것이다.
참고: Pydantic의 이전 버전을 사용할 가능성이 있으며 수정된 솔루션이 필요할 가능성이 있습니다. 이것은 Pydantic >= 2.0을 사용하는 프로젝트를 위한 것입니다.
FastAPI는 Pydantic 모델로 정의되지 않은 매개 변수를 검증하기 위해 Pydantic을 후드 아래에 사용하며, Pydantic의 객체에 추가 인수를 전달한다.
즉, 및 에 추가 인수를 전달할 수 있으며, 이 인수를 사용하여 사용자 지정 검증자를 정의할 수 있습니다.
from typing import Annotated
from fastapi import APIRouter, Path, Query
router = APIRouter("/prefix")
# Define validator according to Pydantic patterns
# https://docs.pydantic.dev/latest/concepts/validators/
def lowercase_validator(value: str) -> str:
assert value.lower() == value, f"{value} is not lowercase"
return value
# Define route using Path and Query parameters
# https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/
# https://fastapi.tiangolo.com/tutorial/query-params-str-validations/
@router.get("/{path}")
async def some_path(
path: str = Path(annotation=Annotated[str, AfterValidator(lowercase_validator)]),
arg: str = Query(annotation=Annotated[str, AfterValidator(lowercase_validator)]),
):
pass
이 솔루션은 FastAPI가 이를 정상적인 유효성 검사의 일부로 직접 처리하고 다른 모든 유효성 검사 실패와 동일한 유형의 오류를 반환하도록 합니다.
원래 질문의 경우, 당신은 검증자를 다음과 같은 것으로 만들 것이다
import pathlib
def validate_relative_path(path: pathlib.Path):
assert not path.is_absolute(), f"{path} is not relative"
return Path
그리고 그것을 경로에 사용하는 것과 같은
@app.get("/new",)
def new_file(where: pathlib.Path = Query(annotation=Annotated[str, AfterValidator(validate_relative_path)])):
pass
이것은 아주 적합한 종류의 검증이다. 이를 통해 주어진 뷰 함수에 대한 종속성을 정의하고, 이러한 종속성을 검증하기 위한 논리를 추가할 수 있습니다. 이를 통해 필요한 뷰에서 다시 사용할 수 있는 일련의 합성 가능한 종속성이 제공됩니다.
종속성을 생성한 다음 이에 의존하여 필요한 검증을 수행할 수 있습니다:
from fastapi import Depends, FastAPI, Response, Query
from fastapi.exceptions import HTTPException
from pathlib import Path
import requests
app = FastAPI()
def relative_where_query(where: Path = Query(...)):
if where.is_absolute():
raise HTTPException(
status_code=409,
detail=f"Absolute paths are not allowed, {where} is absolute."
)
return where
@app.get("/new")
def new_file(where: Path = Depends(relative_where_query)):
return Response(status_code=requests.codes.ok)
이것은 작고 쉽게 읽을 수 있는(그리고 이해할 수 있는) 뷰 기능을 제공하는 반면 종속성("쿼리 매개변수로부터 상대적인 경로가 필요합니다")은 자체 정의로 이동되었다.
그런 다음 쿼리 매개 변수에서 상대 경로가 필요한 모든 뷰 함수에서 이 종속성을 다시 사용할 수 있습니다(필요한 경우 이러한 종속성을 추가로 분해하고 재구성할 수 있습니다).
: 이 처리를 일반화하여 필드 이름을 유효성 검사 함수에서 분리하려면 동적 종속성을 생성하여 이를 수행할 수 있습니다. 이 예들은 Pydantic과 함께 동적 기본 모델을 만들어 내지만, 다른 방법들도 분명히 존재합니다.
이제 Pydantic validator 내부에서 오류를 제기하므로 경로가 유효하지 않을 경우 적절한 오류 응답을 제공하기 위해 예외 처리기를 추가합니다.
마법 자체는 내부에서 발생한다 - 이 함수는 주어진 이름을 사용한다. 그리고 나서 이 모델은 컨트롤러에서 종속적인 것으로 사용된다.
함수에 대한 인수로 주어진 이름은 호출될 때(이 경우 URL에 있음)와 문서가 표시될 때 모두 실제 매개 변수 이름이 됩니다. 컨트롤러 함수의 이름 자체는 함수 내부에서만 관련이 있으며 문서나 쿼리 매개 변수(모델의 필드 이름이 이에 사용됨)로 사용되지 않습니다.
from fastapi import Depends, FastAPI, Response, Query, Request
from fastapi.exceptions import HTTPException
from fastapi.responses import JSONResponse
from pathlib import Path
from pydantic import create_model, validator
import requests
app = FastAPI()
class PathNotAbsoluteError(Exception):
pass
@app.exception_handler(PathNotAbsoluteError)
async def value_error_exception_handler(request: Request, exc: PathNotAbsoluteError):
return JSONResponse(
status_code=400,
content={"message": str(exc)},
)
def path_is_absolute(cls, value):
if not value.is_absolute():
raise PathNotAbsoluteError("Given path is not absolute")
return value
def path_validator(param_name):
validators = {
'pathname_validator': validator(param_name)(path_is_absolute)
}
return create_model(
"AbsolutePathQuery",
**{param_name: (Path, Query(...))},
__validators__=validators,
)
@app.get("/path")
def new_file(path: Path = Depends(path_validator("where"))):
return Response(status_code=requests.codes.ok)
이제 지정된 매개 변수 이름에 종속성을 추가하여 원하는 위치에서 이를 재사용할 수 있습니다:
def new_file(path: Path = Depends(path_validator("my_path"))):
...
def old_file(path: Path = Depends(path_validator("where"))):
...
'개발하자' 카테고리의 다른 글
Jupyter 노트북 새 셀 유형 기본값 (0) | 2023.10.04 |
---|---|
나중을 위해 주피터(IPython) 노트북 세션을 절이거나 저장하는 방법 (0) | 2023.10.03 |
python SDK를 통해 코스모스 처리량 업데이트 (0) | 2023.10.02 |
Visual Studio 코드를 사용하여 스크립트 파일 실행 입력 (0) | 2023.10.01 |
Svelte - on: 블러 이벤트 후에만 입력 화재 시 핸들러 변경 (0) | 2023.10.01 |