04-28 周日 FastAPI Post请求同时传递文件和普通参数

04-28 周日 FastAPI Post请求同时传递文件和普通参数
时间版本修改人描述
04-28 周日V0.1宋全恒新建文档
2024年5月6日14:20:05V1.0宋全恒完成文档的传递

简介

 由于在重构FastBuild的时候,为了支持TLS是否启用,在接口中需要同时传递文件参数和其他参数,遇到了这个问题。结果发现由于HTTP的限制,不能同时传递JSON和文件参数。当时花费了较多的实践,因此记录了如下的过程。

代码示例

使用Form表单形式

 使用Form表单参数,可以实现,同时结合使用UploadFile可以非常方便。

@router.post("/update-docker-server")
async def update_docker_server_config(host: str = Form(), port: int = Form(), tls_tar_file: UploadFile = File(None)):if not validate_host(host):return Response.error(f"请输入有效的ip或者域名,参数host: {host}")new_docker_server = DBDockerServer(host=host,port=port,tls_verify=False)tls_verify = Falseif tls_tar_file:tls_folder_name = get_ip_address_folder(host)

 在相应的swagger页面上,显示如下所示:

image-20240428112217317

同时传递文件和对象参数

如何在FastAPI POST请求中同时添加文件和JSON主体?

image-20240506141857494

 由于上述的HTTP限制,因此,无法在维持JSON的结构的同时传递文件参数。

如here所述,用户可以使用FileForm字段同时定义文件和表单数据。

@router.post("/update-docker-server-in-object")
async def update_docker_server_config_in_object(docker_server_request: DockerServerRequest = Depends(docker_server_request_checker),tls_tar_file: UploadFile = File(None)):print(docker_server_request.host)

 docker_server_request_checker的定义如下:

from http.client import HTTPExceptionfrom fastapi import Form, status
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel, ValidationErrorclass DockerServerRequest(BaseModel):host: strport: int = 2375def docker_server_request_checker(data: str = Form(...)):try:model = DockerServerRequest.parse_raw(data)except ValidationError as e:raise HTTPException(detail=jsonable_encoder(e.errors()),status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,)return model
image-20240428144212784

 对于一个比较复杂的data参数,其中多层嵌套也是比较难写的。因为要手动生成这个结构,倒是不如直接使用Form表单化每个数据,第三方调用这个接口的时候,由于key是不用留心的,这样在传递参数的时候,不需要过多的注意力。

最后的实践

 由于FastBuild工程在运行时需要提前配置好容器所在的宿主机IP,Harbor的用户名和密码,Docker服务器(两种情形,一种是Docker启用了TLS,则需要上传文件tls-client-certs-jenkins.tar.gz, 另外则是普通的Docker服务),为了满足这多种情况,尤其是对于TLS的灵活性,因此最终选择了第一种方案,即使用多个Form参数以及文件参数的方式来完成对于FastBuild的统一配置接口

Controller

@router.post("/config-fastbuild")
async def update_docker_server_config_in_object(fastbuild_host: str = Form(), fastbuild_port: int = Form(default=48001),harbor_username: str = Form(), harbor_password: str = Form(), harbor_registry: str = Form(),harbor_registry_dns: str = Form(default=''),docker_host: str = Form(), docker_port: int = Form(default=2375), docker_tls_tar_file: UploadFile = File(None)):print("fastbuild: ", fastbuild_host, fastbuild_port)print("harbor: ", harbor_username, harbor_password, harbor_registry, harbor_registry_dns)if not all(map(validate_host, [fastbuild_host, harbor_registry, harbor_registry_dns, docker_host])):return Response.error(data="fastbuild_host, harbor_registry_host, harbor_registry_dns, docker_host均应为有效的ip或者域名")db_host = DBHost(host_ip=fastbuild_host, host_port=fastbuild_port)db_harbor = DBHarbor(username=harbor_username, password=harbor_password, registry=harbor_registry, registry_dns=harbor_registry_dns)db_docker = DBDockerServer(host=docker_host, port=docker_port, tls_verify=False)if docker_tls_tar_file:tls_folder_name = get_ip_address_folder(db_docker.host)tls_dir = save_and_extract_tar(docker_tls_tar_file, system_config.get_tls_dir(), tls_folder_name)tls_files = ["ca-jenkins.pem", "cert-jenkins.pem", "key-jenkins.pem"]if not all(file in get_files_in_directory(tls_dir) for file in tls_files):return Response.error(f"请上传正确的tls文件,当前上传的文件为{docker_tls_tar_file.filename},解压后不包含{' '.join(tls_files)}")db_docker.tls_verify = Truedb_docker.client_cert_path = os.path.join(tls_dir, "cert-jenkins.pem")db_docker.ca_path = os.path.join(tls_dir, "ca-jenkins.pem")db_docker.client_key_path = os.path.join(tls_dir, "key-jenkins.pem")try:image_utils = ImageUtils(db_docker, db_harbor)except DockerException as exe:print(f"发生异常: {exe}")raise FBException(code=123, message=f"使用提供的docker和harbor信息,进行登录测试,测试失败,请检查,错误信息为{str(exe)}")DBHostService.save(db_host)DBHarborService.save(db_harbor)DBDockerServerService.save(db_docker)return Response.success(data="成功完成为FastBuild配置需要的宿主机信息,Docker信息以及Harbor信息")

 其中validate_host用于判断输入的字符串是一个有效的ip或者域名,具体定义如下:

