¿Cómo publicar datos JSON desde la interfaz de JavaScript al backend de FastAPI?

Resuelto spal asked hace 2 años • 1 respuestas

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 POSTsolicitud, donde luego tengo acceso al valor que se ha publicado @app.posten FastAPI. Luego devuelvo ese valor como una cadena. Luego lo estoy usando en la GETruta 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.
spal avatar Sep 18 '22 09:09 spal
Aceptado

Se espera que la forma que definió ethAddressen su punto final sea un parámetro de consulta; de ahí el 422 Unprocessable Entityerror. 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 Bodytipo:

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 Bodypará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í .

Chris avatar Sep 18 '2022 09:09 Chris