Bugs in likeadmin and fastapi

The following content was written on August 11, 2023

bug 1

Request body - multiple parameters - for "Single value in request body" in FastAPI (tiangolo.com), select python3.6, and the interface sample code is

from typing import Union

from fastapi import Body, FastAPI
from pydantic import BaseModel
from typing_extensions import Annotated

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None


class User(BaseModel):
    username: str
    full_name: Union[str, None] = None


@app.put("/items/{item_id}")
async def update_item(
    item_id: int, item: Item, user: User, importance: Annotated[int, Body()]
):
    results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
    return results

According to the sample code of the request body given, the request code I wrote is

import requests

url = 'http://127.0.0.1:8000/items/7'
form_data = {
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    },
    "user": {
        "username": "dave",
        "full_name": "Dave Grohl"
    },
    "importance": 5
}
response = requests.put(url=url, json=form_data)
print(response.status_code)
print(response.text)

If you create a new python3.8 environment (installed to 3.8.17, called the likeadmin environment), then install the library according to likeadmin 's requirements.txt, run the server interface code, and then run the request code, you cannot get the correct result, prompt

{"detail":[{"loc":["query","importance"],"msg":"field required","type":"value_error.missing"}]}

If you create a new python3.8 environment (installed to 3.8.17, it is called a pure fastapi environment), then pip install fastapi[all], run the server interface code, and then run the request code, you can get the correct results.

{"item_id":7,"item":{"name":"Foo","description":"The pretender","price":42.0,"tax":3.2},"user":{"username":"dave","full_name":"Dave Grohl"},"importance":5}

The basis for judging whether the result is correct is a sentence in the documentation "In this case, FastAPI  will expect a request body like this".

If you want to get the correct results in the likeadmin environment, check 127.0.0.1:8000/docs to learn that importance should be spliced ​​into the request URL with a question mark, because the automatically generated document shows that it is a query, that is, a query parameter.

Documents automatically generated by the likeadmin environment
Documents automatically generated by pure fastapi environment

 To sum up, if you run the fastapi sample code in the likeadmin environment, you cannot get the expected results mentioned in the fastapi document; and create a new virtual environment of the same python version, with only pip install fastapi[all], you can get the expected results mentioned in the fastapi document. the result of.

As of August 11, 2023, the content of likeadmin’s requirements.txt is

aiofiles==22.1.0
aiomysql==0.1.1
alibabacloud_dysmsapi20170525==2.0.23
alibabacloud_tea_openapi
anyio==3.6.1
async-timeout==4.0.2
click==8.1.3
colorama==0.4.5
commonmark==0.9.1
cos-python-sdk-v5==1.9.22
databases==0.6.1
Deprecated==1.2.13
fastapi==0.85.0
fastapi-cache2==0.1.9
fastapi-pagination==0.10.0
greenlet==1.1.3.post0
h11==0.14.0
httptools==0.5.0
idna==3.4
Jinja2==3.1.2
MarkupSafe==2.1.1
optionaldict==0.1.2
oss2==2.16.0
pendulum==2.1.2
psutil==5.9.3
pydantic==1.10.2
Pygments==2.13.0
PyMySQL==1.0.2
python-dateutil==2.8.2
python-dotenv==0.21.0
python-multipart==0.0.5
pytz==2022.5
pytzdata==2020.1
PyYAML==6.0
qiniu==7.9.0
redis==4.4.0rc2
rich==12.6.0
shellingham==1.5.0
six==1.16.0
sniffio==1.3.0
SQLAlchemy==1.4.41
starlette==0.20.4
tencentcloud-sdk-python==3.0.841
typer==0.6.1
typing-extensions==4.4.0
ua-parser==0.16.1
user-agents==2.2.0
# uvloop==0.17.0
uvicorn==0.18.3
watchfiles==0.17.0
websockets==10.3
wrapt==1.14.1
wechatpy==1.8.18

bug 2

Similar to bug 1, the example code of fastapi is run in the likeadmin environment, but the expected results mentioned in the fastapi document cannot be obtained; and if a new virtual environment of the same python version is created, and only pip install fastapi[all] is used, the expected results mentioned in the fastapi document can be obtained. the expected result.

Request body - multiple parameters - in FastAPI (tiangolo.com), for "Embedding a single request body parameter", select python3.6, and the interface sample code is

