Как в FastAPI определить и обработать HTTP-метод запроса

Ответ

В FastAPI маршрутизация запросов на основе HTTP-метода (GET, POST, PUT и т.д.) выполняется с помощью специальных декораторов. Это основной и наиболее декларативный способ.

1. Основной способ: Декораторы методов

Каждому HTTP-методу соответствует свой декоратор (@app.get, @app.post, @app.put, @app.delete и т.д.), который связывает URL-путь с функцией-обработчиком.

from fastapi import FastAPI

app = FastAPI()

# Этот обработчик будет вызван только для GET-запросов к /items/
@app.get("/items/")
async def read_items():
    return {"method": "GET"}

# Этот обработчик — только для POST-запросов к /items/
@app.post("/items/")
async def create_item():
    return {"method": "POST"}

2. Получение метода в процессе выполнения

Если необходимо узнать метод внутри самой функции (например, для логирования или сложной логики), можно использовать зависимость Request.

from fastapi import FastAPI, Request

app = FastAPI()

@app.api_route("/some-path", methods=["GET", "POST"]) # Обрабатывает несколько методов
async def handle_request_dynamically(request: Request):
    # request.method содержит строку с названием HTTP-метода, например, "GET"
    if request.method == "POST":
        # Логика для создания ресурса
        return {"message": f"Handling a {request.method} request"}

    # Логика по умолчанию для GET
    return {"message": f"Handling a {request.method} request"}

Таким образом, FastAPI предоставляет как статический (декораторы), так и динамический (Request объект) способы работы с HTTP-методами.

Ответ 18+ 🔞

Так, слушай, смотри, как это всё работает, а то я тут вижу, у некоторых мозги уже набекрень поехали от этих HTTP-методов.

Вот смотри, в FastAPI, если тебе нужно, чтобы по одному и тому же пути, ну, скажем, /items/, один код работал на чтение (GET), а другой — на запись (POST), то делается это проще пареной репы. Не надо городить огород, блядь.

Первый способ, он же основной, он же правильный, он же — не выёбывайся

Просто вешаешь на свою функцию-обработчик нужный декоратор. Хочешь GET — @app.get. Хочешь POST — @app.post. Всё, пипец, вопрос закрыт. FastAPI сам разберётся, какую функцию когда вызывать.

from fastapi import FastAPI

app = FastAPI()

# Эта штука сработает ТОЛЬКО если кто-то припёрся с GET-запросом на /items/
@app.get("/items/")
async def read_items():
    return {"method": "GET"}

# А эта — ТОЛЬКО если прилетел POST на тот же самый /items/
@app.post("/items/")
async def create_item():
    return {"method": "POST"}

Вот и вся магия. Чисто, красиво, без всяких подвохов. FastAPI — он умный, он не перепутает.

Второй способ, если ты хитрая жопа и хочешь всё в одной кучке

Бывает же, ну, мало ли, захотелось одну функцию на все методы запилить. Для логирования там, или ещё какая извращенская логика. Ну что ж, можно и так. Берёшь объект Request и смотришь, какой метод пришёл.

from fastapi import FastAPI, Request

app = FastAPI()

# Обрати внимание на @app.api_route и параметр methods. Тут мы говорим: "Эй, функция, лови и GET, и POST!"
@app.api_route("/some-path", methods=["GET", "POST"])
async def handle_request_dynamically(request: Request):
    # А внутри уже смотрим, что за метод нам подсунули
    if request.method == "POST":
        # Ну, значит, создаём что-то, ебать его в сраку
        return {"message": f"Handling a {request.method} request"}

    # А если не POST, то по умолчанию считаем, что GET (ну или другая логика)
    return {"message": f"Handling a {request.method} request"}

Но, честно говоря, если нет реальной причины — не усложняй, ёпта. Первый способ и читается лучше, и поддерживается легче. Не будь тем самым чуваком, который из-за желания выглядеть умным нагородил такую дичь, что потом сам же и обосрётся, когда её чинить придётся.

Короче, выбор за тобой. Можно по-простому, а можно — с приключениями на свою жопу.