When a FastAPI endpoint expects a Pydantic model and one is passed with a string it works as expected unless that string contains unicode characters.
First I create an example application for FastAPI with an example model.
serv.py
from pydantic import BaseModel
class exClass(BaseModel):
id: int = Field(example=1)
text: str = Field(example="Text example")
app = FastAPI(debug=True)
@app.post("/example")
async def receive_pyd(ex: exClass):
print(ex)
return True
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
The client that shows the error in question client.py
from pydantic import BaseModel, Field
import requests
class exClass(BaseModel):
id: int = Field(example=1)
text: str = Field(example="Text example")
ex1 = exClass(id=1, text="working example")
ex2 = exClass(id=2, text="this’ will fail")
ex3 = exClass(id=3, text="🤗 <- also non-working")
r = requests.post(f"http://127.0.0.1:8000/example", data=ex1.model_dump_json())
print(r.text)
r = requests.post(f"http://127.0.0.1:8000/example", data=ex2.model_dump_json())
print(r.text)
r = requests.post(f"http://127.0.0.1:8000/example", data=ex3.model_dump_json())
print(r.text)
Output:
true
Invalid HTTP request received.
Invalid HTTP request received.
When text
contains unicode characters the result is a 422 Unprocessable Entity. I have tried ex.dict(), model_dump(), and using json instead of data in the requests call. Enabling debugging in FastAPI/starlette bubbles up that the Invalid HTTP request is a JSON decode error.
This is not a problem of Pydantic and FastAPI. You should encode you request data like it's shown below:
r = requests.post(
f"http://127.0.0.1:8000/example", data=ex1.model_dump_json().encode('utf-8')
)
print(r.text)
r = requests.post(
f"http://127.0.0.1:8000/example", data=ex2.model_dump_json().encode('utf-8')
)
print(r.text)
r = requests.post(
f"http://127.0.0.1:8000/example", data=ex3.model_dump_json().encode('utf-8')
)
print(r.text)