En AJAX-formular forventer JSON, men får HTML: gennemgå svaret trin for trin
Et 200-svar er ikke bevis på JSON. Gå gennem Netværk-panelet trin for trin, og skil fejl i transport, repræsentation og kontrakt fra hinanden.
Formularen sendes, spinneren vises, og konsollen siger uventet token < i JSON ved position 0. Siden selv indlæses fint, og derfor er den første tilbøjelighed at give parseren eller tunnelen skylden. Ingen af dem er normalt involveret: indsendelsen er en anden anmodning end sideindlæsningen, og den kom tilbage med noget, der ikke er JSON. Arbejd i den rækkefølge, browseren faktisk afslører det i, for de fire mulige svar kræver fire forskellige rettelser.
Trin 1: fang den indsendelse, der faktisk skete
Åbn Netværk-panelet, før du sender, sæt loggen til at bevare poster på tværs af navigation, og lav derefter en uskadelig testindsendelse på en konto, du må bruge. Vælg den anmodning, som formularen selv startede, og ikke sidens dokumentanmodning.
Vær forsigtig med filtre. Et XHR- eller Fetch-filter er bekvemt, men hvis rammen stadig sender gennem en skjult iframe eller en dynamisk oprettet formular, skjuler filteret den eneste anmodning, der betyder noget. Send først én gang uden filter, og se hvad der dukkede op.
For den valgte anmodning skal du notere seks ting, før du fortolker noget: metoden, den fulde URL inklusive query-strengen, status, omdirigeringskæden, svarets Content-Type og de første linjer af kroppen. Reference til Netværk-panelet i Chrome DevTools dækker visningerne Headers, Response og Initiator, hvor det findes, og de tilsvarende paneler i andre browsere viser de samme felter.
Trin 2: bekræft, at det er den anmodning, du tror
Et overraskende antal JSON-fejl er faktisk routingfejl. Hvis indsendelses-handleren kaster, før den kalder preventDefault, udfører browseren et native formular-POST til det, som action-attributten angiver, og serveren svarer med en fuld HTML-side. Handleren kører aldrig, så der blev aldrig bedt om JSON.
Sammenlign URL’en i panelet med den URL, din JavaScript kalder. Se efter en omdirigering, der ender et andet sted, en manglende eller ekstra skråstreg til sidst, et metode-mismatch, hvor handleren sender GET, mens endepunktet accepterer POST, eller en formular, der sender til en relativ sti fra en side, der er flyttet. Følg omdirigeringskæden til ende, og noter den endelige URL, ikke den første.
Kontrollér derefter initiatoren. Hvis anmodningen kom fra en dokumentnavigation og ikke fra dit script, har du allerede fundet problemet, og ingen ændring af en svarparser hjælper.
Trin 3: sortér resultatet i fire kategorier
Hvert resultat hører præcis til én af disse, og kategorien afgør, hvor du kigger næste gang.
| 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 |
De midterste rækker er dem, folk fejldiagnosticerer, fordi status er 200. En login-side, der nås efter en omdirigering, er et fuldstændig godt HTTP-svar og et meget dårligt JSON-dokument. Content-typen application/json reparerer ikke det: det er en etiket, og en fejletiketteret krop kan stadig ikke parses. Adgang blokeret er den række, der ligner en afsluttet anmodning: panelet viser en status, men cross-origin-politikken tilbageholder kroppen, så for det kaldende script er den lige så ubrugelig som en timeout.
Den fjerde række er lige så almindelig på ældre PHP- og ramme-stakke. En deprecation-advarsel, der printes før den kodede belastning, giver en krop, som ingen JSON-parser accepterer, og advarslen er ofte hele forklaringen.
Trin 4: læs parserfejlen bogstaveligt
Fejlteksten nævner det første tegn, der brød parsningen, og det identificerer normalt kategorien uden nogen gætteri.
| 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 |
En tom krop med et 200 er sit eget tilfælde: endepunktet kørte, producerede intet, og noget længere nede behandlede det som succes. Det er en kontraktfejl i applikationen, ikke en transportfejl, og den hører i næste trin, ikke i proxyen. Firefox og Safari formulerer de samme fire fejl anderledes, så match på tegnet eller på den tomme krop i stedet for på den præcise streng.
Trin 5: ret det lag, som evidensen peger på
Ved et routingproblem skal du rette anmodningen: ret action, forhindr handleren i at falde igennem, få endepunkt og metode til at passe, og test igen. Ved et repræsentationsproblem skal du rette det, der producerede kroppen, og finde ud af, hvorfor et fejldokument returneres, hvor der var forventet data. Ved et kontraktproblem skal du læse rammens faktiske forventede struktur for den version, du kører, og forme svaret efter den i stedet for at løsne klienten.
Et svar med blokeret adgang kræver sin egen gennemgang, fordi anmodningen selv kan være korrekt, og kroppen måske aldrig når din kode. Sammenlign svarets Access-Control-Allow-Origin med den præcise Origin, browseren sendte, og husk, at et jokertegn ikke opfylder en anmodning med legitimationsoplysninger. Par credentials: 'include' på klienten med Access-Control-Allow-Credentials: true på serveren, og kontrollér, om kaldet brugte no-cors-tilstand, hvor en uigennemsigtig krop er det dokumenterede resultat og ikke en fejl.
At erstatte parseren med noget eftergivende er den ene rettelse, man skal undgå. At evaluere svaret som kode eller skrælle tekst af, indtil det parser, skjuler kontraktmismatchet og tilføjer en injektionsflade i bytte for tavshed. Ligesom status skal kontrolleres adskilt fra kroppen: et 200 med et applikationsniveau-fejlobjekt er normalt i mange API’er og skal håndteres ved at læse belastningen.
Når du har brug for hjælp fra en anden, så del en minimal registrering — metode, URL, status, endelig URL efter omdirigeringer, svarets indholdstype, kroppens form og den forventede kontrakt — i stedet for en rå eksport. Netværksarkiver indeholder cookies, tokens, query-strenge og de personoplysninger, der var i formularen, og en automatisk renser er ikke en gennemgang.
- Fang anmodningen uden filter, før du ændrer nogen kode.
- Bekræft, at initiatoren var dit script, og at den endelige URL er dit endepunkt.
- Klassificér svaret, før du rører parseren.
- Ret routing, adgang, repræsentation eller kontrakt, og aldrig ved at løsne parseren.