Дублюється виклик коду на бекенді

💡 Усі статті, обговорення, новини про Front-end — в одному місці. Приєднуйтесь до Front-end спільноти!

Нещодавно на роботі натрапив на цікавий кейс — функція на бекенді відпрацьовує двічі, а то й більше, хоча користувач натискає кнопку лише один раз, тобто з фронта не бек запит відправляється лише один раз. Як таке взагалі можливо?

👉 Отже, у нас є:

  • У Network лише один запит
  • Сам запит падає через 4–6 хвилин з помилкою 408 Request Timeout
  • Юзер не взаємодіє зі сторінкою після кліку
  • Вкладка не оновлюється
  • В режимі incognito проблема присутня
  • Браузер Chrome
  • Застаріла версія Node та Express
  • GET-запит

Вже здогадалися, що це таке? Ні? Це був Hidden retry!

Hidden retry — це механізм, при якому браузер автоматично повторює HTTP-запит, але цей повтор не відображається в DevTools. У результаті бекенд отримує кілька однакових запитів, хоча з боку фронтенду здається, що виклик був лише один.

👉 Як це працює

  • Браузер відправляє HTTP-запит
  • Бекенд його довго обробляє
  • Сервер (Node) розриває з’єднання через ~120 секунд (дефолтний server.timeout)
  • Сам код на сервері продовжує виконуватись
  • Браузер не отримує коректної відповіді довгий час
  • Браузер вирішує, що запит не завершився і повторює його

👉 Чому це виникає
Ключова причина — стандартні таймаути у старих версіях Node: server.timeout = 120000 ms (2 хвилини). Після спливу цього часу сервер розриває з’єднання, але сам обробник не зупиняється.
У новіших версіях Node логіку таймаутів переглянули, однак така поведінка тепер просто проявляється по-іншому.

Отже, якщо ваш запит виконується довше двох хвилин, то не виключено, що запит може виконатися більше одного разу.

👍ПодобаєтьсяСподобалось3
До обраногоВ обраному0
LinkedIn
Ctrl + Enter
Ctrl + Enter

Велкам ту реальний світ розробки, де сервер не має довіряти запитам клієнтів за замовчуванням.

де сервер не має довіряти запитам клієнтів

А як тоді з цим жити?

Якщо коротко: робити нормальний бекенд. Наявність безпекової бази поведінки запитів з цієї сторони, виключає подібний кейс апріорі

Ще спробуй потестувати RDNS

Підписатись на коментарі