Formulář AJAX očekává JSON, ale dostává HTML: projděte odpověď krok za krokem
Stav 200 není důkazem JSON. Projděte panel Síť krok za krokem a oddělte selhání přenosu, reprezentace a kontraktu.
Formulář se odešle, objeví se indikátor a konzole hlásí neočekávaný znak < v JSON na pozici 0. Stránka se sama načítá bez potíží, a proto je prvním instinktem vinit parser nebo tunel. Obvykle se neúčastní ani jeden z nich: odeslání je jiný požadavek než načtení stránky a vrátilo se s něčím, co není JSON. Pracujte v pořadí, v jakém to prohlížeč skutečně odhaluje, protože čtyři možné odpovědi vyžadují čtyři různá řešení.
Krok 1: zachyťte odeslání, které opravdu proběhlo
Otevřete panel Síť ještě před odesláním, nastavte záznam tak, aby si pamatoval položky i po navigaci, a pak proveďte jedno neškodné testovací odeslání na účtu, který smíte použít. Vyberte požadavek, který spustil sám formulář, nikoli požadavek na dokument stránky.
Pozor na filtry. Filtr XHR nebo Fetch je pohodlný, ale pokud rámec stále odesílá přes skrytý iframe nebo dynamicky vytvořený formulář, filtr skryje jediný důležitý požadavek. Nejdřív odešlete jednou bez filtru a podívejte se, co se objevilo.
U vybraného požadavku si před jakýmkoli výkladem zapište šest věcí: metodu, plnou URL včetně dotazovacího řetězce, stav, řetězec přesměrování, Content-Type odpovědi a první řádky těla. Reference k panelu Síť v Chrome DevTools pokrývá pohledy Headers, Response a Initiator, kde to je, a odpovídající panely v jiných prohlížečích ukazují stejná pole.
Krok 2: ověřte, že jde o požadavek, který si myslíte
Překvapivě mnoho chyb s JSON jsou ve skutečnosti chyby směrování. Když obsluha odeslání vyhodí výjimku dřív, než zavolá preventDefault, prohlížeč provede nativní POST formuláře na adresu z atributu action a server odpoví celou HTML stránkou. Obsluha se nikdy nespustí, takže JSON nebyl nikdy vyžádán.
Porovnejte URL v panelu s URL, kterou volá váš JavaScript. Hledejte přesměrování, které končí jinde, chybějící nebo přebývající lomítko na konci, nesoulad metody, kdy obsluha posílá GET a koncový bod přijímá POST, nebo formulář posílající na relativní cestu ze stránky, která se přesunula. Sledujte řetězec přesměrování až do konce a poznamenejte si konečnou URL, ne první.
Potom zkontrolujte iniciátora. Pokud požadavek přišel z navigace dokumentu a ne z vašeho skriptu, problém jste už našli a žádná změna parseru odpovědi nepomůže.
Krok 3: zařaďte výsledek do čtyř kategorií
Každý výsledek patří právě do jedné z nich a kategorie rozhoduje, kam se dívat dál.
| What you see | Category | Where to look |
|---|---|---|
| Request never finishes, TLS or connection error | No usable response | Endpoint reachability, certificate, front-end timeout |
| Request completes, script gets an opaque failure | Access blocked | Cross-origin policy, credentials mode, missing response header |
| 200 with an HTML body or a login form | Wrong representation | Redirect, expired session, route fallback, error handler |
| Body begins with a notice then valid JSON | Wrong representation | Server-side warning output before serialisation |
| Valid JSON, framework rejects it | Contract mismatch | Envelope shape, field names, value types |
Prostřední řádky lidé diagnostikují špatně, protože stav je 200. Přihlašovací stránka dosažená po přesměrování je naprosto dobrá odpověď HTTP a velmi špatný dokument JSON. Typ obsahu application/json to nespraví: je to jen označení a špatně označené tělo se stejně nepodaří analyzovat. Přístup zablokován je řádek, který vypadá jako dokončený požadavek: panel ukazuje stav, ale politika různých zdrojů tělo zadrží, takže je pro volající skript stejně nepoužitelné jako vypršení času.
Čtvrtý řádek je stejně častý na starších sestavách PHP a rámců. Upozornění na zastarání vypsané před zakódovaným obsahem vytvoří tělo, které žádný parser JSON nepřijme, a to upozornění je často celé vysvětlení.
Krok 4: čtěte chybu parseru doslova
Text chyby pojmenuje první znak, který analýzu zlomil, což obvykle určí kategorii bez jakéhokoli hádání.
| Error text (Chrome/V8) | What it means |
|---|---|
| Unexpected token < in JSON at position 0 | The body starts with markup: an HTML page or an error document |
| Unexpected end of JSON input | Empty body, or the response was truncated |
| Unexpected token o in JSON at position 1 | You parsed something already parsed, typically an object rather than text |
| Unexpected token u | The body starts with the bare word undefined, usually an empty response rendered as a string |
Prázdné tělo se stavem 200 je samostatný případ: koncový bod proběhl, nic nevytvořil a něco níž to vzalo jako úspěch. To je selhání kontraktu aplikace, ne přenosu, a patří do dalšího kroku, ne do proxy. Firefox a Safari formulují stejné čtyři chyby jinak, takže porovnávejte podle znaku nebo prázdného těla, ne podle přesného řetězce.
Krok 5: opravte vrstvu, na kterou ukazují důkazy
U problému se směrováním opravte požadavek: opravte action, zabraňte propadnutí obsluhy, slaďte koncový bod a metodu a znovu otestujte. U problému s reprezentací opravte to, co tělo vytvořilo, a zjistěte, proč se vrací chybový dokument tam, kde se čekala data. U problému s kontraktem si přečtěte skutečnou očekávanou strukturu rámce pro verzi, kterou provozujete, a odpověď jí přizpůsobte, místo abyste uvolňovali klienta.
Odpověď se zablokovaným přístupem potřebuje vlastní průchod, protože požadavek sám může být správný a tělo se k vašemu kódu nemusí nikdy dostat. Porovnejte Access-Control-Allow-Origin odpovědi s přesným Origin, který prohlížeč poslal, a pamatujte, že zástupný znak neuspokojí požadavek s přihlašovacími údaji. Spojte credentials: 'include' na klientovi s Access-Control-Allow-Credentials: true na serveru a zkontrolujte, zda volání nepoužilo režim no-cors, kde je neprůhledné tělo dokumentovaný výsledek, ne chyba.
Nahradit parser něčím shovívavějším je jediná oprava, které je třeba se vyhnout. Vyhodnocovat odpověď jako kód nebo odstraňovat text, dokud se nezpracuje, skrývá nesoulad kontraktu a přidává plochu pro injekci výměnou za ticho. Stejně tak je nutné kontrolovat stav odděleně od těla: stav 200 s chybovým objektem na úrovni aplikace je v mnoha API běžný a musí se řešit čtením obsahu.
Když potřebujete pomoc od někoho jiného, sdílejte minimální záznam — metodu, URL, stav, konečnou URL po přesměrováních, typ obsahu odpovědi, tvar těla a očekávaný kontrakt — místo surového exportu. Síťové archivy obsahují cookies, tokeny, dotazovací řetězce a osobní údaje, které byly ve formuláři, a automatický čistič není revize.
- Zachyťte požadavek bez filtru, než změníte jakýkoli kód.
- Ověřte, že iniciátorem byl váš skript a konečná URL je váš koncový bod.
- Klasifikujte odpověď, než se dotknete parseru.
- Opravte směrování, přístup, reprezentaci nebo kontrakt, a nikdy uvolněním parseru.