def validate_host(host: str):# 匹配 IP 地址的正则表达式ip_pattern = r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$"# 匹配域名地址的正则表达式domain_pattern = r"^(?!:\/\/)([a-zA-Z0-9-_]+\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+(\.[a-zA-Z]{2,11})$"# 尝试匹配 IP 地址和域名地址的正则表达式if re.match(ip_pattern, host) or re.fullmatch(domain_pattern, host):return True  # 主机地址合法else:return False  # 主机地址不合法

 而get_ip_address_folder则是用来根据ip地址获取对应的一个目录,其中包含了一个6位的随机数字

def get_ip_address_folder(ip: str):"""将 IP 地址或域名转换为文件夹名称,用于存储tls相关的文件:param ip: IP 地址或域名:return: 文件夹名称"""random_number = ''.join(random.choices('0123456789', k=6))# 将 IP 或域名中的 . 替换为 -converted_ip = str(ip).replace(".", "-")# 将随机数添加到转换后的字符串中result = f"{converted_ip}-{random_number}"return result

swagger请求

 如下,在配置时,传入多个参数。

image-20240506141542082

 由于按照Form参数类型传入值,因此需要再代码中重新组织这些参数,完成序列化。

    db_host = DBHost(host_ip=fastbuild_host, host_port=fastbuild_port)db_harbor = DBHarbor(username=harbor_username, password=harbor_password, registry=harbor_registry, registry_dns=harbor_registry_dns)db_docker = DBDockerServer(host=docker_host, port=docker_port, tls_verify=False)

总结

 这主要是因为之前FastBuild系统的启动,需要依赖一个外部Docker服务器来进行系统镜像的构建,因此,在启动的时候,需要事先准备好TLS支持的配置文件"ca-jenkins.pem", “cert-jenkins.pem”, “key-jenkins.pem”,而这样优化之后,则可以先启动FastBuild,通过接口完成对于FastBuild的配置,从而减少FastBuild的依赖,这真的是很好的一种工程实践。

注: 我们应该尽量增强工程的可配置性,而减少依赖性。不然每次重新部署,都需要花费很多的时间,让人非常的痛苦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/321059.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Vue3】Ref与Reactive

3.1【ref 创建:基本类型的响应式数据】 作用:定义响应式变量。语法:let xxx ref(初始值)。返回值:一个RefImpl的实例对象,简称ref对象或ref,ref对象的value属性是响应式的。注意点: JS中操作数…

docker 指定根目录 迁移根目录

docker 指定根目录 迁移根目录 1、问题描述2、问题分析3、解决方法3.1、启动docker程序前就手动指定docker根目录为一个大的分区(支持动态扩容),事前就根本上解决根目录空间不够问题3.1.0、方法思路3.1.1、docker官网安装文档3.1.2、下载docker安装包3.1.3、安装doc…

网络安全之交换基础

交换属于二层技术。路由器(router)是三层设备,可以基于IP地址转发,但需要路由表来记录。 交换机(switch)是二层设备,网桥(switch)也是二层设备,这两个都是基…

zabbix监控方式(zabbix-trapper)

中文:zabbix采集器,即zabbix sender 。 Zabbix-Trapper 监控方式可以一次批量发送数据给Zabbix Server,与主动模式不同,Zabbix-Trapper 可以让用户控制数据的发送,而不用Zabbix-Agent进程控制,这意味着可以…

【算法小白周赛1A】分析 - 题解与代码

题目链接:https://www.starrycoding.com/problem/155 题目描述 小可可最近在学数学运算!他希望考考你,给你两个整数 A , B A,B A,B,询问 A B A\times B AB 是否是偶数。 注意,可能存在前导 0 0 0,比如…

与Apolo共创生态: Apollo X企业自动驾驶解决方案的亮点

