Задать вопрос
New_Horizons
@New_Horizons
Бред:

Может ли браузер дублировать POST запрос?

Есть некое приложение на Vue.js 3 + axios.
Есть бэк для него на Nginx + php-fpm 7.4 + laravel 8.
Приложения на отдельных доменах, искользуется CORS.
В nginx включен http2.

Приложение используется на планшетах на adnroid 14 + Яндекс браузер, по wi-fi

Пользователь в браузере нажимает на кнопку, через axios отправляются запросы на бэк:
OPTIONS - потому что CORS.
POST запрос с данными.

Это штатное поведение.

Очень редко происходит такая ситуация:
OPTIONS
POST
POST

т.е. последний запрос дублируется, они абсолютно идентичные, интервал - около секунды.

Я добавил в запрос уникальный идентификатор, чтобы понять: это какой-то баг фронта, и функция отправки запроса выполняется дважды, или это что-то более глубокое. На бэке вижу, что идентификаторы у запросов одинаковые.

Мои варианты:
- axios дублирует POST запрос. Это странно, у него никаких плагинов не подключено, по идее не должен.
- Браузер дублирует запрос из-за нестабильности сети. Основная версия
  • Вопрос задан
  • 1781 просмотр
Подписаться 4 Простой 10 комментариев
Пригласить эксперта
Ответы на вопрос 3
@Everything_is_bad
дабл клик
Ответ написан
Такое обычно происходит, когда запрос кидается в lifecycle-хуках, которые могут сработать много раз (например, updated), либо в watch. И когда у вас что-то ошибочно повторно перерендерится, то может бахнуть второй запрос. Дабл-клик по кнопке, которую вы не выключаете сразу после первого клика также не исключается.

Насчёт идентификатора вашего ничего не могу сказать, потому что не вижу, где и как вы его генерируете.

Дебажить, дебажить, и ещё раз дебажить VUE.

1. Если есть возможность запустить фронтенд на локалке в development environment, установите в браузер плагин Vuejs devtools, и посмотрите поведение компонента, кидающего запросы, может быть там что-то увидите.

2. Откройте devtools браузера и на вкладке Network и кликните ссылку в колонке Initiator (не знаю, как по-русски, не пользуюсь русским в браузере) у этих повторяющихся запросов. Если будут показаны разные участки кода, значит, где-то еще в коде затерялся такой же запрос.

3. Самое простое: прямо перед строчкой с вызовом запроса axios (прямо перед запросом, в этой же функции, не где-то вне её, а прямо в предыдущей строчке) напишите банальный console.log("Gotcha!!!!"). Если сообщение в консоли браузера появится дважды, значит, проблема исключительно в логике вашей программы.

4. Если ваш ID действительно генерируется прямо рядом с вызовом запроса, прямо в той же самой функции (что исключает баг с тем, что в запрос подставляется где-то сохранённый и кэшированный фреймворком ID), и это действительно подлый Chromium повторяет запросы из-за крайне нестабильного коннекта у пользователя, то тогда генерируйте ID не просто рандомом, который всё же может повториться, а сгенерируйте нормальный UUID, вероятность повторения которого ЗНАЧИТЕЛЬНО ниже. При приходе запроса сохраняете этот UUID на короткое время где вам удобнее, и если придёт такой же запрос с таким же UUID, то не обрабатываете его. Этот же UUID вам может помочь и в других аспектах: например, вы можете его использовать как "Correlation ID" данного конкретного запроса. Его можно отражать в логах, передавать в другие сервисы, если у вас их несколько. И тогда вы сможете без проблем отслеживать жизненный цикл каждого конкретного запроса.
Ответ написан
@IvanShatsky
Метод POST относится к неидемпотентным методам (неидемпотентными считаются три метода - POST, LOCK и PATCH). Разница между идемпотентными и неидемпотентными методами описана в RFC 9110, раздел 9.2.2. Там же сказано следующее:

A client SHOULD NOT automatically retry a request with a non-idempotent method unless it has some means to know that the request semantics are actually idempotent, regardless of the method, or some means to detect that the original request was never applied.

Nginx тоже не должен повторять попытку повторно передать запрос с неидемпотентным методом на бэкенд в случае сбоя соединения, хотя его можно заставить это делать, указав в директиве proxy_next_upstream флаг non_idempotent.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы