¿Cómo publicar datos JSON desde la interfaz de JavaScript al backend de FastAPI?
Estoy intentando pasar un valor llamado 'ethAddress' desde un formulario de entrada en el cliente a FastAPI para poder usarlo en una función para generar un gráfico matplotlib.
Estoy usando fetch para PUBLICAR el texto ingresado en el archivo Charts.tsx:
fetch("http://localhost:8000/ethAddress", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(ethAddress),
}).then(fetchEthAddresses);
Luego tengo mi archivo api.py configurado de la siguiente manera:
#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
Según tengo entendido, estoy pasando la 'ethAddress' en el cuerpo de la solicitud del cliente al backend mediante la fetch
POST
solicitud, donde luego tengo acceso al valor que se ha publicado @app.post
en FastAPI. Luego devuelvo ese valor como una cadena. Luego lo estoy usando en la GET
ruta para generar el gráfico.
Recibo este 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
También intenté cambiar el método de recuperación en el cliente a OBTENER en lugar de POST. Pero aparece el siguiente error:
TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.
Se espera que la forma que definió ethAddress
en su punto final sea un parámetro de consulta; de ahí el 422 Unprocessable Entity
error. Según la documentación :
Cuando declara otros parámetros de función que no forman parte de los parámetros de ruta, se interpretan automáticamente como parámetros de "consulta".
Para que el parámetro se interprete como JSON, debe hacer lo siguiente:
Opción 1
Crea un modelo Pydantic :
from pydantic import BaseModel
class Item(BaseModel):
eth_addr: str
@app.post('/ethAddress')
def add_eth_addr(item: Item):
return item
FastAPI esperará un cuerpo como:
{
"eth_addr": "some addr"
}
Usando la API de recuperación:
//...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"eth_addr": "some addr"}),
//...
opcion 2
o utilice el Body
tipo:
from fastapi import Body
@app.post('/ethAddress')
def add_eth_addr(eth_addr: str = Body()):
return {'eth_addr': eth_addr}
FastAPI esperará un cuerpo como:
"some addr"
Usando la API de recuperación:
//...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify("some addr"),
//...
Opción 3
Dado que tiene un único parámetro de cuerpo , es posible que desee utilizar el Body
parámetro especial embed
:
from fastapi import Body
@app.post('/ethAddress')
def add_eth_addr(eth_addr: str = Body(embed=True)):
return {'eth_addr': eth_addr}
FastAPI esperará un cuerpo como:
{
"eth_addr": "some addr"
}
Usando la API de recuperación:
//...
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"eth_addr": "some addr"}),
//...
Las respuestas relacionadas, incluidos ejemplos de JavaScript sobre cómo publicar datos JSON, se pueden encontrar aquí , aquí , así como aquí y aquí .