Форма надсилається, з’являється індикатор, і консоль повідомляє про неочікуваний символ < у JSON на позиції 0. Сама сторінка завантажується добре, тому перший рефлекс — звинуватити парсер або тунель. Зазвичай жоден із них не задіяний: надсилання — це окремий запит, а не завантаження сторінки, і воно повернулося з чимось, що не є JSON. Працюйте в тому порядку, у якому браузер справді це виявляє, бо чотири можливі відповіді вимагають чотирьох різних виправлень.

Крок 1: перехопіть надсилання, яке справді відбулося

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

Будьте обережні з фільтрами. Фільтр XHR або Fetch зручний, але якщо каркас досі надсилає через прихований iframe або динамічно створену форму, фільтр приховає єдиний важливий запит. Спочатку надішліть один раз без фільтра і подивіться, що з’явилося.

Для вибраного запиту запишіть шість речей до будь-якого тлумачення: метод, повний URL разом із рядком запиту, статус, ланцюг переспрямувань, Content-Type відповіді та перші рядки тіла. Довідник панелі «Мережа» у Chrome DevTools охоплює подання Headers, Response і Initiator, де це міститься, а відповідні панелі в інших браузерах показують ті самі поля.

Крок 2: підтвердьте, що це саме той запит

Напрочуд багато помилок JSON насправді є помилками маршрутизації. Якщо обробник надсилання кидає виняток до виклику preventDefault, браузер виконує власний POST форми на адресу з атрибута action, а сервер відповідає повною HTML-сторінкою. Обробник ніколи не запускається, тож JSON ніколи не запитувався.

Порівняйте URL на панелі з URL, який викликає ваш JavaScript. Шукайте переспрямування, що закінчується в іншому місці, відсутній або зайвий завершальний слеш, невідповідність методу, коли обробник надсилає GET, а кінцева точка приймає POST, або форму, що надсилає на відносний шлях зі сторінки, яка переїхала. Прослідкуйте ланцюг переспрямувань до кінця і запишіть кінцевий URL, а не перший.

Потім перевірте ініціатора. Якщо запит прийшов із навігації документа, а не з вашого скрипту, проблему вже знайдено, і жодна зміна в парсері відповіді не допоможе.

Крок 3: розкладіть результат за чотирма категоріями

Кожен результат належить рівно до однієї з них, і категорія визначає, куди дивитися далі.

What you seeCategoryWhere to look
Request never finishes, TLS or connection errorNo usable responseEndpoint reachability, certificate, front-end timeout
Request completes, script gets an opaque failureAccess blockedCross-origin policy, credentials mode, missing response header
200 with an HTML body or a login formWrong representationRedirect, expired session, route fallback, error handler
Body begins with a notice then valid JSONWrong representationServer-side warning output before serialisation
Valid JSON, framework rejects itContract mismatchEnvelope shape, field names, value types

Середні рядки найчастіше діагностують неправильно, бо статус — 200. Сторінка входу, досягнута після переспрямування, — цілком нормальна відповідь HTTP і дуже поганий документ JSON. Тип вмісту application/json цього не виправляє: це лише ярлик, а неправильно позначене тіло все одно не парситься. «Доступ заблоковано» — це рядок, що виглядає як завершений запит: панель показує статус, але політика між різними джерелами утримує тіло, тож для скрипту, що викликає, воно так само марне, як і тайм-аут.

Четвертий рядок так само частий на старих стеках PHP і каркасів. Попередження про застарілість, надруковане перед закодованим навантаженням, дає тіло, яке не прийме жоден парсер JSON, і часто це попередження і є всім поясненням.

Крок 4: читайте помилку парсера буквально

Текст помилки називає перший символ, що зламав розбір, і це зазвичай визначає категорію без жодних здогадів.

Error text (Chrome/V8)What it means
Unexpected token < in JSON at position 0The body starts with markup: an HTML page or an error document
Unexpected end of JSON inputEmpty body, or the response was truncated
Unexpected token o in JSON at position 1You parsed something already parsed, typically an object rather than text
Unexpected token uThe body starts with the bare word undefined, usually an empty response rendered as a string

Порожнє тіло зі статусом 200 — окремий випадок: кінцева точка відпрацювала, нічого не створила, а щось нижче сприйняло це як успіх. Це збій контракту застосунку, а не транспорту, і його місце в наступному кроці, а не в проксі. Firefox і Safari формулюють ті самі чотири збої інакше, тому зіставляйте за символом або за порожнім тілом, а не за точною послідовністю.

Крок 5: виправте шар, на який указують докази

Для проблеми маршрутизації виправте запит: виправте action, не дайте обробнику провалитися, узгодьте кінцеву точку й метод і перевірте знову. Для проблеми подання виправте те, що створило тіло, і з’ясуйте, чому документ помилки повертається там, де очікувалися дані. Для проблеми контракту прочитайте реальну очікувану структуру каркасу для вашої версії і сформуйте відповідь за нею, а не послаблюйте клієнт.

Відповідь із заблокованим доступом потребує окремого проходу, бо сам запит може бути правильним, а тіло може так і не дійти до вашого коду. Порівняйте Access-Control-Allow-Origin відповіді з точним Origin, який надіслав браузер, і пам’ятайте, що шаблон не задовольняє запит з обліковими даними. З’єднайте credentials: 'include' на клієнті з Access-Control-Allow-Credentials: true на сервері та перевірте, чи виклик не використав режим no-cors, де непрозоре тіло — це задокументований результат, а не дефект.

Заміна парсера на щось поблажливіше — єдине виправлення, якого слід уникати. Виконання відповіді як коду або зчищення тексту, доки він не розбереться, приховує невідповідність контракту і додає поверхню для ін’єкцій в обмін на тишу. Так само статус треба перевіряти окремо від тіла: 200 з об’єктом помилки на рівні застосунку нормальний у багатьох API, і його треба обробляти, читаючи навантаження.

Коли потрібна допомога іншої людини, поділіться мінімальним записом — метод, URL, статус, кінцевий URL після переспрямувань, тип вмісту відповіді, форма тіла й очікуваний контракт — замість необробленого експорту. Мережеві архіви містять cookie, токени, рядки запитів і персональні дані, що були у формі, а автоматичний очищувач не є переглядом.

  • Перехопіть запит без фільтра, перш ніж змінювати будь-який код.
  • Підтвердьте, що ініціатором був ваш скрипт, а кінцевий URL — ваша кінцева точка.
  • Класифікуйте відповідь, перш ніж торкатися парсера.
  • Виправте маршрутизацію, доступ, подання або контракт і ніколи — послаблюючи парсер.

Схожі статті