Maison >développement back-end >Tutoriel Python >Comment créer un point de terminaison FastAPI qui accepte soit le formulaire, soit le corps JSON ?

Comment créer un point de terminaison FastAPI qui accepte soit le formulaire, soit le corps JSON ?

DDD
DDDoriginal
2024-10-27 06:16:03485parcourir

How to Create a FastAPI Endpoint That Accepts Either Form or JSON Body?

Comment créer un point de terminaison FastAPI pouvant accepter un corps de formulaire ou un corps JSON ?

Dans FastAPI, vous pouvez définir des points de terminaison qui gèrent différents types de corps de requête, tels que JSON ou données de formulaire. Cela vous permet de créer des points de terminaison pouvant accepter l'un ou l'autre format sans avoir besoin de points de terminaison séparés.

Pour y parvenir, vous pouvez suivre l'une des approches ci-dessous :

Option 1 : Utiliser une fonction de dépendance

Vous pouvez utiliser une fonction de dépendance pour vérifier l'en-tête Content-Type de la requête, puis analyser le corps de manière appropriée à l'aide des méthodes de Starlette. Notez que s'appuyer uniquement sur l'en-tête Content-Type ne garantit pas toujours la validité du corps de la requête, il est donc recommandé d'inclure la gestion des erreurs.

<code class="python">import os, sys
from fastapi import FastAPI, Depends, HTTPException
from starlette.requests import Request
app = FastAPI()

# Generating file
open("./app.txt", "w").write("hello from a file")

async def body_parser(request: Request):
    ct = request.headers.get("Content-Type", "")
    if ct == "application/json":
        try:
            d = await request.json()
            if not isinstance(d, dict):
                raise HTTPException(status_code=400, details={"error":"request body must be a dict"})
            return d
        except JSONDecodeError:
            raise HTTPException(400, "Could not parse request body as JSON")
    elif ct == "multipart/form-data":
        await request.stream()  # this is required for body parsing.
        d = await request.form()
        if not d:
            raise HTTPException(status_code=400, details={"error":"no form parameters found"})
        return d
    else:
        raise HTTPException(405, "Content-Type must be either JSON or multipart/form-data")

@app.post("/", dependencies=[Depends(body_parser)])
async def body_handler(d: dict):
    if "file" in d:
        return {"file": d["file"]}
    return d</code>

Option 2 : Utilisation des paramètres de formulaire/fichier facultatifs

Dans cette approche, vous pouvez définir les paramètres de formulaire/fichier comme facultatifs dans votre point de terminaison. Si l'un de ces paramètres a des valeurs, cela suppose une demande de données de formulaire. Sinon, il valide le corps de la requête comme JSON.

<code class="python">from fastapi import FastAPI, Form, File, UploadFile
app = FastAPI()

@app.post("/")
async def file_or_json(
    files: List[UploadFile] = File(None),
    some_data: str = Form(None)
):
    if files:
        return {"files": len(files)}
    return {"data": some_data}</code>

Option 3 : Définir des points de terminaison distincts pour chaque type

Vous pouvez également créer des points de terminaison distincts, un pour JSON et un autre pour les données de formulaire . À l'aide d'un middleware, vous pouvez vérifier l'en-tête Content-Type et rediriger la requête vers le point de terminaison approprié.

<code class="python">from fastapi import FastAPI, Request, Form, File, UploadFile
from fastapi.responses import JSONResponse
app = FastAPI()

@app.middleware("http")
async def middleware(request: Request, call_next):
    ct = request.headers.get("Content-Type", "")
    if ct == "application/json":
        request.scope["path"] = "/json"
    elif ct in ["multipart/form-data", "application/x-www-form-urlencoded"]:
        request.scope["path"] = "/form"
    return await call_next(request)

@app.post("/json")
async def json_endpoint(json_data: dict):
    pass

@app.post("/form")
async def form_endpoint(file: UploadFile = File(...)):
    pass</code>

Option 4 : référencer une autre réponse pour une approche alternative

De plus, vous pouvez trouvez cette réponse sur Stack Overflow utile car elle offre une perspective différente sur la gestion à la fois du JSON et des données de formulaire dans un seul point de terminaison :

https://stackoverflow.com/a/67003163/10811840

Options de test 1, 2 et 3

À des fins de test, vous pouvez utiliser la bibliothèque de requêtes :

<code class="python">import requests

url = "http://127.0.0.1:8000"
# for testing Python 3.7 and above use:
# url = "http://localhost:8000"

# form-data request
files = [('files', ('a.txt', open('a.txt', 'rb'), 'text/plain'))]
response = requests.post(url, files=files)
print(response.text)

# JSON request
data = {"some_data": "Hello, world!"}
response = requests.post(url, json=data)
print(response.text)</code>

Ces approches fournissent différentes méthodes pour créer un point de terminaison capable de gérer à la fois JSON et le formulaire -données dans FastAPI. Choisissez l'approche qui correspond le mieux à vos besoins et à votre cas d'utilisation.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn