Question
I am trying to pass a value called 'ethAddress' from an input form on the client to FastAPI so that I can use it in a function to generate a matplotlib chart.
I am using fetch to POST the inputted text in Charts.tsx file:
fetch("http://localhost:8000/ethAddress", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(ethAddress),
}).then(fetchEthAddresses);
Then I have my api.py file set up as follows:
#imports
app = FastAPI()
@app.get("/ethAddress")
async def get_images(background_tasks: BackgroundTasks, ethAddress: str):
image = EthBalanceTracker.get_transactions(ethAddress)
img_buf = image
background_tasks.add_task(img_buf.close)
headers = {'Content-Disposition': 'inline; filename="out.png"'}
return Response(img_buf.getvalue(), headers=headers, media_type='image/png')
@app.post("/ethAddress")
async def add_ethAddress(ethAddress: str):
return ethAddress
To my understanding, I am passing the 'ethAddress' in the Request Body from
the client to the backend using fetch
POST
request, where I then have
access to the value that has been posted using @app.post
in FastAPI. I then
return that value as a string. Then I am using it in the GET
route to
generate the chart.
I'm getting this error:
INFO: 127.0.0.1:59821 - "POST /ethAddress HTTP/1.1" 422 Unprocessable Entity
INFO: 127.0.0.1:59821 - "GET /ethAddress HTTP/1.1" 422 Unprocessable Entity
I have also tried switching the fetch method on the client to GET instead of POST. But get the following error:
TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.
Answer
The way you defined ethAddress
in your endpoint is expected as a query
parameter; hence, the 422 Unprocessable Entity
error. As per the
[documentation](https://fastapi.tiangolo.com/tutorial/query-params/#query-
parameters):
When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters.
For the parameter to be interpreted as JSON, you need to either:
Option 1
from pydantic import BaseModel
class Item(BaseModel):
eth_addr: str
@app.post('/ethAddress')
def add_eth_addr(item: Item):
return item
FastAPI will expect a body like:
{
"eth_addr": "some addr"
}
Using Fetch API:
//...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"eth_addr": "some addr"}),
//...
Option 2
or, use the Body
type:
from fastapi import Body
@app.post('/ethAddress')
def add_eth_addr(eth_addr: str = Body()):
return {'eth_addr': eth_addr}
FastAPI will expect a body like:
"some addr"
Using Fetch API:
//...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify("some addr"),
//...
Option 3
Since you have a [single body
parameter](https://fastapi.tiangolo.com/tutorial/body-multiple-params/#embed-
a-single-body-parameter), you might want to use the special Body
parameter
embed
:
from fastapi import Body
@app.post('/ethAddress')
def add_eth_addr(eth_addr: str = Body(embed=True)):
return {'eth_addr': eth_addr}
FastAPI will expect a body like:
{
"eth_addr": "some addr"
}
Using Fetch API:
//...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"eth_addr": "some addr"}),
//...
Related answers, including JavaScript examples on how to post JSON data as well, can be found here, here, as well as here and here.