fastapi封装post、get请求
需要用到的相关python库
from pydantic import BaseModel
from typing import Generic, TypeVar, Type, Any
import httpx
1. 封装响应体
T = TypeVar("T")
class ResponseTemplate(BaseModel, Generic[T]):
flag_ret: bool
data: T | list[T] | None
msg: str | None
class Response:
@staticmethod
def success(*, data: T = None, msg: str = "操作成功") -> ResponseTemplate[T]:
return ResponseTemplate(flag_ret=True, data=data, msg=msg)
@staticmethod
def fail(*, data: Any = None, msg: str = "操作失败") -> ResponseTemplate[T]:
return ResponseTemplate(flag_ret=False, data=data, msg=msg)
2.封装post请求
ReqTemplate = TypeVar("ReqTemplate", bound=BaseModel)
RespTemplate = TypeVar("RespTemplate", bound=ResponseTemplate)
async def sendReqPost(ClsReq: Type[ReqTemplate], ClsResp: Type[RespTemplate], url, **kwargs: Any)->tuple[Type[RespTemplate]|None, str]:
req = None
try:
req = ClsReq(**kwargs)
except Exception as e:
return None, f'make request body failed, {e}'
try:
async with httpx.AsyncClient(timeout=3*60) as client:
dict_data = req.model_dump()
response = await client.post(url, json=dict_data)
try:
ret = ClsResp.model_validate(response.json())
if ret.flag_ret:
return ret, ''
return None, f'{ret.msg}'
except Exception as e:
return None, f'{extractValidateErrFromDefaultJson(response.json())}'
except Exception as e:
return None, f'{e}'
3.封装get请求
RespTemplate = TypeVar("RespTemplate", bound=ResponseTemplate)
async def sendReqGet(ClsResp: Type[RespTemplate], url, **kwargs: Any)->tuple[Type[RespTemplate]|None, str]:
try:
async with httpx.AsyncClient(timeout=3*60) as client:
response = await client.get(url, params=kwargs)
try:
ret = ClsResp.model_validate(response.json())
if ret.flag_ret:
return ret, ''
return None, f'{ret.msg}'
except Exception as e:
return None, f'{extractValidateErrFromDefaultJson(response.json())}'
except Exception as e:
return None, f'{e}'
4. 调用
get请求
- fastapi server
@app.get("/get")
def getIp(num:int, q:str):
try:
return Response.success(data={num,q})
except Exception as e:
return Response.fail(msg=f'{e}')
- client
ret, msg = asyncio.run(sendReqGet(ClsResp=ResponseTemplate, url='http://localhost:8000/get', num=1, q='123'))
post请求
- post请求与get请求不同,需要用pydantic检验参数合法性,因此需要提前定义好结构体
from pydantic import BaseModel
class RequestBuildParam(BaseModel):
url_ssh_repository:str
checkout_target:str
command:str
list_to_pack:list[str]
ip_dst:str
path_folder_dst:str
- fastapi定义post接口
@app.post("/build")
def build(build_param:RequestBuildParam):
try:
clelery_app = Celery('auto_builder')
clelery_app.config_from_object(celery_config)
param_scheduler = ParamScheduler(NUM_WORKER, clelery_app, PATH_FOLDER_REPOS, build_param.url_ssh_repository)
path_file_pack = genZipPath(PATH_FOLDER_PACK)
param_task = ParamTask(path_file_pack, build_param.checkout_target, build_param.command, build_param.list_to_pack, build_param.ip_dst, build_param.path_folder_dst)
work_scheduler = WorkScheduler()
ret, msg = work_scheduler.init(param_scheduler, callbackInfo, callbackErr)
id = work_scheduler.addTask(param_task)
return Response.success(data=id)
except Exception as e:
return Response.fail(msg=f'{e}')
- 给fastapi发请求
ret, msg = await sendReqPost(ClsReq=RequestBuildParam, ClsResp=ResponseTemplate, url="http://localhost:8000/build",
url_ssh_repository = text_ssh.value,
checkout_target = text_checkout.value,
command = text_command.value,
list_to_pack = list_pack,
ip_dst = text_ip_dst.value,
path_folder_dst = text_path_folder_dst.value
)
if ret:
id = ret.data