from typing import Union

from fastapi import Body, FastAPI
from pydantic import BaseModel
from typing_extensions import Annotated

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
    results = {"item_id": item_id, "item": item}
    return results

The documentation says "In this case, FastAPI  will expect a request body like this:"

{
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    }
}

instead of:

{
    "name": "Foo",
    "description": "The pretender",
    "price": 42.0,
    "tax": 3.2
}

According to the sample code of the request body given, the request code I wrote is

import requests

url = 'http://127.0.0.1:8000/items/7'
form_data_1 = {
    "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    }
}
form_data_2 = {
    # "item": {
        "name": "Foo",
        "description": "The pretender",
        "price": 42.0,
        "tax": 3.2
    # }
}
response_1 = requests.put(url=url, json=form_data_1)
response_2 = requests.put(url=url, json=form_data_2)
print(response_1.status_code)
print(response_1.text)
print(response_2.status_code)
print(response_2.text)
# 上面的打印结果:
# fastapi环境
# 200
# {"item_id":7,"item":{"name":"Foo","description":"The pretender","price":42.0,"tax":3.2}}
# 422
# {"detail":[{"type":"missing","loc":["body","item"],"msg":"Field required","input":null,"url":"https://errors.pydantic.dev/2.1/v/missing"}]}
# likeadmin环境
# 422
# {"detail":[{"loc":["body","name"],"msg":"field required","type":"value_error.missing"},{"loc":["body","price"],"msg":"field required","type":"value_error.missing"}]}
# 200
# {"item_id":7,"item":{"name":"Foo","description":"The pretender","price":42.0,"tax":3.2}}

bug 3

Header parameters - "Declaration  Header Parameters" in FastAPI (tiangolo.com) (and Cookie parameters -Cookie "Declaration  Parameters" in  FastAPI (tiangolo.com)), select python3.6, the interface sample code is

from typing import Union

from fastapi import FastAPI, Header
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/")
async def read_items(user_agent: Annotated[Union[str, None], Header()] = None):
    return {"User-Agent": user_agent}
from typing import Union

from fastapi import Cookie, FastAPI
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/")
async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None):
    return {"ads_id": ads_id}

 The interface code I actually wrote is

from typing import Union

from fastapi import FastAPI, Header, Cookie
from typing_extensions import Annotated

app = FastAPI()

@app.get("/items/")
async def read_items(
    BIDUPSID: Annotated[Union[str, None], Cookie()] = None,  # 从请求头的cookie中获取键为BIDUPSID的值
    PSTM: Annotated[Union[str, None], Cookie()] = None,
    BA_HECTOR: Annotated[Union[str, None], Cookie()] = None,
    user_agent: Annotated[Union[str, None], Header()] = None  # fastapi自动将user_agent转为user-agent,又因HTTP headers是大小写不敏感的,所以user_agent就是User-Agent。from https://fastapi.tiangolo.com/zh/tutorial/header-params/#_1中"自动转换处"
    ):
    return {"Cookie": f'BIDUPSID={BIDUPSID}; PSTM={PSTM}; BA_HECTOR={BA_HECTOR}', "User-Agent": user_agent}

'''
# from https://fastapi.tiangolo.com/zh/tutorial/header-params/#_1中"自动转换处"
自动转换
Header 在 Path, Query 和 Cookie 提供的功能之上有一点额外的功能。

大多数标准的headers用 "连字符" 分隔,也称为 "减号" (-)。

但是像 user-agent 这样的变量在Python中是无效的。

因此, 默认情况下, Header 将把参数名称的字符从下划线 (_) 转换为连字符 (-) 来提取并记录 headers.

同时,HTTP headers 是大小写不敏感的,因此,因此可以使用标准Python样式(也称为 "snake_case")声明它们。

因此,您可以像通常在Python代码中那样使用 user_agent ,而不需要将首字母大写为 User_Agent 或类似的东西。

如果出于某些原因,你需要禁用下划线到连字符的自动转换,设置Header的参数 convert_underscores 为 False
'''

The request code I wrote is

import requests