文章目录 前言技术革新的里程碑Apollo X企业自动驾驶解决方案的亮点Application X企业预制套件的多场景覆盖Studio X企业协同工具链的全周期支持第一阶段:上机系统构建第二阶段:POC搭建第三阶段:规模运营小结 共创生态,共享未来共…

Sermant在异地多活场景下的实践

Sermant社区在1.3.0和1.4.0版本相继推出了消息队列禁止消费插件和数据库禁写插件,分别用于解决异地多活场景下的故障切流和保护数据一致性问题。本文将对Sermant在异地多活场景下的实践进行剖析。 一、异地多活 1.1 什么是异地多活 对于一个软件系统,…

互联网十万个为什么之什么是云计算

云计算是一种通过互联网提供计算资源和服务的技术。它允许用户随时随地访问和使用云平台上的数据、软件和硬件资源。在数字化时代,互联网已经成为基础设施。云计算使得数据中心能够像一台计算机一样去工作。通过互联网将算力以按需使用、按量付费的形式提供给用户&a…

双热点的王炸组合!损失函数+Attention,精度与速度上实现SOTA!

损失函数注意力机制在深度学习领域是一个热门研究方向,它可以提高模型的性能和泛化能力,帮助我们构建更加精确且高效的模型。 具体来说: 通过结合注意力机制的聚焦能力和损失函数的优化指导,模型能够更精确地捕捉数据中的关键信息…

如何从Windows 10电脑远程登录Ubuntu系统

要从Windows 10电脑远程登录Ubuntu系统,您可以使用以下步骤: 在Ubuntu上安装xRDP: 首先,在Ubuntu电脑上打开终端,然后输入以下命令来安装xRDP服务: sudo apt update sudo apt install xrdpxRDP是一个开源的远程桌面协议…

ES6新特性

1.let声明变量 不允许重复声明、没有变量提升 暂存性死区 let a 1 function test(){console.log(a)//undefinedlet a2 } test() 不与顶层对象挂钩 let a 1 console.log(window.a)//undefined 块级作用域 var olidocument.querySelectorAll("ul li") for(var i0…

使用pandas的merge()和join()函数进行数据处理

目录 一、引言 二、pandas的merge()函数 基本用法 实战案例 三、pandas的join()函数 基本用法 实战案例 四、merge()与join()的比较与选择 使用场景: 灵活性: 选择建议: 五、进阶案例与代码 六、总结 一、引言 在数据分析和处理…

物联网技术、测试要点和测试标准

物联网定义 物联网:利用嵌入式电子设备、微芯片等连接车辆、家电、医疗设备,以收集和交换不同类型的数据,被称为物联网。借助物联网,用户能够远程控制设备,可以实现不同设备的互联。在现实生活中物联网开始有越来越多…

【消息队列】MQ介绍

MQ MQ(MessageQueue),中文是消息队列,就是存放消息的队列,也是下面提到的事件驱动架构中的Broker 同步调用的优点: 时效性强,可以立即得到结果 同步调用的问题: 耦合度高性能和吞吐…

2022 年全国职业院校技能大赛高职组云计算赛项试卷(容器云)

#需要资源(软件包及镜像)或有问题的,可私聊博主!!! #需要资源(软件包及镜像)或有问题的,可私聊博主!!! #需要资源(软件包…

自然语言(NLP)

It’s time for us to learn how to analyse natural language documents, using Natural Language Processing (NLP). We’ll be focusing on the Hugging Face ecosystem, especially the Transformers library, and the vast collection of pretrained NLP models. Our proj…

蓝牙连接手机播放音乐的同时传输少量数据,那些蓝牙芯片可以实现呢

简介 蓝牙连接手机播放音乐的同时连接另一蓝牙芯片传输少量数据,那些蓝牙芯片可以实现呢? 这个需求,其实就是双模的需求 简单描述就是:播放音乐的同时,还可以连接ble,进行数据的传输。二者同时进行,互不…

TCP的特性(4)

TCP特性 拥塞控制(可靠性机制)延迟应答(效率机制)捎带应答(效率机制)面向字节流(粘包问题)TCP异常机制(心跳包)小结 拥塞控制(可靠性机制) 虽然TCP引入了滑动窗口,能够高效可靠的传输大量数据,但是在开始阶段就发送大量数据,可能引起一系列问题. TCP引入了慢启动机制,先发少量的…

kafka学习笔记(三、生产者Producer使用及配置参数)

1.简介 1.1.producer介绍 生产者就是负责向kafka发送消息的应用程序。消息在通过send()方法发往broker的过程中,有可能需要经过拦截器(Interceptor)、序列化器(Serializer)和分区器(Partitioner)的一系列作用后才能被真正的发往broker。 demo: public class Kafk…