AJAX forma očekuje JSON, ali dobija HTML: pregledajte odgovor korak po korak
Status 200 nije dokaz da je odgovor JSON. Prođite kroz panel Mreža korak po korak i razdvojite kvarove prenosa, predstavljanja i ugovora.
Forma se šalje, pojavljuje se indikator i konzola javlja neočekivani znak < u JSON-u na poziciji 0. Sama stranica se dobro učitava, zato je prvi refleks kriviti parser ili tunel. Obično nijedno od toga nije uključeno: slanje je drugi zahtjev od učitavanja stranice i vratilo se s nečim što nije JSON. Radite redom kojim to preglednik zaista otkriva, jer četiri moguća odgovora traže četiri različita popravka.
Korak 1: uhvatite slanje koje se zaista dogodilo
Otvorite panel Mreža prije slanja, podesite dnevnik da čuva zapise kroz navigaciju, pa napravite jedno bezopasno probno slanje na računu koji smijete koristiti. Odaberite zahtjev koji je pokrenula sama forma, a ne zahtjev dokumenta stranice.
Pazite na filtere. Filter XHR ili Fetch je zgodan, ali ako okvir još šalje kroz skriveni iframe ili dinamički stvorenu formu, filter će sakriti jedini važan zahtjev. Prvo pošaljite jednom bez filtera i pogledajte što se pojavilo.
Za odabrani zahtjev zapišite šest stvari prije bilo kakvog tumačenja: metodu, puni URL uključujući upitni niz, status, lanac preusmjeravanja, Content-Type odgovora i prve redove tijela. Referenca za panel Mreža u Chrome DevTools pokriva prikaze Headers, Response i Initiator u kojima se to nalazi, a ekvivalentni paneli u drugim preglednicima pokazuju ista polja.
Korak 2: potvrdite da je to zahtjev koji mislite
Iznenađujuće mnogo grešaka s JSON-om zapravo su greške usmjeravanja. Ako rukovalac slanja baci izuzetak prije nego pozove preventDefault, preglednik izvrši izvorni POST forme na adresu iz atributa action, a server odgovori punom HTML stranicom. Rukovalac se nikad ne izvrši, pa JSON nikad nije ni zatražen.
Uporedite URL u panelu s URL-om koji poziva vaš JavaScript. Tražite preusmjeravanje koje završava negdje drugdje, kosu crtu na kraju koja nedostaje ili je suvišna, nesklad metoda gdje rukovalac šalje GET a krajnja točka prima POST, ili formu koja šalje na relativnu putanju sa stranice koja se preselila. Prati lanac preusmjeravanja do kraja i zabilježite konačni URL, ne prvi.
Zatim provjerite inicijatora. Ako je zahtjev došao iz navigacije dokumenta, a ne iz vaše skripte, već ste našli problem i nikakva promjena parsera odgovora neće pomoći.
Korak 3: razvrstajte ishod u četiri kategorije
Svaki rezultat pripada tačno jednoj od njih, a kategorija odlučuje gdje dalje gledate.
| 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 |
Srednji redovi su oni koje ljudi pogrešno dijagnostikuju, jer je status 200. Stranica za prijavu do koje se dođe nakon preusmjeravanja sasvim je dobar HTTP odgovor i vrlo loš JSON dokument. Tip sadržaja application/json to ne popravlja: to je oznaka, a pogrešno označeno tijelo se i dalje ne može parsirati. Pristup blokiran je red koji izgleda kao završen zahtjev: panel pokazuje status, ali politika različitih izvora zadržava tijelo, pa je za skriptu koja poziva jednako neupotrebljivo kao istek vremena.
Četvrti red je jednako čest na starijim PHP i okvirnim stekovima. Upozorenje o zastarjelosti ispisano prije kodiranog tereta stvara tijelo koje nijedan JSON parser neće prihvatiti, a to upozorenje često je cijelo objašnjenje.
Korak 4: pročitajte grešku parsera doslovno
Tekst greške imenuje prvi znak koji je slomio parsiranje, što obično prepoznaje kategoriju bez ikakvog nagađanja.
| 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 |
Prazno tijelo sa statusom 200 poseban je slučaj: krajnja točka je radila, ništa nije proizvela, a nešto nizvodno to je uzelo kao uspjeh. To je kvar ugovora aplikacije, a ne prenosa, i mjesto mu je u sljedećem koraku, ne u proksiju. Firefox i Safari iste četiri kvarove formuliraju drugačije, pa upoređujte po znaku ili praznom tijelu, a ne po tačnom nizu.
Korak 5: popravite sloj na koji dokazi pokazuju
Za problem usmjeravanja popravite zahtjev: ispravite action, spriječite da rukovalac propadne, uskladite krajnju točku i metodu i ponovo testirajte. Za problem predstavljanja popravite ono što je proizvelo tijelo i otkrijte zašto se vraća dokument greške tamo gdje su se očekivali podaci. Za problem ugovora pročitajte stvarnu očekivanu strukturu okvira za verziju koju pokrećete i oblikujte odgovor prema njoj umjesto da olabavite klijenta.
Odgovor s blokiranim pristupom traži svoj prolaz, jer zahtjev sam može biti ispravan, a tijelo možda nikad ne stigne do vašeg koda. Uporedite Access-Control-Allow-Origin odgovora s tačnim Origin koji je preglednik poslao i zapamtite da zamjenski znak ne zadovoljava zahtjev s vjerodajnicama. Spojite credentials: 'include' na klijentu sa Access-Control-Allow-Credentials: true na serveru i provjerite je li poziv koristio način no-cors, gdje je neprozirno tijelo dokumentovan ishod, a ne greška.
Zamjena parsera nečim popustljivijim jedini je popravak koji treba izbjegavati. Izvršavanje odgovora kao koda ili skidanje teksta dok se ne parsira skriva nesklad ugovora i dodaje površinu za injektiranje u zamjenu za tišinu. Isto tako, provjera statusa odvojeno od tijela je obavezna: status 200 s objektom greške na razini aplikacije normalan je u mnogim API-jima i mora se obraditi čitanjem tereta.
Kada vam treba pomoć nekoga drugog, podijelite minimalni zapis — metodu, URL, status, konačni URL nakon preusmjeravanja, tip sadržaja odgovora, oblik tijela i očekivani ugovor — umjesto sirovog izvoza. Mrežni arhivi sadrže kolačiće, tokene, upitne nizove i lične podatke koji su bili u formi, a automatski čistač nije pregled.
- Uhvatite zahtjev bez filtera prije nego promijenite bilo koji kod.
- Potvrdite da je inicijator bila vaša skripta i da je konačni URL vaša krajnja točka.
- Klasificirajte odgovor prije nego dotaknete parser.
- Popravite usmjeravanje, pristup, predstavljanje ili ugovor i nikad olabavljivanjem parsera.