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://xiahunao.cn/news/3017613.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

matlab 基于拉依达检验法(3σ准则) 实现多类别多参数的批量异常样本检验 V2.0

简介 拉依达检验法(3σ准则)是一种统计学方法,用于检测数据中的异常值。这种方法基于正态分布的特性来确定数据点是否可能是异常值。以下是关于拉依达检验法(3σ准则)的详细介绍: 基本原理: 拉…

代码随想录第四十六天|单词拆分

题目链接:. - 力扣(LeetCode)

2.4V转3.8V/3.9V供电升压方案:为水表提供稳定电力

随着科技的不断发展,水表等智能设备在我们的生活中扮演着越来越重要的角色。为了让水表得以正常工作,稳定的电力供应是至关重要的。在这篇文章中,我们将探讨一种2.4V转3.8V/3.9V供电方案,以确保为水表提供稳定的电力。 为了实现2…

每日两题 / 138. 随机链表的复制 148. 排序链表(LeetCode热题100)

138. 随机链表的复制 - 力扣(LeetCode) 用哈希表记录原链表中的节点是否被复制过 遍历原链表并通过哈希表维护新链表 /* // Definition for a Node. class Node { public:int val;Node* next;Node* random;Node(int _val) {val _val;next NULL;rand…

STM32F407VET6 学习笔记1:GPIO引脚认识分类与开发板原理图

今日学习STM32F407VET6 ,首先从基本原理图、引脚方面开始做个初步理解并整理: 这里使用的学习开发板是在嘉立创购买的 立创梁山派天空星,芯片是 STM32F407VET6 主要对这个芯片的引脚做一些归纳认识、对开发学习板原理图设计进行认识理解:最…

23 JavaScript学习:验证API

JavaScript验证API 举例&#xff1a; <input id"id1" type"number" min"100" max"300" required> <button onclick"myFunction()">验证</button><p id"demo"></p><script>f…

HarmonyOS实战开发-如何实现Web组件中网页长截图。

介绍 本案例实现了Web组件中网页长截图的方案。支持截图后展示大小浮窗预览、保存图片到相册、手势左滑关闭等功能。 效果图预览 实现思路 本解决方案通过循环滚动Web组件&#xff0c;每次滚动截取当前状态后拼接到离屏画布&#xff0c;最后一次性转为PixelMap图片并显示在全…

Arduino PlatformIO避坑记

实在受不了Arduino IDE上古时期的界面风格&#xff0c;最要命的是编译速度慢到极点&#xff0c;好在有PlatformIO。VS搭配PlatformIO&#xff0c;有微软加持&#xff0c;界面自然是妥妥的了&#xff0c;编译速度提升也肉眼可见。 至于PlatformIO的安装过程&#xff0c;网上教程…

Day 24 数据库管理及数据类型

数据库管理及数据类型 一&#xff1a;数据类型 1.数值类型 整数类型 ​ 整数类型&#xff1a;TINYINT SMALLINT MEDIUMINT INT BIGINT ​ 作用&#xff1a;用于存储用户的年龄、游戏的Level、经验值等 浮点数类型 ​ 浮点数类型&#xff1a;FLOAT DOUBLE ​ 作用&#xf…

超疏水TiO₂纳米纤维网膜的良好性能

超疏水TiO₂纳米纤维网膜是一种具有特殊性能的材料&#xff0c;它结合了TiO₂的光催化性能和超疏水表面的自清洁、防腐、防污等特性。这种材料在防水、自清洁、油水分离等领域具有广阔的应用前景。 制备超疏水TiO₂纳米纤维网膜的过程中&#xff0c;通过精确控制纺丝溶液的成分…

vue3专栏项目 -- 项目介绍以及准备工作

这是vue3TS的项目&#xff0c;是一个类似知乎的网站&#xff0c;可以展示专栏和文章的详情&#xff0c;可以登录、注册用户&#xff0c;可以创建、删除、修改文章&#xff0c;可以上传图片等等。 这个项目全部采用Composition API 编写&#xff0c;并且使用了TypeScript&#…

PyQt5中重要的概念:信号与槽

PyQt中信号与槽概念定义如下&#xff08;网络上引用的&#xff09;&#xff1a; 信号&#xff08;signal&#xff09;和槽&#xff08;slot&#xff09;是Qt的核心机制&#xff0c;也是在PyQt编程中对象之间进行通信的机制。在创建事件循环之后&#xff0c;通过建立信号和槽的…

3W 1.5KVDC 3KVDC 隔离宽范围输入,单、双输出 DC/DC 电源模块——TP2L-3W 系列

TP2L-3W系列是一款高性能、超小型的电源模块&#xff0c;宽范围2:1,4:1输入&#xff0c;输出有稳压和连续短路保护功能&#xff0c;隔离电压为1.5KVDC、3KVDC工作温度范围为–40℃到85℃。特别适合对输出电压的精度有严格要求的地方&#xff0c;外部遥控功能对您的设计又多一项…

AIGC绘画辅助网站

Midjourney风格样式 Midjourney Style Classifier | Andrei Kovalevs Midlibrary

Python-VBA函数之旅-property函数

目录 一、property函数的常见应用场景 二、property函数使用注意事项 三、如何用好property函数&#xff1f; 1、property函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;神奇夜光杯-CSDN博客 一、prop…

Django 4.x 智能分页get_elided_page_range

Django智能分页 分页效果 第1页的效果 第10页的效果 带输入框的效果 主要函数 # 参数解释 # number: 当前页码&#xff0c;默认&#xff1a;1 # on_each_side&#xff1a;当前页码前后显示几页&#xff0c;默认&#xff1a;3 # on_ends&#xff1a;首尾固定显示几页&#…

多对多字段,执行aerich migrate命令报错

报错状态&#xff1a; 解决&#xff1a; 目前只知道通过修改源码的方式进行更改

【牛客】【模板】差分

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 差分模板。 b[0]a[0]; b[1]a[1]-a[0]; b[2]a[2]-a[1]; ...... b[n-1]a[n-1]-a[n-2]; b[n]a[n]-a[n-1]; 差分标记&#xff1a;b[l]k,b…

一部手机实现全行业的AI实景自动无人直播软件:为商家提供更便捷的推广方式

随着人工智能技术的快速发展&#xff0c;AI实景自动无人直播软件成为了商家推广产品的新宠。这款软件结合了智能讲解、一键开播、智能回复等多项功能&#xff0c;为商家提供了一种全新的直播方式。 首先&#xff0c;智能讲解功能让专业主播录制直播脚本&#xff0c;并通过软件自…

计划订单转采购申请的增强点和可以增强的内容

MD15 MD14 计划订单转采购申请&#xff0c;涉及的增强点和增强内容 对于外协的采购申请&#xff0c;有时候需要对组件的内容做一些特殊的处理&#xff0c;但是处理组件清单的增强ME_COMPONENTS_UPDATE的增强点&#xff08;这个增强点对于手工创建的外协PR、外协PO,外协pr转外协…