FastAPI удалил cookie, браузер отправляет её снова: Path и Domain

Endpoint выхода возвращает 200 и заголовок Set-Cookie с истёкшим сроком. Но следующий запрос всё ещё содержит session. Часто причина в том, что при входе cookie создавали для /app, а при выходе удаляют с path по умолчанию /. В хранилище клиента это разные cookie с одним именем, и команда удаления адресована другой записи.

Cookie задаётся не только ключом. Для выбора нужной записи важны область домена и путь. Удаление работает через новый Set-Cookie, который делает соответствующую cookie истёкшей. Поэтому параметры удаления должны совпадать с параметрами создания. Ответ 200 говорит об обработке endpoint, но не подтверждает, что клиент удалил именно нужную запись.

Хранить область в одном месте

Ниже приложение устанавливает тестовую cookie для /app и удаляет её с теми же параметрами. Это пример области cookie, а не готовая система аутентификации. Для запуска и проверки установите FastAPI и httpx: python -m pip install fastapi httpx.

from fastapi import FastAPI, Response

app = FastAPI()
COOKIE_PATH = '/app'

@app.post('/app/login')
def login(response: Response):
    response.set_cookie('session', 'test-value', path=COOKIE_PATH, httponly=True)
    return {'ok': True}

@app.post('/app/logout')
def logout(response: Response):
    response.delete_cookie('session', path=COOKIE_PATH)
    return {'ok': True}

Если при создании был указан domain, передайте тот же domain при удалении. Если domain не задавался, сохраните этот контракт и в delete_cookie. Для HTTPS-приложения отдельно задаются Secure и остальные требования сессии; они не заменяют правильный путь. Не пытайтесь лечить несовпадение Path переключением SameSite: этот параметр решает другую задачу отправки cookie.

Посмотреть хранилище и заголовок

В браузере откройте список cookie и сравните имя, Domain и Path. Там могут одновременно находиться session для / и session для /app. Затем проверьте Set-Cookie в ответе выхода: есть ли нужный Path, нужный Domain и указание истечения. Если обработчик возвращает собственный Response, убедитесь, что cookie изменяется именно на возвращаемом объекте, а не на другом временном response.

Для локальной проверки TestClient позволяет выполнить login, затем logout и посмотреть его cookie jar. При намеренно неправильном path='/' запись для /app останется; после исправления исчезнет. Это воспроизводимая проверка заголовков и поведения клиента без отдельного сервера. Для браузерной интеграции после неё стоит повторить запросы в реальном HTTPS-окружении.

Удаление cookie и отзыв сессии — разные действия. Если сервер хранит состояние сессии или использует токен с собственным сроком действия, выход должен следовать выбранной политике отзыва. Исчезновение записи из браузера само по себе не отзывает скопированный ранее токен. Исправление Path завершает конкретную задачу доставки команды клиенту; жизненный цикл авторизации нужно проверять отдельно на уровне backend.

Продолжить практику

Такие ошибки становятся понятнее, когда жизненный цикл ресурсов и обработка исключений выражены в коде явно. В курсе «Python для профессионалов» есть практика контекстных менеджеров, декораторов, асинхронного кода и профилирования. Это продолжение для разработчика, который уже пишет сервисы и хочет увереннее управлять выполнением Python-программы: ограничивать область работы с ресурсом, понимать завершение операции и находить причину лишнего ожидания. Выберите в программе темы, которые нужны вашему следующему проекту.

Посмотреть программу курса

Источник: официальная документация.

Другие задачи по теме: База, HTTP-клиенты и тесты API.

Продолжить на практике

  • Python для профессионалов ↗

    Python для профессионалов — курс для людей, стремящихся углубить свои знания языка. Вы изучите итераторы, генераторы, декораторы, современные возможности Python (3.8+), освоите метапрограммирование, асинхронность, внутреннее устройство интерпретатора, инструменты оптимизации и профилирования, а также получите уверенность в использовании продвинутых возможностей стандартной библиотеки.