url = 'http://127.0.0.1:8000/items/'
headers = {
    'Cookie': 'BIDUPSID=A9DA10BEC1294DD8D4F6E654A52CBDC8; PSTM=1691732828; BAIDUID=A9DA10BEC1294DD8402C67E5E8156634:FG=1; BD_UPN=12314753; BA_HECTOR=8h8k05052l000la0a1810h0j1idbjgf1p; BAIDUID_BFESS=A9DA10BEC1294DD8402C67E5E8156634:FG=1; BD_CK_SAM=1; PSINO=2; ZFY=FJzChFI0tlXn0pdMbu9GDJzHS1iNKW8:A:AjdKkCxk2W0:C; delPer=0; BD_HOME=1; COOKIE_SESSION=21_0_0_0_3_0_0_0_0_0_0_0_23_0_4_0_1691734574_0_1691734570%7C2%230_0_1691734570%7C1; H_PS_PSSID=36546_39112_38831_39008_39114_39038_38917_26350_39138_39132_39137_22157_39100; H_PS_645EC=d157JRTS54%2FnnbXzJd5jNKP%2FMviUleulBfUEwB4MIKKEUrwiHAKJcjpnt4A',
    'Referer': 'https://www.baidu.com/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203'
}
# cookie = {
#     'BIDUPSID': 'A9DA10BEC1294DD8D4F6E654A52CBDC8',
#     'PSTM': '1691732828',
#     'BA_HECTOR': '8h8k05052l000la0a1810h0j1idbjgf1p'
# }

response = requests.get(url=url, headers=headers)
# response = requests.get(url=url, headers=headers, cookies=cookie)  # 注释掉headers中Cookie,取消cookie的注释,再用这个请求,和上一行的结果一样
print(response.status_code)
print(response.text)

 The likeadmin environment cannot obtain Cookie and User-Agent; in the pure fastapi environment, both Cookie and User-Agent can be obtained. 

# likeadmin的环境的结果
{"Cookie":"BIDUPSID=None; PSTM=None; BA_HECTOR=None","User-Agent":null}

# 纯fastapi环境的结果
{"Cookie":"BIDUPSID=A9DA10BEC1294DD8D4F6E654A52CBDC8; PSTM=1691732828; BA_HECTOR=8h8k05052l000la0a1810h0j1idbjgf1p","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203"}

bug 4

Path operation configuration - at "status_code status code" in FastAPI (tiangolo.com), the interface sample code is

from typing import Set, Union

from fastapi import FastAPI, status
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None
    tags: Set[str] = set()


@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)  # 也可以直接用status_code=201
async def create_item(item: Item):
    return item

The request code I wrote is

import requests

url = 'http://127.0.0.1:8000/items/'
form_data = {
    'name': 'Bob',
    'price': 12.3,
}
response = requests.post(url=url, json=form_data)
print(response.status_code)
print(response.text)

 The status code printed in the likeadmin environment is still 200, and has not changed to the set 201; in the pure fastapi environment, it is 201.

Bug 1 and bug 2 and bug 3 and bug 4 solutions

Since the python versions of the two virtual environments are the same, I suddenly thought that it was caused by the different fastapi versions. Check the pure fastapi environment (August 11, 2023) to get

Package              Version
-------------------- -----------
annotated-types      0.5.0
anyio                3.7.1
certifi              2023.7.22
click                8.1.6
colorama             0.4.6
dnspython            2.4.2
email-validator      2.0.0.post2
exceptiongroup       1.1.2
fastapi              0.101.0
h11                  0.14.0
httpcore             0.17.3
httptools            0.6.0
httpx                0.24.1
idna                 3.4
itsdangerous         2.1.2
Jinja2               3.1.2
MarkupSafe           2.1.3
orjson               3.9.4
pip                  23.2.1
pydantic             2.1.1
pydantic_core        2.4.0
pydantic-extra-types 2.0.0
pydantic-settings    2.0.2
python-dotenv        1.0.0
python-multipart     0.0.6
PyYAML               6.0.1
setuptools           68.0.0
sniffio              1.3.0
starlette            0.27.0
typing_extensions    4.7.1
ujson                5.8.0
uvicorn              0.23.2
watchfiles           0.19.0
websockets           11.0.3
wheel                0.38.4

Upgrade likeadmin's fastapi library from 0.85.0 to 0.101.0, which is the same as the pure fastapi environment, and then run the above sample code to get the correct results.

Guess you like

Origin blog.csdn.net/fj_changing/article/details/132224527