1

I'm trying to POST some data to an API method using the browser. When I use fastAPI's Request object all is working. But when I use a pedantic model I get:

422 (Unprocessable Entity)

I have tested my code with curl and again all is working.

Here is my fastAPI:


from typing import Optional

from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware

from pydantic import BaseModel

import uvicorn

app = FastAPI()

origins = ["*"]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = 'N/A'

@app.post("/test_request")
async def create_item(request:Request):
  json = request.json()
  return await json

@app.post("/test_pydantic")
async def create_item(item:Item):
  return item

if __name__ == '__main__':
    uvicorn.run(app='main:app', reload=True, debug=True)

And here is my index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>test</h1>
    <script>
        const person = {
            name: 'XXX',
            description: 'XXX Desc',
            price:200,
            tax: 400123598
        }

        fetch('http://127.0.0.1:8000/test_request', {
            method: 'POST',
            body: JSON.stringify(person),
            contentType: "application/json",
            dataType: 'json',
        }).then(function(respones) {
            return respones.json();
        }).then(function(data) {
            console.log('Using request', data);
        })

        fetch('http://127.0.0.1:8000/test_pydantic', {
            method: 'POST',
            body: JSON.stringify(person),
            contentType: "application/json",
            dataType: 'json',
        }).then(function(respones) {
            return respones.json();
        }).then(function(data) {
            console.log('Using pydantic', data);
        })
</script>

</body>

</html>

When calling test_pydantic from the browser I get the 422.

Chris
  • 18,724
  • 6
  • 46
  • 80
chhenning
  • 2,017
  • 3
  • 26
  • 44
  • The 422 error will have a body with the actual error message - i.e. which field that fails validation. – MatsLindh Oct 18 '21 at 16:48
  • OK. The error is `value is not a valid dict` – chhenning Oct 18 '21 at 16:58
  • Does this answer your question? [How to post JSON data from JavaScript frontend to FastAPI backend?](https://stackoverflow.com/questions/73759718/how-to-post-json-data-from-javascript-frontend-to-fastapi-backend) – Chris Feb 22 '23 at 09:54
  • Related answers can also be found [here](https://stackoverflow.com/a/71741617/17865804), as well as [here](https://stackoverflow.com/a/70636163/17865804) and [here](https://stackoverflow.com/a/74106637/17865804). – Chris Feb 22 '23 at 09:58
  • Additionally, I wouldn't recommend using the `'*'` wildcard in the `allow_origins` argument (as demonstrated in your question). Please have a look at [this answer](https://stackoverflow.com/a/75048778/17865804) and [this answer](https://stackoverflow.com/a/73963905/17865804) for more details. – Chris Feb 22 '23 at 10:03

1 Answers1

1

You're not setting the correct content-type when calling fetch with the JSON data. The content-type header is under the headers key:

fetch('http://127.0.0.1:8000/test_pydantic', {
    method: 'POST',
    body: JSON.stringify(person),
    headers: {"content-type": "application/json"},
    dataType: 'json',
}).then(function(respones) {
    return respones.json();
}).then(function(data) {
    console.log('Using pydantic', data);
})
MatsLindh
  • 49,529
  • 4
  • 53
  • 84