CORS uitgelegd: preflight, headers en CORS-fouten oplossen
CORS uitgelegd
CORS uitgelegd: preflight, headers, fouten en oplossingen | We.Inc
Zo werkt CORS: simple vs preflight requests, elke Access-Control-header, regels voor credentials, de veelvoorkomende consolefouten en een serverfix voor Express, Next.js en nginx.
CORS (cross-origin resource sharing) is de manier waarop een server de browser vertelt dat JavaScript van een andere origin zijn responses mag lezen. De server antwoordt met Access-Control-Allow-Origin en verwante headers. Requests met andere methodes, eigen headers of JSON-bodies sturen eerst een OPTIONS-preflight. De oplossing hoort altijd thuis op de server die u aanroept, nooit op de pagina.
De CORS-responseheaders in één oogopslag
Header
Wat hij toestaat
Access-Control-Allow-Origin
Welke origin de response mag lezen (één origin of *)
Access-Control-Allow-Methods
Methodes die na een preflight zijn toegestaan
Access-Control-Allow-Headers
Requestheaders die na een preflight zijn toegestaan
Access-Control-Allow-Credentials
Cookies en authenticatie die met de request meegaan (waarde moet true zijn)
Access-Control-Expose-Headers
Responseheaders die scripts mogen lezen
Access-Control-Max-Age
Aantal seconden dat een preflight-antwoord in de cache mag blijven
Een CORS-fout lijkt erop dat uw code kapot is, terwijl de request de server meestal gewoon heeft bereikt. De browser weigerde alleen het antwoord aan uw script te geven. Met de simulator hieronder beschrijft u een request en een serverconfiguratie, en ziet u of er een preflight wordt verstuurd, of de browser de response doorlaat en welke consolemelding u zou krijgen.
Stel de origin van de pagina in, de methode, een eventuele eigen header en of er cookies worden meegestuurd.
Stel in wat de server antwoordt: toegestane origin, methodes, headers en de credentials-vlag.
Lees het oordeel: of een preflight nodig is, of die slaagt, en de consolereden als het misgaat.
Kopieer het bijpassende serverfragment hieronder en voeg het toe aan de API, niet aan de front-end.
Geef de exacte origin van de aanvrager terug uit een allowlist als er cookies in het spel zijn, want de wildcard wordt met credentials geweigerd.
Voeg Vary: Origin toe zodra de toegestane origin per request verschilt, zodat caches het antwoord voor de ene site niet aan een andere geven.
Beantwoord OPTIONS met een 2xx-status en zonder redirect. Een preflight die op een login-redirect uitkomt, mislukt altijd.
CORS uitschakelen in uw eigen browser verbergt het probleem alleen op uw computer. Bezoekers krijgen de fout nog steeds.
Bij aanroepen van server naar server speelt CORS nooit een rol. Hebt u de API niet zelf in handen, roep hem dan aan vanuit uw eigen backend.
Veelgestelde vragen
Waarom werkt het in Postman of curl wel en in de browser niet?
CORS wordt alleen door browsers afgedwongen, om te voorkomen dat scripts van de ene site met uw cookies gegevens van een andere site lezen. Tools zoals curl draaien geen onbetrouwbare paginacode en negeren het dus. De response van de server was identiek; alleen de browser besloot hem achter te houden.
Wat veroorzaakt een preflight-request?
Elke methode behalve GET, HEAD of POST, elke header buiten de paar toegestane (Accept, Accept-Language, Content-Language, Content-Type, Range), of een Content-Type anders dan formuliercodering, multipart of text/plain. Het versturen van application/json is de meest voorkomende oorzaak.
Kan ik CORS vanuit de frontend oplossen?
Nee. Access-Control-headers op uw request zetten doet niets, en mode: no-cors geeft u een opaque response die uw script niet kan lezen. Ofwel voegt de API de headers toe, ofwel haalt uw eigen server de gegevens op en geeft ze door.
Kan ik Access-Control-Allow-Origin: * gebruiken met cookies?
Nee. Als een request credentials meestuurt, weigert de browser een wildcard-origin en eist hij de exacte origin plus Access-Control-Allow-Credentials: true. Hetzelfde geldt voor wildcards in de lijsten met methodes, headers en expose headers.
Waarom kan mijn script een eigen responseheader niet lezen?
Een cross-origin script ziet standaard alleen een korte lijst veilige responseheaders. Zet andere headers in Access-Control-Expose-Headers, bijvoorbeeld X-Request-Id, en ze worden leesbaar.
Same origin, en waarom de browser het lezen blokkeert
Een origin is het schema, de host en de poort samen. https://app.example.com en https://api.example.com zijn verschillende origins, net als de http- en https-versie van één domein. Standaard mag een script een request naar een andere origin sturen, maar niet lezen wat er terugkomt.
CORS is de manier om dat expliciet toe te staan. De API somt op welke origins hij vertrouwt en de browser handhaaft die lijst namens de bezoeker. Daarom moet de header komen van de server die u aanroept.
Simple requests en preflights
Een gewone GET, of een POST vanuit een normaal formulier, gaat direct de deur uit met een Origin-header. De browser controleert daarna of het antwoord een toegestane origin bevat voordat hij het aan uw code geeft.
Alles daarbuiten stuurt eerst een OPTIONS-request met Access-Control-Request-Method en Access-Control-Request-Headers. Pas als de server beide goedkeurt, gaat de echte request de deur uit. Met Access-Control-Max-Age kan de browser de goedkeuring onthouden, al begrenzen browsers hoe lang.
De consolefout lezen
Om veiligheidsredenen hoort uw JavaScript alleen dat de fetch mislukte, met een TypeError en zonder details. De echte reden staat in de browserconsole, en die noemt de header die ontbrak of fout was. Vergelijk hem met de tabel met meldingen hieronder.
Veelvoorkomende CORS-fouten en hoe u ze oplost
De formulering van meldingen verschilt per browser. Dit zijn de redenen zoals Firefox ze op MDN noemt; Chrome zegt hetzelfde in langere zinnen.
CORS-consoleredenen en de oplossing op de server
Consolereden
Wat het betekent
Oplossing op de server
CORS header 'Access-Control-Allow-Origin' missing
De response bevatte helemaal geen allow-origin-header
Voeg de header toe aan elke response, ook aan foutmeldingen
CORS header 'Access-Control-Allow-Origin' does not match
De header noemt een andere origin
Geef de origin van de aanroeper terug uit uw allowlist
Credential is not supported if the CORS header 'Access-Control-Allow-Origin' is '*'
Er werden cookies verstuurd maar de server antwoordde met *
Geef de exacte origin terug en Allow-Credentials: true
expected 'true' in CORS header 'Access-Control-Allow-Credentials'
Credentials verstuurd maar de vlag ontbreekt
Stuur Access-Control-Allow-Credentials: true
Did not find method in CORS header 'Access-Control-Allow-Methods'
De preflight keurde de methode niet goed
Zet PUT, PATCH of DELETE in Allow-Methods
missing token in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel
Een requestheader zoals Authorization werd niet goedgekeurd
Zet hem in Allow-Headers
CORS preflight channel did not succeed
OPTIONS mislukte, werd omgeleid of gaf een fout
Beantwoord OPTIONS met 204 en de headers
Multiple CORS header 'Access-Control-Allow-Origin' not allowed
Twee lagen (app en proxy) voegden allebei de header toe
Stel hem op één plek in
Serverfragmenten
Express: allowlist met credentials
Geeft de origin alleen terug als die op de lijst staat, beantwoordt preflights met 204 en voegt Vary toe zodat caches origins uit elkaar houden.
Next.js-route-handler
Een publiek endpoint zonder cookies kan de wildcard gebruiken. Exporteer OPTIONS zodat de preflight een eigen antwoord krijgt.
nginx vóór een API
De always-vlag houdt de header ook op foutresponses, zodat een 500 zijn echte status laat zien in plaats van een CORS-fout.
De browserkant: cookies cross-origin versturen
credentials: "include" is wat de strengere credentials-regels op de server activeert.
CORS-requestsimulator
Beschrijf een request en de CORS-headers van de server om te zien of er een preflight wordt verstuurd en of de browser uw script de response laat lezen.
De request
Het antwoord van de server
Origin van de pagina
Origin van de API
Methode
Content-Type
Geen body
Extra requestheader (leeg voor geen)
Cookies meesturen (credentials: include)
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Allow-Credentials: true
Oordeel
Same origin: CORS is niet van toepassing, de response is leesbaar.
Geen preflight: dit is een simple request.
Preflight nodig: de browser stuurt eerst OPTIONS.
Reden: de methode is niet GET, HEAD of POST.
Reden: de header {v} staat niet op de lijst met toegestane headers.
Reden: Content-Type {v} is niet een van de drie simple types.