Formulár AJAX očakáva JSON, ale dostáva HTML: prejdite odpoveď krok za krokom
Stav 200 nie je dôkazom, že ide o JSON. Prejdite panel Sieť krok za krokom a oddeľte zlyhania prenosu, zobrazenia a kontraktu.
Formulár sa odošle, objaví sa indikátor a konzola hlási neočakávaný znak < v JSON na pozícii 0. Samotná stránka sa načítava dobre, a preto je prvým inštinktom viniť parser alebo tunel. Zvyčajne nie je zapojený ani jeden: odoslanie je iná požiadavka než načítanie stránky a vrátilo sa s niečím, čo nie je JSON. Pracujte v poradí, v akom to prehliadač skutočne odhaľuje, pretože štyri možné odpovede vyžadujú štyri rôzne opravy.
Krok 1: zachyťte odoslanie, ktoré sa naozaj stalo
Otvorte panel Sieť pred odoslaním, nastavte záznam tak, aby si pamätal položky aj pri navigácii, a potom urobte jedno neškodné testovacie odoslanie na účte, ktorý smiete použiť. Vyberte požiadavku, ktorú spustil samotný formulár, nie požiadavku dokumentu stránky.
Pozor na filtre. Filter XHR alebo Fetch je pohodlný, ale ak rámec stále odosiela cez skrytý iframe alebo dynamicky vytvorený formulár, filter skryje jedinú dôležitú požiadavku. Najprv odošlite raz bez filtra a pozrite sa, čo sa objavilo.
Pri vybranej požiadavke si pred akýmkoľvek výkladom zapíšte šesť vecí: metódu, plnú URL vrátane dopytového reťazca, stav, reťazec presmerovaní, Content-Type odpovede a prvé riadky tela. Referencia panela Sieť v Chrome DevTools pokrýva zobrazenia Headers, Response a Initiator, kde to je, a zodpovedajúce panely v iných prehliadačoch ukazujú rovnaké polia.
Krok 2: potvrďte, že je to požiadavka, ktorú si myslíte
Prekvapivo veľa chýb JSON sú v skutočnosti chyby smerovania. Ak obsluha odoslania vyhodí výnimku skôr, než zavolá preventDefault, prehliadač vykoná natívny POST formulára na adresu z atribútu action a server odpovie celou HTML stránkou. Obsluha sa nikdy nespustí, takže JSON nebol nikdy vyžiadaný.
Porovnajte URL v paneli s URL, ktorú volá váš JavaScript. Hľadajte presmerovanie, ktoré končí inde, chýbajúcu alebo prebytočnú lomku na konci, nesúlad metódy, keď obsluha posiela GET a koncový bod prijíma POST, alebo formulár odosielajúci na relatívnu cestu zo stránky, ktorá sa presunula. Sledujte reťazec presmerovaní až do konca a zapíšte konečnú URL, nie prvú.
Potom skontrolujte iniciátora. Ak požiadavka prišla z navigácie dokumentu a nie z vášho skriptu, problém ste už našli a žiadna zmena parsera odpovede nepomôže.
Krok 3: zatrieďte výsledok do štyroch kategórií
Každý výsledok patrí práve do jednej z nich a kategória rozhoduje, kam sa pozerať ďalej.
| 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 |
Prostredné riadky ľudia diagnostikujú nesprávne, pretože stav je 200. Prihlasovacia stránka dosiahnutá po presmerovaní je úplne dobrá odpoveď HTTP a veľmi zlý dokument JSON. Typ obsahu application/json to nespraví: je to označenie a nesprávne označené telo sa stále nedá parsovať. Prístup zablokovaný je riadok, ktorý vyzerá ako dokončená požiadavka: panel ukazuje stav, ale politika rôznych zdrojov zadrží telo, takže pre volajúci skript je rovnako nepoužiteľné ako vypršanie času.
Štvrtý riadok je rovnako častý na starších zostavách PHP a rámcov. Upozornenie na zastaranie vytlačené pred zakódovaným obsahom vytvorí telo, ktoré žiadny parser JSON neprijme, a to upozornenie je často celé vysvetlenie.
Krok 4: čítajte chybu parsera doslovne
Text chyby pomenúva prvý znak, ktorý zlomil parsovanie, a to zvyčajne určí kategóriu bez akéhokoľvek hádania.
| 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ázdne telo so stavom 200 je samostatný prípad: koncový bod prebehol, nič nevytvoril a niečo nižšie to vzalo ako úspech. Je to zlyhanie kontraktu aplikácie, nie prenosu, a patrí do ďalšieho kroku, nie do proxy. Firefox a Safari formulujú tie isté štyri zlyhania inak, preto porovnávajte podľa znaku alebo prázdneho tela, nie podľa presného reťazca.
Krok 5: opravte vrstvu, na ktorú ukazujú dôkazy
Pri probléme so smerovaním opravte požiadavku: opravte action, zabráňte prepadnutiu obsluhy, zlaďte koncový bod a metódu a znova otestujte. Pri probléme so zobrazením opravte to, čo vytvorilo telo, a zistite, prečo sa vracia chybový dokument tam, kde sa očakávali dáta. Pri probléme s kontraktom si prečítajte skutočnú očakávanú štruktúru rámca pre verziu, ktorú spúšťate, a odpoveď jej prispôsobte namiesto uvoľňovania klienta.
Odpoveď so zablokovaným prístupom potrebuje vlastný prechod, pretože požiadavka sama môže byť správna a telo sa k vášmu kódu nemusí nikdy dostať. Porovnajte Access-Control-Allow-Origin odpovede s presným Origin, ktorý poslal prehliadač, a pamätajte, že zástupný znak neuspokojí požiadavku s prihlasovacími údajmi. Spojte credentials: 'include' na klientovi s Access-Control-Allow-Credentials: true na serveri a skontrolujte, či volanie nepoužilo režim no-cors, kde je nepriehľadné telo dokumentovaný výsledok, nie chyba.
Nahradiť parser niečím zhovievavejším je jediná oprava, ktorej sa treba vyhnúť. Vyhodnocovanie odpovede ako kódu alebo odstraňovanie textu, kým sa nedá parsovať, skrýva nesúlad kontraktu a pridáva plochu pre injekciu výmenou za ticho. Rovnako treba stav kontrolovať oddelene od tela: stav 200 s chybovým objektom na úrovni aplikácie je v mnohých API bežný a musí sa riešiť čítaním obsahu.
Keď potrebujete pomoc od niekoho iného, zdieľajte minimálny záznam — metódu, URL, stav, konečnú URL po presmerovaniach, typ obsahu odpovede, tvar tela a očakávaný kontrakt — namiesto surového exportu. Sieťové archívy obsahujú cookies, tokeny, dopytové reťazce a osobné údaje, ktoré boli vo formulári, a automatický čistič nie je revízia.
- Zachyťte požiadavku bez filtra, kým zmeníte akýkoľvek kód.
- Potvrďte, že iniciátorom bol váš skript a konečná URL je váš koncový bod.
- Zatrieďte odpoveď, kým sa dotknete parsera.
- Opravte smerovanie, prístup, zobrazenie alebo kontrakt, a nikdy uvoľnením parsera.