10

I am usually using Tornado, and trying to migrate to FastAPI.

Let's say, I have a very basic API as follows:

@app.post("/add_data")
async def add_data(data):
    return data

When I am running the following Curl request: curl http://127.0.0.1:8000/add_data -d 'data=Hello'

I am getting the following error:

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

So I am sure I am missing something very basic, but I do not know what that might be.

Chris
  • 18,724
  • 6
  • 46
  • 80
Djoby
  • 602
  • 1
  • 6
  • 22
  • Future readers might find [this answer](https://stackoverflow.com/a/70636163/17865804) and [this answer](https://stackoverflow.com/a/70640522/17865804) helpful as well. – Chris Apr 27 '23 at 05:21

3 Answers3

8

Since you are sending a string data, you have to specify that in the router function with typing as

from pydantic import BaseModel


class Payload(BaseModel):
    data: str = ""


@app.post("/add_data")
async def add_data(payload: Payload = None):
    return payload

Example cURL request will be in the form,

curl -X POST "http://0.0.0.0:6022/add_data"  -d '{"data":"Hello"}'
JPG
  • 82,442
  • 19
  • 127
  • 206
  • Thank you it works! I am however a bit confused why I need to define a BaseModel for post API but not get. – Djoby Sep 25 '20 at 14:34
  • 1
    In your get request, the data are being sent as ***query parameters*** whereas here as ***payload*** – JPG Sep 25 '20 at 15:18
  • And you don't have to hard-code input parameters (such as `data` field in `Payload`), see how to pass and receive any dict or JSON, without having to predefine its keys: https://stackoverflow.com/a/70879659/9962007 – mirekphd Dec 12 '22 at 12:08
1

In your case, you passing a form data to your endpoint. To process it, you need to install python-multipart via pip and rewrite your function a little:

from fastapi import FastAPI, Form

app = FastAPI()

@app.post('/add_data')
async def process_message(data: str = Form(...)):
    return data

If you need json data, check Arakkal Abu's answer.

0

FastAPI docs advise this solution for strings in body:

  • just add Body(), like data: str = Body().

Complete example:

from fastapi import Body

@app.post("/add_data")
async def add_data(data: str = Body()):
    return data

That tells FastAPI that the value is expected in body, not in the URL.

elano7
  • 1,584
  • 1
  • 18
  • 18