AJAX forma traži JSON, a dobija HTML: prođite kroz odgovor korak po korak
Status 200 nije dokaz da je odgovor JSON. Prođite kroz ploču Mreža korak po korak i razdvojite kvarove prenosa, prikaza i ugovora.
Obrazac se šalje, pokazivač se pojavljuje i konzola javlja neočekivani znak < u JSON-u na poziciji 0. Sama stranica se dobro učitava, pa je prvi refleks kriviti parser ili tunel. Obično nijedno od njih 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 doista otkriva, jer četiri moguća odgovora traže četiri različita popravka.
Korak 1: uhvatite slanje koje se stvarno dogodilo
Otvorite ploču Mreža pre slanja, postavite zapisnik da čuva unose kroz navigaciju, pa napravite jedno bezopasno probno slanje na računu koji smijete koristiti. Odaberite zahtjev koji je pokrenuo sam obrazac, a ne zahtjev dokumenta stranice.
Pazite na filtre. Filtar XHR ili Fetch je zgodan, ali ako okvir još šalje kroz skriveni iframe ili dinamički stvoreni obrazac, filtar će sakriti jedini važan zahtjev. Prvo pošaljite jednom bez filtra i pogledajte što se pojavilo.
Za odabrani zahtjev zapišite šest stvari pre bilo kakvog tumačenja: metodu, puni URL uključujući upitni niz, status, lanac preusmjeravanja, Content-Type odgovora i prve redove tela. Referenca za ploču Mreža u Chrome DevToolsu pokriva prikaze Headers, Response i Initiator u kojima se to nalazi, a ekvivalentne ploče u drugim preglednicima pokazuju ista polja.
Korak 2: potvrdite da je to zahtjev koji mislite
Iznenađujuće mnogo pogrešaka s JSON-om zapravo su pogreške usmjeravanja. Ako rukovatelj slanja baci iznimku pre nego pozove preventDefault, preglednik izvrši izvorni POST obrasca na adresu iz atributa action, a poslužitelj odgovori punom HTML stranicom. Rukovatelj se nikad ne izvrši, pa JSON nikad nije zatražen.
Usporedite URL na ploči s URL-om koji poziva vaš JavaScript. Tražite preusmjeravanje koje završava drugde, kosu crtu na kraju koja nedostaje ili je suvišna, nesklad metode gde rukovatelj šalje GET a krajnja točka prima POST, ili obrazac koji š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 točno jednoj od njih, a kategorija odlučuje gde 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 dijagnosticiraju, jer je status 200. Stranica za prijavu do koje se dođe nakon preusmjeravanja sasvim je dobar HTTP odgovor i vrlo loš JSON dokument. Vrsta sadržaja application/json to ne popravlja: to je oznaka, a pogrešno označeno telo i dalje se ne može parsirati. Pristup blokiran red je koji izgleda kao dovršen zahtjev: ploča pokazuje status, ali politika različitih izvora zadržava telo, pa je za skriptu koja poziva jednako neupotrebljivo kao istek vremena.
Četvrti red jednako je čest na starijim PHP i okvirnim stogovima. Upozorenje o zastarjelosti ispisano pre kodiranog tereta stvara telo koje nijedan JSON parser neće prihvatiti, a to je upozorenje često celo objašnjenje.
Korak 4: pročitajte pogrešku parsera doslovno
Tekst pogreške imenuje prvi znak koji je slomio parsiranje, što obično prepoznaje kategoriju bez ikakva 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 telo 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 mesto mu je u sljedećem koraku, ne u proxyju. Firefox i Safari ista četiri kvara formuliraju drukčije, pa uspoređujte po znaku ili praznom telu, a ne po točnom nizu.
Korak 5: popravite sloj na koji dokazi upućuju
Za problem usmjeravanja popravite zahtjev: ispravite action, sprečite da rukovatelj propadne, uskladite krajnju točku i metodu i ponovno testirajte. Za problem prikaza popravite ono što je proizvelo telo i otkrijte zašto se vraća dokument pogreške tamo gde su se očekivali podaci. Za problem ugovora pročitajte stvarnu očekivanu strukturu okvira za inačicu koju pokrećete i oblikujte odgovor prema njoj umesto da olabavite klijenta.
Odgovor s blokiranim pristupom traži svoj prolaz, jer zahtjev sam može biti ispravan, a telo možda nikad ne stigne do vašeg koda. Usporedite Access-Control-Allow-Origin odgovora s točnim Originom koji je preglednik poslao i zapamtite da zamjenski znak ne zadovoljava zahtjev s vjerodajnicama. Spojite credentials: 'include' na klijentu s Access-Control-Allow-Credentials: true na poslužitelju i provjerite je li poziv rabio način no-cors, gde je neprozirno telo dokumentiran 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 tela je obavezna: status 200 s objektom pogreš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, vrstu sadržaja odgovora, oblik tela i očekivani ugovor — umesto sirovog izvoza. Mrežni arhivi sadrže kolačiće, tokene, upitne nizove i osobne podatke koji su bili u obrascu, a automatski čistač nije pregled.
- Uhvatite zahtjev bez filtra pre 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 pre nego dotaknete parser.
- Popravite usmjeravanje, pristup, prikaz ili ugovor i nikad olabavljivanjem parsera.