Näin korjaat CORS-virheet ja ymmärrät, miksi ne syntyvät
CORS-virhe tarkoittaa, että web-sivusi yritti lukea vastauksen toisesta originista (toisesta domainista, portista tai protokollasta), eikä sen palvelin lähettänyt otsikoita, jotka sallivat sen. Selaimet estävät vastauksen suojellakseen käyttäjiä. Korjaat sen palvelimella: palautat sivustosi originille Access-Control-Allow-Origin-otsikon ja käsittelet OPTIONS-esilento-pyynnöt. Tai vältät virheen lähettämällä pyynnön oman takapäsi kautta samassa originissa.
Se on yksi web-kehityksen sekavimmista virheistä, koska pyyntö usein saavuttaa palvelimen hyvin. Tämä opas selittää, mitä tapahtuu, ja miten korjata kukin variantti.
Mitä ”origin” tarkoittaa
Origin on protokollan, domainin ja portin yhdistelmä:
| URL | Origin |
|---|---|
https://omasovellus.fi/dashboard | https://omasovellus.fi |
https://api.omasovellus.fi/users | https://api.omasovellus.fi (eri aliaksen vuoksi eri origin) |
http://localhost:5173 | http://localhost:5173 |
http://localhost:3000 | http://localhost:3000 (eri portin vuoksi eri origin) |
Selaimet noudattavat samaa originia koskevaa käytäntöä: sivun JavaScript voi vapaasti lukea oman originsa vastaukset, mutta ei muiden. CORS (Cross-Origin Resource Sharing) on järjestelmä, jolla palvelin voi antaa luvan: ”sivut näistä origineista saavat lukea vastaukseni”.
Kaksi seikkaa yllättää ihmisiä:
- Pyyntö usein saavuttaa palvelimen. CORS estää yleensä koodiasi lukemasta vastausta, ei palvelinta vastaanottamasta pyyntöä. POST on saattanut tallentua, vaikka näit virheen.
- Vain selaimet noudattavat sitä. curl, Postman ja palvelinpuolen koodi eivät välitä CORS:sta lainkaan. Siksi ”toimii Postmanissa” ei kerro sinulle mitään CORS:sta.
Vaihe 1: Lue tarkka virhe
Avaa kehittäjätyökalut (oikea klikkaus → Tarkista), siirry Console-välilehdelle ja lue koko viesti. Chromen sanamuoto kertoo, mikä ongelma on:
| Viesti sisältää | Mikä on vialla |
|---|---|
No 'Access-Control-Allow-Origin' header is present | Palvelin ei lähettänyt otsikkoa lainkaan, tai pyyntö epäonnistui ennen CORS-koodiasi (esimerkiksi 404 tai 500) |
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin | Palvelin sallii jonkin muun originin kuin sinun |
Response to preflight request doesn't pass access control check | OPTIONS-esilento epäonnistui |
...must not be the wildcard '*' when the request's credentials mode is 'include' | Lähetät evästeitä, ja palvelin vastasi *-merkillä |
Request header field authorization is not allowed | Palvelin ei listannut tätä otsikkoa kohdassa Access-Control-Allow-Headers |
Avaa sen jälkeen Network-välilehti, etsi epäonnistunut pyyntö (ja mahdollinen sitä edeltävä OPTIONS-pyyntö) ja katso sen tilakoodi ja vastausotsikot.
Tarkista ensin tilakoodi. Monet ”CORS-virheet” ovat oikeasti palvelinvirheitä naamioituneina. Jos palvelin kaatuu tai palauttaa 404:n, sen virhevastauksesta puuttuvat usein CORS-otsikot, joten selain raportoi CORS-virheen oikean ongelman sijaan. Korjaa 500 tai 404 ensin, ja CORS-virhe voi kadota.
Vaihe 2: Päätä, pitäisikö selaimen kutsua tätä API:a ollenkaan
Ennen kuin lisäät otsikoita, kysy: pitäisikö selaimen kutsua tätä API:a suoraan?
- Kolmannen osapuolen API, joka vaatii salaisen avaimen (OpenAI, Stripen salainen avain, useimmat sähköpostipalvelut), ei koskaan pidä kutsua selaimesta. Avain näkyisi jokaiselle kävijälle. Kutsu se takapäästäsi, ja CORS-ongelma katoaa, koska palvelin-palvelin-pyynnöt eivät ole CORS:n alaisia. Katso näin pidät API-avaimet turvassa.
- Kolmannen osapuolen API, jota et hallitse eikä lähetä CORS-otsikoita, ei voi korjata omalta puoleltasi. Kutsu sitä takapäästäsi.
- Oma API voidaan korjata kunnolla asettamalla se. Jatka alla.
Vaihe 3: Korjaa palvelimellasi
Palvelimen pitää lisätä oikeat otsikot vastauksiinsa, myös virhevastauksiin.
Varsinaiselle pyynnölle lähetä:
Access-Control-Allow-Origin: https://omasovellus.fi(frontendisi tarkka origin, ilman perässä olevaa kauttaviivaa)Vary: Origin, jos arvo riippuu siitä, mikä origin pyysi
Esilento-pyynnölle OPTIONS vastaa onnistumistilalla (200 tai 204) ja:
Access-Control-Allow-Origin: https://omasovellus.fiAccess-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETEAccess-Control-Allow-Headers: Content-Type, Authorization(jokainen mukautettu otsikko, jonka lähetät)- Valinnaisesti
Access-Control-Max-Age: 600, jotta selain välimuistittaa esilennon hetkeksi
Useimmilla kehyksillä on paketti tai asetus, joka tekee tämän. Expressissä cors-paketti; FastAPI:ssa CORSMiddleware; ASP.NET Coressa AddCors; Springissä @CrossOrigin tai CORS-konfiguraatio. Tyypillinen Express-asetus:
import cors from "cors";
app.use(cors({
origin: ["https://omasovellus.fi", "http://localhost:5173"],
credentials: true,
}));
Sijoita CORS-käsittely ennen reittejäsi ja tunnistautumista, jotta esilento-pyyntöjä (joissa ei ole kirjautumista) ei hylätä 401:llä.
Tekoälyrakentajalla kuvaile asetus tarkasti:
Frontend osoitteessa
https://omasovellus.fikutsuu API:a osoitteessahttps://api.omasovellus.fija saa virheen ”Response to preflight request doesn't pass access control check”. Määritä API:n CORS sallimaan täsmälleenhttps://omasovellus.fija esikatselun origin, sallia GET, POST, PATCH ja DELETE Content-Type- ja Authorization-otsikoilla, käsitellä OPTIONS ennen tunnistautumista ja sisällyttää CORS-otsikot myös virhevastauksiin.
Vaihe 4: Käsittele evästeet ja tunnistetiedot
Jos frontendisi lähettää evästeitä (esimerkiksi kirjautumisistuntoa) toiseen originiin, molempien osapuolten on oltava samaa mieltä:
- Frontend asettaa
credentials: "include"fetch-kutsuun taiwithCredentials: trueaxiosissa. - Palvelin lähettää
Access-Control-Allow-Credentials: true. - Palvelimen
Access-Control-Allow-Originon oltava tarkka origin, ei*.
Evästeet eri sivustojen välillä tarvitsevat myös SameSite=None; Secure-asetuksen, ja jotkut selaimet rajoittavat kolmannen osapuolen evästeitä vielä enemmän. Se on yksi lisäsyy suosia Vaiheen 5 lähestymistapaa.
Vaihe 5: Vältä CORS samalla originilla
Usein puhtain korjaus on olla tekemättä domainien välisiä pyyntöjä lainkaan. Tarjoa API samasta originista kuin sivu, esimerkiksi osoitteessa https://omasovellus.fi/api/...:
- Kehityksessä useimmat kehityspalvelimet voivat välittää pyyntöjä. Viten
server.proxy-asetus voi ohjata/apitakapäähän toisessa portissa, jolloin selain puhuu aina vain yhdelle originille. - Tuotannossa reititä
/apitakapäähän hostin rewrite- tai proxy-asetuksilla, tai tarjoa frontend ja API yhdeltä palvelimelta.
Frontend kutsuu sitten suhteellista polkua kuten fetch("/api/orders"). Ei domainien välistä pyyntöä, ei originien välistä esilentoa eikä evästeongelmia. Se tarkoittaa myös, ettei API-domainia tarvitse kovakoodata, ja se eroaa esikatselun ja tuotannon välillä.
Muuta frontend kutsumaan takapäätä suhteellisilla /api-poluilla täydellisen URL-osoitteen sijaan, ja aseta kehityksen välityspalvelin ohjaamaan /api API-palvelimelle. Poista sen jälkeen CORS-asetukset, joita emme enää tarvitse.
Mitä ei kannata tehdä
mode: "no-cors"fetch-kutsussa. Se ei ohita mitään; se antaa koodillesi tyhjän, lukukelvottoman vastauksen.- Selainlaajennukset, jotka poistavat CORSin käytöstä. Ne muuttavat vain omaa selaintasi. Jokainen kävijä näkee yhä virheen.
- Julkiset ”CORS-välityspalvelut” oikeille sovelluksille. Ne voivat lukea ja muuttaa kaikkea niiden kautta kulkevaa, ja ne menevät välillä alas.
Access-Control-Allow-Origin: *API:ssa, joka käyttää kirjautumista. Se ei toimi tunnistetietojen kanssa, ja se on väärä oletus yksityiselle datalle.- Minkä tahansa
Origin-otsikon heijastaminen takaisin tunnistetietojen sallimisen kanssa. Se antaa minkä tahansa web-sivun tehdä kirjautuneita pyyntöjä käyttäjiesi puolesta. Käytä sallittujen listaa.
Yleisiä syitä tekoälyllä rakennetuissa sovelluksissa
| Tilanne | Korjaus |
|---|---|
| Frontend kutsuu kolmannen osapuolen API:a salaisella avaimella | Siirrä kutsu takapäähän |
| Toimii esikatselussa, epäonnistuu julkaistulla domainilla | Lisää julkaistu ja oma domain originien listalle, tai käytä suhteellisia /api-polkuja |
| Virhe vain POST-, PUT- tai DELETE-pyynnöissä | Esilentoa ei käsitelty; lisää OPTIONS-käsittely ja sallitut otsikot |
| Virhe ilmestyi kirjautumisen lisäämisen jälkeen | Tunnistetiedot vaativat tarkan originin ja Allow-Credentials-asetuksen |
| ”CORS-virhe”, mutta Network-välilehdellä 500 | Korjaa palvelinvirhe ensin |
API-osoite kovakoodattu localhost-osoitteeseen | Käytä suhteellisia polkuja tai ympäristökohtaista asetusta |
CORS Mythexissä
Kun Mythex-projektissa on sekä verkkosivusto että API-palvelin, molemmat toimivat palveluina samassa projektissa, ja niiden välillä voi vaihtaa esikatselussa. Kun pyydät agenttia tekemään frontendin kutsumaan takapäätä suhteellisen /api-polun kautta, joka välitetään kehityksessä, vältät useimmat CORS-ongelmat. Jos tarvitset todella domainien välisiä kutsuja, anna agentille tarkka virhe konsolista ja kyseiset originit. Tarkista tulos myös julkaistusta sovelluksesta, koska sen osoite on eri kuin esikatselun. Katso Monipalveluiset sovellukset ja API-takapäät dokumentaatiosta sekä oppaamme tekoälyllä rakennetun sovelluksen virheenkorjauksesta ja frontend vs. backend.
CORS-tarkistuslista
- Luettu koko konsolivirhe ja epäonnistuneen pyynnön tilakoodi
- Suljettu pois piilossa oleva 404 tai 500
- Salaisen avaimen API:t kutsutaan takapäästä, ei selaimesta
- Palvelin lähettää
Access-Control-Allow-Origin-otsikon tarkoilla sallituilla originilla - OPTIONS-esilento vastataan sallituilla metodeilla ja otsikoilla, ennen tunnistautumista
- CORS-otsikot ovat mukana myös virhevastauksissa
- Tunnistetiedot: tarkka origin,
Allow-Credentials: trueja oikeat evästeasetukset - Esikatselun, julkaistun ja oman domainin originit kaikki katettu tai käytetty suhteellisia
/api-polkuja - Ei
no-cors-asetusta, julkisia välityspalveluja tai kaiken heijastavia originijärjestelyjä
Kysymykset
Mitä CORS-virhe tarkoittaa?
Sivusi, joka latautui yhdestä originista, yritti lukea vastauksen toisesta originista, eikä sen palvelimen vastaus sisältänyt sallivia otsikoita. Selain estää koodiasi lukemasta vastausta. Korjaus tehdään palvelimella tai siinä, miten pyyntö reititetään, ei frontend-koodissa.
Voinko korjata CORS-virheen frontendistä?
Ei kunnolla. Asetukset kuten mode: 'no-cors' vain piilottavat vastauksen koodiltasi. Korjaat sen saamalla palvelimen lähettämään oikean Access-Control-Allow-Origin-otsikon tai kutsumalla API:a omalta takapäältäsi tai saman originin välityspalvelimen kautta.
Onko Access-Control-Allow-Origin: * turvallinen?
Se on sopiva julkiselle datalle, jota kuka tahansa saa lukea, kuten julkiselle API:lle ilman kirjautumista. Sitä ei voi käyttää evästeiden tai muiden tunnistetietojen kanssa, ja yksityisille API:ille sinun kannattaa listata tarkat sallitut originit.
Miksi pyyntö toimii Postmanissa tai curlissa mutta ei selaimessa?
CORS-tarkistus tehdään vain selaimissa. Työkalut kuten Postman ja curl eivät sovella sitä, joten pyyntö voi onnistua siellä ja silti estyä, kun sivun JavaScript tekee sen.
Mikä on esilento-pyyntö (preflight)?
Pyynnöille, jotka eivät ole yksinkertaisia, kuten JSON-POST tai pyyntö, jossa on Authorization-otsikko, selain lähettää ensin OPTIONS-pyynnön ja kysyy palvelimelta, mitkä metodit ja otsikot ovat sallittuja. Jos tuo OPTIONS-pyyntö epäonnistuu tai siitä puuttuvat oikeat otsikot, varsinaista pyyntöä ei lähetetä ollenkaan.