FastAPI接口请求带来的一系列疑问与收获

背景

最近把AIGC调用的接口部署起来后,在调用过程遇到了点问题,比如图生图的时候没用办法直接传送图片信息,必须进行转码,且图片的大小可能也存在限制。因此,打算系统性的梳理一下遇到的问题和踩过的坑。


FastAPI接口参数定义

我用的接口是用Ray serve进行部署的,Ray是一个分布式的计算框架,包含数据、模型、训练、微调和部署整套流程的服务,这里可以简单理解为该模块是在Fast Api的基础上做了些封装和完善。我定义的接口是一个post的接口,部署起来后,返回的状态码一直显示错误,一直没发现存在什么问题,后面经过多方搜寻,发现错误的原因是传递的参数中存在无法识别的参数。
经过查询后,原来是因为post接口的参数不能随意起,必须以json的格式传送

@app.get("/get")
async def get(a: int, b:int):
    '''
    一个带有参数的get请求,分别有2个int类型的参数
    '''
  
    result = {'a': a, 'b': b}
    return result
from pydantic import BaseModel

class User(BaseModel):
    a: int
    b: int        

      
@app.post("/post")
async def post(request_data: User):
    '''
    必须传json的post接口, request_data: json字段(User类)
    '''
    a = request_data.a
    b = request_data.b

    result = {'a': a, 'b': b}
    return result

错误的原因是我把post的参数直接像get一样在接口中声明了,所以就会出错。一般的做法是自己根据需求定义一个参数类,继承BaseModel基类,这个参数类其实就可以当成是一个json来处理了。


UTF-8编码、base64编码、字符与字节的区别和联系

字符是用来显示的,字节是用来存储的。 UTF-8编码是常见的字符编码方式,其他的还有GBK编码等。而base64只能用于字节的编码。对于一个字节还要进行base64的编码,简单来说可能作用就是把所有不统一的字节再经过一轮转换,变成大家都能识别的更小的字节了,就是一个英文字符,如a,B这种,每个字符都是一个字节(Bytes),8个Bits,因此英文编码成字节是不存在问题的,如b'ABC'共有24个比特位,每8个比特位能定位出原字母。但是对于中文字符,每个中文字符需要3个字节才能完整编码(以常用的UTF-8编码方式),如果b'中文'共有48比特位,中文字符数量又多,因此就会存在编码错误的情况。
base64.b64encode()


图片数据转字节流、字节流转base64编码,与反转

import io
from PIL import Image
import base64
byte_stream = io.BytesIO()

Image.open()

# 1)从路径打开图片,并转换为base64编码后的字符
with open('my_path.png', 'rb')as f:
	img_base64_str = str(base64.b64encode(f.read()),"utf-8") # 加一层str和utf-8方便post请求传输json
	
# 2) Image对象打开图片,并转换为字节流
	# 创建一个字节流管道
	img_bytes = io.BytesIO()
	# 将图片数据存入字节流管道, format可以按照具体文件的格式填写
	image.save(img_bytes, format="JPEG") # image是一张可以直接显示的图片
	# 从字节流管道中获取二进制
	image_bytes = img_bytes.getvalue()
	
# 3)字节流写入图片路径
with open('my_path.png', 'wb')as f:
	f.write(image_bytes )
	
# 4)将base64编码后的字符转图片
res_image = Image.open(io.BytesIO(base64.b64decode(img_base64_str))) #可直接显示出来


python客户端的http请求

以python-requests模块为例

请求类型

requests请求功能
requests.get( )从服务器获取数据
requests.post( )向服务器提交数据
requests.put( )从客户端向服务器传送的数据取代指定的文档的内容
requests.delete( )请求服务器删除指定页面
requests.head( )请求页面头部信息
requests.options( )获取服务器支持的HTTP请求方法
requests.patch( )向HTML提交局部修改请求,对应于HTTP的PATCH
requests.connect( )把请求连接转换到透明的TCP/IP通道
requests.trace( )回环测试请求,查看请求是否被修改
requests.session( ).get( )构造会话对象

get和post是最常用的,一般从字面上理解的话get是获取数据、而post是发送数据,但是实际情况可能会稍微复杂一些:可以用get来发送请求也可以用post来获取数据。在开发中对于获取一般常用get请求,而对于数据的增添、删除、修改,一般都使用post请求进行操作。还有一点,它们两者之间的参数传递也是不同的。get请求是将参数拼接到 url上进行参数传递的,而 post 是将参数写入到请求正文中传递的。

# get请求一般用于数据的查询,请求参数拼接到url路径中,如浏览器中地址栏的url一般都是get请求
# 下面例子get的接口名称为`search`, 接受一个参数`q`
www.douban.com/search?q=电影

