Форма адпраўляецца, з’яўляецца індыкатар, і кансоль паведамляе пра нечаканы сімвал < у 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 пасля перанакіраванняў, тып змесціва адказу, форма цела і чаканы кантракт — а не сырым экспартам. Неэтворк-архівы змяшчаюць кукі, токены, радкі запыту і асабістыя даныя, якія былі ў форме, а аўтаматычны ачышчальнік не з’яўляецца рэвізіяй.

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

Падобныя артыкулы