FastAPI:为什么 JSON POST 请求中需要 Content-Type 标头?

问题描述 投票:0回答:1

我有以下 FastAPI 应用程序:

from pydantic import BaseModel as Schema
from fastapi import FastAPI

api = FastAPI()

class User(Schema):
    firstname: str
    lastname: str
    age: int | None = None


@api.post('/user')
def user_selection(user: User):
    return {'data': f'{user.firstname} {user.lastname} age: {user.age}'}

主文件名为

file.py
,所以我像这样运行uvicorn服务器:

uvicorn file:api --reload

通过另一个控制台,我发送此请求:

curl -X 'POST' -i 'http://127.0.0.1:8000/user' -d '{firstname":"mike", "lastname":"azer"}'

但是,我收到此错误:

HTTP/1.1 422 Unprocessable Entity
date: Sun, 05 Feb 2023 16:01:14 GMT
server: uvicorn
content-length: 88
content-type: application/json

{"detail":[{"loc":["body"],"msg":"value is not a valid dict","type":"type_error.dict"}]}

这是为什么?

但是,如果我在请求中将

Content-Type
标头设置为
application/json

curl -X 'POST'   'http://127.0.0.1:8000/user'   -H 'Content-Type: application/json'   -d '{
  "firstname": "aaa",
  "lastname": "zzz"
}'

它有效很好。

为什么需要标题?当我执行

GET
请求时,我不必添加标头并且它可以工作。与
POST
请求有何不同?

python json curl fastapi content-type
1个回答
1
投票

问:“为什么 JSON POST 请求中需要 Content-Type 标头?”

A:根据

curl
的文档

使用curl的

-d
选项进行POST将使其包含默认标头 看起来像
Content-Type: application/x-www-form-urlencoded
。 这就是您的典型浏览器用于普通 POST 的方式。

许多 POST 数据的接收者并不关心或检查 内容类型标头。

如果该标题对您来说不够好,您当然应该, 替换它并提供正确的一个。例如,如果您发布 JSON 到服务器并希望更准确地告诉服务器 内容是什么:

curl -d '{json}' -H 'Content-Type: application/json' https://example.com

因此,在发送包含 JSON 数据的

'Content-Type: application/json'
请求时需要
POST
标头的原因很简单,因为
curl
默认情况下使用
application/x-www-form-urlencoded
Content-Type 对构成请求正文的数据进行编码—这是浏览器在提交 HTML 时通常使用的方式
<form>

但是,如果

files
也包含在请求中,则
multipart/form-data
内容类型将由 curl 使用
自动
— 这同样适用于使用 Python 请求,如 this 答案 所示(对于 HTML表单,您需要手动指定
enctype
,如此处所示)—根据
curl
的文档

发布二进制文件

从文件中读取要发布的数据时,

-d
将删除回车符和换行符。如果您有以下情况,请使用
--data-binary
想要curl完全按照给定的方式读取和使用给定的二进制文件:

curl --data-binary @filename http://example.com/ 

我还建议您查看相关答案hereherehere,以及使用/docs处的

interactive Swagger UI autodocs
来测试API,它也会自动生成用于测试 API 端点的
curl
命令。

问:“当我发出

GET
请求时,我不需要添加标头,它就可以工作。与
POST
请求有什么区别?”

A:发出

GET
请求时,不包含请求体,因此不需要编码请求体内容,也不需要告诉服务器正在发送什么类型的数据。在
GET
请求中,所有参数必须出现在 URL(即查询字符串)或标头中。虽然 HTTP 标准没有定义 URL 或标头的长度限制,但通常存在长度限制,具体取决于服务器和客户端(通常在 2KB 到 8KB 之间)。然而,在
POST
请求中,限制要高得多,并且比客户端更依赖于服务器。

© www.soinside.com 2019 - 2024. All rights reserved.