get请求会被浏览器主动缓存,如果下次传输的数据相同,那么浏览器就会返回缓存中的内容,以求更快的展示所需要的数据。

相对应的,post请求的数据不会出现在浏览器的地址栏中,因此post 请求不会被缓存,也就不会保留在浏览器历史记录中。而post请求的数据是通过request对象中的data属性来传参,用来存放请求体数据,这里的data是一个字典,里面要有匹配键值对。

请求参数

get的请求参数

常用方式:
	response=response.get(url,params,**kwargs)
参数说明:
    ·url:拟获取页面的url链接
    ·params:用get方式传进去的参数
    ·***kwargs:控制参数(非必填)
例子:

    1. 参数写在url里面
    import requests
    response = request.get("http://httpbin.org/get?name=gemey&age=22")
    print(response.text)

    2. 参数不在url里,独立写在params中
     d={
         'name':'tom',
         'age':'20'
     }
     response = requests.get('http://httpbin.org/get', params=d)
     print(response.text)

post的请求参数

常用方式:
response=response.post(url,data, json, **kwargs)
参数说明:
   ·url:以post方式请求的地址
   ·data: 填加到请求体中的数据
   ·json:Json格式的数据
   ·**kwargs:控制参数
例子:
    requests.post('https://api.github.com/some/endpoint', data=json.dumps({'some': 'data'}))

data参数和params参数的区别: params是添加到url的请求字符串中的,用于get请求。 data是添加到请求体中的, 用于post请求。

data参数和json参数的区别:主要在于查看请求体时候显示的内容不同。用data参数提交数据时,request.body的内容则为a=1&b=2的这种形式,用json参数提交数据时,request.body的内容则为’{“a”: 1, “b”: 2}'的这种形式。

请求响应

response属性功能
response.text获取文本内容
response.content获取二进制数据
response.status_code获取状态码
response.headers获取响应头
response.cookies获取cookies信息
response.cookies.get_dict以字典形式获取cookies信息
response.cookies.items以列表形式获取cookies信息
response.url获取请求的URL
response.historty获取跳转前的URL
response.json获取json数据

常用的就前3个,text返回文本string,content返回文本bytes,status_code返回状态码,状态码分类和含义如下:

状态码分类含义
1**信息服务器收到请求,需要请求者继续执行操作
2**成功请求被成功接收并处理
3**重定向需要进一步的操作以完成请求
4**客户端错误请求包含语法错误或无法完成请求
5**服务器错误服务器在处理请求的过程中发送错误

一般http请求没出错的话则返回200,其余都是过程中存在错误导致请求失败。

命令行的http请求

get请求参数:

  • 在url中传递参数:可以在url后面使用?连接参数名和参数值,多个参数之间使用&分隔。
  • 使用 -d 或 --data 参数:可以使用 -d 参数后面跟随的字符串来传递url编码的参数。
curl http://127.0.0.1:8080/login?admin=admin&passwd=12345678
curl https://www.douban.com/search?q='战争'
curl https://www.douban.com/search -d '{"q":"战争"}'

post请求参数:

  • 使用 -d 或 --data 参数:可以使用 -d 参数后面跟随的字符串来传递url编码的参数。
  • 使用 -F 参数:可以使用 -F 参数后面跟随的字符串来传递表单参数。
curl -H "Content-Type:application/json" -X POST -d '{"user": "admin", "passwd":"12345678"}' http://127.0.0.1:8000/login

curl常用参数说明

  • -H 请求头
  • -X 请求方法
  • -d 请求参数
  • -o 输出文件

请求头部信息是在HTTP请求中包含的元数据,用于提供有关请求的额外信息。这些头部信息提供了关于请求的详细说明,帮助服务器了解请求的性质、期望和所需的处理方式。

以下是一些常见的请求头部信息及其作用:
Content-Type:指定请求体的媒体类型。例如,Content-Type: application/json 表示请求体是 JSON 格式的数据。
Accept:指定客户端可以接受的响应内容类型。服务器可以根据此头部信息来确定要发送给客户端的响应类型。
Authorization:用于在请求中提供身份验证凭据,通常用于访问需要身份验证的资源。常见的方式包括使用 Basic 认证或 Bearer Token。
User-Agent:标识发起请求的客户端应用程序或浏览器的名称和版本号。服务器可以根据此头部信息来处理不同类型的客户端请求。
Referer:指示当前请求是从哪个 URL 发起的。服务器可以根据此头部信息来跟踪请求的来源。
Cookie:用于在请求中发送保存在客户端的 Cookie 数据。服务器可以根据此头部信息来获取客户端的会话信息。

通过设置适当的请求头部信息,你可以控制请求的行为和服务器的处理方式。这些头部信息在与服务器通信时起到了重要的作用,帮助服务器理解和正确处理请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值