Mundarija (42)
- Bu darsda
- 1. Nega bu kerak?
- 2. Origin: kodingiz qayerdan ishlayapti?
- 2.1 Qisqa takrorlash
- 2.2 Bizning origin'larimiz
- 3. Haqiqiy CORS xatosi
- 3.1 Yopiq endpoint
- 3.2 Xabarni bo'laklab o'qiymiz
- 3.3 So'rov serverga yetib bordimi?
- 3.4 Node'da CORS yo'q
- 4. Brauzer qanday qaror qiladi
- 5. Oddiy so'rov va preflight
- 5.1 Qaysi so'rov "oddiy"?
- 5.2 Chrome'da sinab ko'rdik
- 5.3 Preflight javobi
- 6. Preflight xatolari
- 7. credentials: "include" — cookie bilan so'rov
- 7.1 Qoida
- 7.2 Mashq API'sida sinaymiz
- 8. mode: no-cors va same-origin
- 8.1 no-cors — tuzatish emas
- 8.2 same-origin — begonani taqiqlash
- 9. CORS va CSP — ikki xil to'siq
- 10. CORS xatosini qanday hal qilish kerak
- 10.1 Frontend kodida — hech qanday yo'l bilan
- 10.2 Dev proxy
- 10.3 O'z serveringiz orqali
- 11. CORS xabarlari — qisqa lug'at
- 12. Hujumchi nigohi
- 13. Ko'p uchraydigan xatolar
- 13.1 CORS'ni frontend kodida tuzatishga urinish
- 13.2 Node'da sinab, "brauzerda ham ishlaydi" deb o'ylash
- 13.3 Faqat Failed to fetch ga qarash
- 13.4 Preflight'ni unutish
- 13.5 Keraksiz sarlavha preflight chaqiradi
- 14. Mashqlar
- 1-mashq (oson): Preflight bo'ladimi?
- 2-mashq (o'rta): Xabarni o'qing
- 3-mashq (qiyin): CORS'mi yoki tarmoqmi?
- 15. Real ishda
- Xulosa
- Manbalar
CORS xatosi: fetch'da origin, preflight va credentials — mijoz tomonidan
Qisqacha: Brauzer boshqa origin'ga so'rovni yuboradi, lekin javobni kodingizga faqat server ruxsat bersa beradi —
Access-Control-Allow-Originsarlavhasi bilan. Ruxsat bo'lmasa,fetchTypeError: Failed to fetchbilan rad etiladi, haqiqiy sabab esa faqat DevTools konsolida yoziladi. JSON,PUT/DELETEyoki maxsus sarlavhali so'rovdan oldin brauzerOPTIONSbilan preflight yuboradi. CORS xatosini frontend kodi bilan tuzatib bo'lmaydi — tuzatish joyi server yoki proxy.
Bu darsda
- Kodingiz qaysi origin'dan ishlayotganini bilasiz — natija oynasida u nega
null. - CORS xatosini DevTools'da o'qib, sababini aniq ayta olasiz.
- Qaysi so'rov oddiy, qaysi biri preflight talab qilishini oldindan ayta olasiz.
credentials: "include",mode: "no-cors"vamode: "same-origin"nima berishini haqiqiy natijalardan bilasiz.- CORS va CSP bloklashini farqlaysiz va dev proxy g'oyasini tushunasiz.
Oldin bilishingiz kerak: Origin va Same-Origin Policy, fetch asoslari, fetch bilan ma'lumot yuborish, Request, Response, Headers va fetch opsiyalari.
1. Nega bu kerak?
Sardor yangi API bilan ishlamoqda. Node'da kod a'lo ishlaydi: node test.mjs — javob keldi. Xuddi shu kodni sahifaga qo'ydi va Live Server'da ochdi. Konsolda qizil yozuv, fetch esa TypeError: Failed to fetch beradi. Sardor kodni o'n marta qayta yozadi — natija bir xil.
Bu — frontend dasturchisining eng mashhur "dushmani": CORS xatosi. Uning g'oyasini Origin va Same-Origin Policy darsida o'rgangan edik: brauzer bir origin'dagi skriptga boshqa origin javobini o'qishni taqiqlaydi, server esa CORS sarlavhalari bilan ruxsat beradi.
U darsda biz brauzerni curl bilan "o'ynagan" edik. Endi fetch qo'limizda — xatoni haqiqiy brauzerda o'zimiz chaqiramiz, o'qiymiz va har bir turini ajratamiz. Mashq API'sida buning uchun ikkita maxsus endpoint bor:
| Endpoint | CORS ruxsati |
|---|---|
GET /api/mashq/cors/ochiq |
bor: Access-Control-Allow-Origin: * |
GET /api/mashq/cors/yopiq |
yo'q — javobda ruxsat sarlavhasi umuman yo'q |
2. Origin: kodingiz qayerdan ishlayapti?
2.1 Qisqa takrorlash
Origin — uch qismdan iborat manzil "kimligi": protokol + domen + port. https://ilmhamroh.uz va http://127.0.0.1:5500 — ikki xil origin. Uch qismdan bittasi farq qilsa ham — boshqa origin. Same-Origin Policy (SOP) — brauzerning asosiy qoidasi: skript boshqa origin'ga so'rov yuborishi mumkin, lekin javobni o'qishi uchun ruxsat kerak.
So'rov qaysi origin'dan ketayotganini brauzer o'zi Origin sarlavhasiga yozadi — kodingiz uni o'zgartira olmaydi.
2.2 Bizning origin'larimiz
Bu kursda kodingiz to'rt xil joyda ishlaydi:
| Qayerda | Origin |
|---|---|
| Live Server | http://127.0.0.1:5500 |
| GitHub Pages | https://<login>.github.io |
| Saytdagi natija oynasi | null |
| Node | origin yo'q, CORS yo'q |
Natija oynasining origin'ini o'zingiz tekshiring:
<p>Konsolga qarang.</p>
<script>
console.log("Origin:", self.origin);
async function ochiqniSora() {
const url = "https://ilmhamroh.uz/api/mashq/cors/ochiq";
const javob = await fetch(url);
const malumot = await javob.json();
console.log(javob.status, javob.type, malumot.xabar);
}
ochiqniSora();
</script>Konsolda:
Origin: null
200 cors CORS ruxsat berilganself.origin — joriy sahifaning origin'i. Natija oynasi — sandbox'li (izolyatsiya qilingan) iframe: sayt uni ataylab hech qaysi origin'ga bog'lamaydi. Shunda siz yozgan kod IlmHamroh saytining cookie'lari va ma'lumotlariga tega olmaydi. Brauzer bunday "hech kimniki" origin'ni null deb yozadi.
null ham haqiqiy origin — CORS unga ham to'liq ishlaydi. cors/ochiq javobi keldi: type: "cors" — "boshqa origin'dan, ruxsat bilan" (Response turlari). Server Access-Control-Allow-Origin: * qaytardi — "hamma origin'ga, null ga ham ruxsat".
3. Haqiqiy CORS xatosi
3.1 Yopiq endpoint
Endi ruxsatsiz endpoint'ni so'raymiz. Bu blok — xato ataylab chiqariladi:
<p>Konsolga qarang. To'liq xabar — DevTools konsolida (F12).</p>
<script>
async function yopiqniSora() {
const url = "https://ilmhamroh.uz/api/mashq/cors/yopiq";
try {
await fetch(url);
console.log("Javob keldi");
} catch (xato) {
console.log("Ushlandi:", xato.name, "—", xato.message);
}
}
yopiqniSora();
</script>Konsolda:
Ushlandi: TypeError — Failed to fetchNatija konsolida — faqat TypeError: Failed to fetch. Bu fetch asoslari dagi tarmoq xatosi bilan bir xil xabar. Kod internet uzildimi yoki CORS bloklandimi — farqlay olmaydi.
Haqiqiy sababni brauzer DevTools konsoliga yozadi. Sahifada F12 ni bosing — Chrome 154 da natija oynasi uchun aynan shunday:
Access to fetch at 'https://ilmhamroh.uz/api/mashq/cors/yopiq' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.Live Server'dan ishga tushirsangiz — faqat origin o'zgaradi:
Access to fetch at 'https://ilmhamroh.uz/api/mashq/cors/yopiq' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.3.2 Xabarni bo'laklab o'qiymiz
| Bo'lak | Ma'nosi |
|---|---|
Access to fetch at '...' |
qaysi manzilga fetch |
from origin 'null' |
qaysi origin'dan |
has been blocked by CORS policy |
CORS siyosati to'sdi |
No 'Access-Control-Allow-Origin' header ... |
sabab: javobda ruxsat sarlavhasi yo'q |
Butun tarjima: "null origin'idan .../cors/yopiq ga fetch so'rovi CORS siyosati bilan bloklandi: so'ralgan resursda Access-Control-Allow-Origin sarlavhasi yo'q." Eng muhim qism — ikki nuqtadan keyingisi. CORS xatolarining hammasi bir xil boshlanadi, sabab esa oxirida. Bu darsda yana to'rt xil sababni ko'ramiz.
Uning ostida yana bitta qator chiqadi: Failed to load resource: net::ERR_FAILED. Bu — o'sha bloklashning oqibati, alohida xato emas.
3.3 So'rov serverga yetib bordimi?
Ha. DevTools → Network da yopiq qatorini toping. Status ustunida CORS error yozuvi turadi, lekin server javobi kelgan. Buni curl bilan ham ko'ramiz — Origin va Same-Origin Policy darsidagidek, Origin sarlavhasini qo'lda qo'shib:
curl -i https://ilmhamroh.uz/api/mashq/cors/yopiq \
-H "Origin: http://127.0.0.1:5500"Natija (qisqartirilgan):
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"xabar":"Bu javobni brauzer sizga ko'rsatmaydi"}Server 200 va tanani berdi. Faqat Access-Control-Allow-Origin yo'q. cors/ochiq ga xuddi shu buyruq esa Access-Control-Allow-Origin: * ni ham qaytaradi. Brauzer javobni oldi, sarlavhalarini tekshirdi, ruxsat topmadi — va javobni kodingizdan yashirdi.
3.4 Node'da CORS yo'q
Sardorning muammosini eslang: Node'da hammasi ishlagan edi. Tekshiramiz:
async function nodeDan() {
const url = "https://ilmhamroh.uz/api/mashq/cors/yopiq";
const javob = await fetch(url);
const malumot = await javob.json();
console.log(javob.status, malumot.xabar);
}
nodeDan();Konsolda:
200 Bu javobni brauzer sizga ko'rsatmaydiNode javobni bemalol o'qidi. CORS — brauzer qoidasi. U foydalanuvchini himoya qiladi: brauzerda foydalanuvchining cookie'lari, kirish sessiyalari bor; begona sayt ularning nomidan so'rov yuborib, javobni o'g'irlamasin. Node'da, curl da, Postman'da (API'ni qo'lda sinash dasturi) bunday "foydalanuvchi" yo'q — himoya qiladigan narsa ham yo'q.
Tekshirib ko'ring: Nega brauzer CORS xatosining sababini
xato.messagega yozmaydi, faqat DevTools'ga?
Javob
Xavfsizlik uchun. Agar kod sababni o'qiy olsa, begona sayt foydalanuvchi brauzeri orqali "bu manzilda server bormi, u nima javob berdi" deb boshqa tarmoqlarni (masalan, ofisdagi ichki serverlarni) tekshirib chiqa olardi. DevTools'ni esa faqat foydalanuvchining o'zi ko'radi.
4. Brauzer qanday qaror qiladi
Har bir boshqa origin'ga ketgan fetch uchun brauzer shu yo'ldan o'tadi:
flowchart TD
A["fetch boshqa origin'ga"] --> B{"Oddiy so'rovmi?"}
B -->|"yo'q"| P["Preflight: OPTIONS"]
P --> Q{"Metod va sarlavhalarga<br/>ruxsat bormi?"}
Q -->|"yo'q"| X["CORS xatosi<br/>(asosiy so'rov ketmaydi)"]
Q -->|"ha"| S["Asosiy so'rov"]
B -->|"ha"| S
S --> C{"Javobda Allow-Origin<br/>mos keladimi?"}
C -->|"ha"| OK["Javob kodga beriladi"]
C -->|"yo'q"| X2["CORS xatosi<br/>(javob yashiriladi)"]Sxemaga qarang: CORS xatosi ikki joyda chiqishi mumkin. Preflight da — unda asosiy so'rov umuman yuborilmaydi. Javobda — unda so'rov ketgan, server uni bajargan, faqat javob yashirilgan. cors/yopiq — ikkinchi holat.
5. Oddiy so'rov va preflight
5.1 Qaysi so'rov "oddiy"?
Oddiy so'rov (simple request) — oddiy HTML forma ham yubora oladigan so'rov. Brauzer uni darhol yuboradi. Shart — uchalasi ham bajarilsin:
| Shart | Ruxsat etilgani |
|---|---|
| Metod | GET, HEAD, POST |
| Sarlavhalar | faqat Accept, Accept-Language, Content-Language, Content-Type (+ Range) |
Content-Type qiymati |
text/plain, application/x-www-form-urlencoded, multipart/form-data |
Bittasi buzilsa — so'rov "oddiy emas" va brauzer avval preflight (uchishdan oldingi tekshiruv) yuboradi: OPTIONS metodi bilan "shunday so'rov yuborsam maylimi?" deb so'raydi.
Diqqat: Content-Type: application/json — oddiy emas. Demak, fetch bilan ma'lumot yuborish dagi har bir JSON POST preflight bilan ketgan.
5.2 Chrome'da sinab ko'rdik
Natija oynasidan aks ga oltita so'rov yubordik va Chrome qaysi biriga OPTIONS qo'shganini kuzatdik (Chrome 154):
| So'rov | Preflight |
|---|---|
GET |
yo'q |
POST, tana — satr (text/plain) |
yo'q |
POST, tana — URLSearchParams |
yo'q |
POST, Content-Type: application/json |
bor |
DELETE |
bor |
GET + Authorization sarlavhasi |
bor |
Natija «Qaysi so'rov "oddiy"?» bo'limidagi qoidaga aynan mos keladi. Preflight bo'lgan har bir so'rov uchun Network'da ikkita qator ko'rasiz: preflight turidagi OPTIONS (status 204) va asosiy so'rov.
5.3 Preflight javobi
Brauzer yuboradigan preflight'ni curl bilan takrorlaymiz — JSON POST dan oldingi so'rov:
curl -i -X OPTIONS https://ilmhamroh.uz/api/mashq/bronlar \
-H "Origin: http://127.0.0.1:5500" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: content-type"Mashq serveri javobi (qisqartirilgan):
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS
Access-Control-Allow-Headers: Content-Type,Authorization,X-Sinov,Last-Event-ID
Access-Control-Max-Age: 600
Access-Control-Expose-Headers: Location,X-Jami,X-Sorov-IdQatorma-qator:
Allow-Methods— qaysi metodlar mumkin.POSTbor — ruxsat.Allow-Headers— qaysi qo'shimcha sarlavhalar mumkin.Content-Typebor — ruxsat. Ro'yxatda yo'q sarlavha bilan so'rov — xato (keyingi bo'limda).Max-Age: 600— "bu ruxsatni 600 soniya eslab qol". Live Server sahifasidan bir xil JSONPOSTni uch marta yubordik — ChromeOPTIONSni faqat birinchisidan oldin yubordi, qolgan ikkitasi keshdagi ruxsatdan foydalandi.Expose-Headers— javobning qaysi sarlavhalarini JavaScript o'qiy oladi. Oldingi darsda brauzerdaX-Jamiko'rindi,X-RateLimit-Limitesanulledi — sababi shu ro'yxat.
Tekshirib ko'ring:
fetch(url, { method: "POST", body: new FormData(forma) })preflight talab qiladimi?
Javob
Yo'q. Metod — POST, qo'lda sarlavha yo'q, fetch qo'yadigan Content-Type — multipart/form-data. Uchala shart ham bajarildi — oddiy so'rov. Agar unga Authorization sarlavhasi qo'shilsa — preflight paydo bo'ladi.
6. Preflight xatolari
Preflight muvaffaqiyatsiz bo'lsa, asosiy so'rov umuman ketmaydi. Uch xil holatni natija oynasida chaqiramiz. Har biri natija konsolida Failed to fetch, DevTools'da esa o'z sababi bilan chiqadi:
<p>Konsolga va DevTools konsoliga qarang.</p>
<script>
const API = "https://ilmhamroh.uz/api/mashq";
async function sina(nom, url, sozlama) {
try {
const javob = await fetch(url, sozlama);
console.log(nom, "→", javob.status);
} catch (xato) {
console.log(nom, "→", xato.message);
}
}
async function hammasi() {
await sina("X-Boshqa", `${API}/aks`, {
method: "POST",
headers: { "X-Boshqa": "1" },
});
await sina("patch", `${API}/aks`, { method: "patch" });
await sina("yopiq + X-Sinov", `${API}/cors/yopiq`, {
headers: { "X-Sinov": "1" },
});
}
hammasi();
</script>Konsolda:
X-Boshqa → Failed to fetch
patch → Failed to fetch
yopiq + X-Sinov → Failed to fetchDevTools konsolida Chrome 154 uchala sababni aytadi. Har birining faqat ikki nuqtadan keyingi qismini olamiz:
Request header field x-boshqa is not allowed by Access-Control-Allow-Headers in preflight response.
Method patch is not allowed by Access-Control-Allow-Methods in preflight response.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.- "
x-boshqasarlavhasiga preflight javobidagiAccess-Control-Allow-Headersruxsat bermaydi." Ro'yxatdaX-Sinovbor,X-Boshqayo'q. Tuzatish: server ro'yxatga qo'shsin — yoki sarlavha umuman kerakmi, o'ylab ko'ring. - "
patchmetodigaAccess-Control-Allow-Methodsruxsat bermaydi." Ro'yxatdaPATCHbor! Lekinfetchbilan ma'lumot yuborish darsidan eslang:fetchpatchni katta harfga aylantirmaydi, CORS esa metodni harfma-harf solishtiradi. Tuzatish:"PATCH". - "Preflight so'roviga javob tekshiruvdan o'tmadi:
Access-Control-Allow-Originsarlavhasi yo'q."cors/yopiqOPTIONSga umuman CORS javobi bermaydi.X-Sinovsarlavhasi so'rovni "oddiy emas" qildi — va xato preflight bosqichida chiqdi.
Uchinchi holat Origin va Same-Origin Policy darsidagi ogohlantirishning amaldagi ko'rinishi: "backend OPTIONS ga javob bermasa, asosiy so'rov serverga yetib bormaydi — dasturchi uni server logida behuda qidiradi".
7. credentials: "include" — cookie bilan so'rov
7.1 Qoida
fetch opsiyalari darsida aytdik: standart holatda ("same-origin") cookie boshqa origin'ga yuborilmaydi. credentials: "include" bilan yuboriladi — masalan, sayt app.example.com da, API api.example.com da, foydalanuvchi esa cookie bilan kirgan.
Lekin bunday so'rovga CORS qoidasi qattiqroq. Server javobida ikkalasi bo'lishi shart:
Access-Control-Allow-Origin— aniq origin (https://app.example.com),*emas;Access-Control-Allow-Credentials: true.
7.2 Mashq API'sida sinaymiz
Mashq API'si ataylab cookie ishlatmaydi va * qaytaradi. include bilan so'raymiz:
await fetch("https://ilmhamroh.uz/api/mashq/cors/ochiq", {
credentials: "include",
});TypeError: Failed to fetch, DevTools'da esa:
Access to fetch at 'https://ilmhamroh.uz/api/mashq/cors/ochiq' from origin 'null' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.Tarjimasi: "So'rovning credentials rejimi include bo'lganda, javobdagi Access-Control-Allow-Origin qiymati yulduzcha * bo'lmasligi kerak." Bir daqiqa oldin xuddi shu cors/ochiq muammosiz ishlagan edi. Farq — bitta opsiya.
Nega brauzer bunchalik qattiq? * — "istalgan sayt". include — "foydalanuvchining kirish ma'lumotlari bilan". Ikkalasi birga — istalgan sayt foydalanuvchi nomidan so'rov yuborib, javobini o'qiy oladi degani. Brauzer bunga yo'l qo'ymaydi.
Tuzatish joyi — server: aniq origin va Allow-Credentials: true. Frontendda esa include ni faqat haqiqatan cookie kerak bo'lganda yozing. Buni server tomondan CORS chuqur darsida sozlaymiz.
8. mode: no-cors va same-origin
8.1 no-cors — tuzatish emas
Internetdagi eng mashhur "maslahat": CORS xatosi chiqsa, mode: "no-cors" qo'shing. Haqiqiy natijani ko'ramiz:
const url = "https://ilmhamroh.uz/api/mashq/cors/yopiq";
const javob = await fetch(url, { mode: "no-cors" });
console.log(javob.type, javob.status, javob.ok);
console.log(JSON.stringify(await javob.text()));Chrome 154 da (natija oynasida ham, Live Server'da ham):
opaque 0 false
""Xato yo'qoldi — lekin ma'lumot ham. opaque (shaffof emas) javob: status 0, tana bo'sh satr, sarlavhalar yo'q. Server {"xabar": ...} yuborgan edi — kod uni hech qachon ko'rmaydi. no-cors "javobni o'qimayman, faqat yuboraman" degani. U faqat GET, HEAD, POST va oddiy sarlavhalar bilan ishlaydi.
Uning bitta foydali joyi bor: Service Worker'da begona rasm yoki skriptni keshlash. Va bitta qiziq ishlatilishi — 3-mashqda: "server umuman javob berdimi?" degan savolga javob.
8.2 same-origin — begonani taqiqlash
mode: "same-origin" — teskari qat'iylik: faqat o'z origin'ingizga. Live Server sahifasidan mashq API'siga:
Fetch API cannot load https://ilmhamroh.uz/api/mashq/menyu. Request mode is "same-origin" but the URL's origin is not same as the request origin http://127.0.0.1:5500.Tarjimasi: "So'rov rejimi same-origin, lekin URL origin'i so'rov origin'i bilan bir xil emas." Bu yerda so'rov umuman yuborilmadi — brauzer uni boshidayoq to'xtatdi. Bu opsiya kodingiz tasodifan begona serverga ma'lumot yubormasligiga kafolat sifatida ishlatiladi.
9. CORS va CSP — ikki xil to'siq
fetch asoslari darsida ogohlantirgan edik: natija oynasida fetch faqat https://ilmhamroh.uz ga ishlaydi. Bu CORS emas — CSP. Natija oynasida https://example.com ga fetch qilsangiz, DevTools'da boshqacha xabar chiqadi (qisqartirilgan):
Connecting to 'https://example.com/' violates the following Content Security Policy directive: "connect-src 'self' https://ilmhamroh.uz ...". The action has been blocked.Tarjimasi: "https://example.com/ ga ulanish quyidagi Content Security Policy qoidasini buzadi: connect-src ... Harakat bloklandi." Ikkalasi ham kodga bir xil Failed to fetch beradi, lekin mohiyati boshqa:
| CORS | CSP | |
|---|---|---|
| Kim qaror qiladi | server (javob sarlavhasida) | sahifa (o'z qoidasida) |
| So'rov ketadimi | ha (yoki preflight) | yo'q, umuman |
| Kimni himoya qiladi | serverdagi foydalanuvchi ma'lumotini | sahifaning o'zini (XSS'dan) |
| DevTools xabari | blocked by CORS policy |
violates ... Content Security Policy |
CSP — "bu sahifa faqat shu manzillarga ulanishi mumkin" degan sahifa qoidasi. IlmHamroh saytida u bor; sizning Live Server sahifangizda — yo'q. Shuning uchun boshqa API'larni Live Server'da sinang. CSP'ni Brauzer xavfsizlik modeli darsida o'rganamiz.
Tekshirib ko'ring: Natija oynasida
https://api.github.com/users/octocatgafetchqildingiz —Failed to fetch. Bu CORS mi yoki CSP mi? Qanday bilasiz?
Javob
CSP. DevTools konsolida violates the following Content Security Policy directive deb yoziladi, blocked by CORS policy emas. Network panelida esa so'rov serverga umuman ketmagan bo'ladi. Xuddi shu kod Live Server'da ishlaydi: u yerda sahifada CSP yo'q, GitHub API esa CORS ruxsatini beradi.
10. CORS xatosini qanday hal qilish kerak
10.1 Frontend kodida — hech qanday yo'l bilan
Bu darsning eng muhim gapi: CORS xatosini fetch kodini o'zgartirib tuzatib bo'lmaydi. mode: "no-cors", boshqa sarlavha, XMLHttpRequest (fetch dan oldingi eski so'rov usuli) yoki Axios — hech biri yordam bermaydi. Javobni brauzer yashiryapti, va u serverdan ruxsat kutyapti. To'g'ri yo'llar:
- Serverni sozlash — API sizniki yoki jamoangizniki bo'lsa. Server
Access-Control-Allow-Origin(va kerak bo'lsa boshqaAllow-*) sarlavhalarini qaytaradi. Express'da bunicorspaketi qiladi (CORS chuqur). - Dev proxy — ishlab chiqish paytida.
- O'z serveringiz orqali — begona API uchun.
10.2 Dev proxy
Ishlab chiqishda frontend http://localhost:5173 da, backend esa boshqa manzilda. Vite kabi vosita ichida proxy — "vositachi" server bor. Brauzer so'rovni o'z origin'iga yuboradi: fetch("/api/mashq/menyu"). Vite uni jimgina haqiqiy serverga uzatadi va javobni qaytaradi. Brauzer uchun hammasi bitta origin'dan — CORS umuman ishga tushmaydi.
// vite.config.js — Vite'ni 16-qismda o'rnatamiz
export default {
server: {
proxy: {
"/api": {
target: "https://ilmhamroh.uz",
changeOrigin: true,
},
},
},
};Vite — frontend loyihalarni yig'adigan vosita, uni Vite dev server darsida o'rnatamiz; hozir bilish shart emas. Hozir g'oyani biling: proxy faqat ishlab chiqish uchun. Saytni internetga chiqarganda proxy yo'q — u yerda baribir server CORS'ni sozlaydi yoki frontend va API bitta domenda turadi.
10.3 O'z serveringiz orqali
Begona API CORS ruxsati bermasa-chi (masalan, ob-havo xizmati faqat serverlar uchun)? Node'da CORS yo'qligini ko'rdik. Demak, o'z serveringiz begona API'dan ma'lumot oladi va frontendga o'z domeningizdan beradi. Bu usul maxfiy API kalitini ham brauzerdan yashiradi (fetch asoslari dagi "Hujumchi nigohi"). Bunday serverni backend qismlarida yozasiz.
Diqqat: Internetdagi "bepul CORS proxy" xizmatlari (
https://...proxy.../?url=...) — xavfli. Barcha so'rovlaringiz va javoblaringiz begona serverdan o'tadi, u ularni o'qishi va o'zgartirishi mumkin. Mashq uchun ham, ish uchun ham ishlatmang.
11. CORS xabarlari — qisqa lug'at
DevTools'dagi xabarning ikki nuqtadan keyingi qismiga qarang:
| Xabar bo'lagi | Sabab | Kim tuzatadi |
|---|---|---|
No 'Access-Control-Allow-Origin' header is present |
server ruxsat bermagan | server |
Request header field ... is not allowed |
sarlavha ruxsat ro'yxatida yo'q | server yoki siz (sarlavhani olib tashlang) |
Method ... is not allowed |
metod ruxsat etilmagan yoki kichik harfda | server yoki siz ("PATCH") |
Response to preflight request doesn't pass |
OPTIONS ga to'g'ri javob yo'q |
server |
must not be the wildcard '*' when ... 'include' |
cookie + * |
server (aniq origin) |
12. Hujumchi nigohi
1. Server har qanday Origin ni qaytaradi. Dasturchi "CORS ishlamayapti" deb serverga so'rovdagi Origin ni ko'r-ko'rona Access-Control-Allow-Origin ga yozadigan va Allow-Credentials: true qo'yadigan kod qo'ydi. Endi istalgan sayt foydalanuvchining cookie'si bilan so'rov yuborib, javobini o'qiy oladi. Qarshi chora: ruxsat berilgan origin'lar — aniq ro'yxat.
2. null origin'ga ruxsat. "Lokal fayllardan ham ishlasin" deb Access-Control-Allow-Origin: null qo'yish — xavfli. Bu darsda ko'rdik: null ni istalgan sandbox'li iframe oladi. Ya'ni hujumchi o'z sahifasidagi iframe'dan "ruxsat berilgan" origin bo'lib oladi. Qarshi chora: null ni hech qachon ruxsat ro'yxatiga qo'shmang.
3. "CORS meni himoya qiladi" xatosi. cors/yopiq misolida so'rov serverga yetib bordi va server uni bajardi — faqat javob yashirildi. Agar u "bronni o'chirish" so'rovi bo'lganida, bron o'chib bo'lardi. CORS javobni o'qishdan himoya qiladi, so'rovning bajarilishidan emas. Qarshi chora: server o'zgartiruvchi so'rovlarni autentifikatsiya va CSRF himoyasi bilan tekshiradi. CSRF — begona sayt foydalanuvchi nomidan uning cookie'si bilan so'rov yuboradigan hujum; uni backend qismida o'rganamiz (CSRF), hozir bilish shart emas.
13. Ko'p uchraydigan xatolar
13.1 CORS'ni frontend kodida tuzatishga urinish
no-cors, Access-Control-Allow-Origin ni so'rov sarlavhasiga qo'shish (u faqat javobda ma'noli), boshqa kutubxona — hech biri ishlamaydi. Tuzatish: server, dev proxy yoki o'z serveringiz.
13.2 Node'da sinab, "brauzerda ham ishlaydi" deb o'ylash
Node CORS'ni tekshirmaydi. Tuzatish: brauzer kodini brauzerda sinang — Live Server yoki natija oynasida.
13.3 Faqat Failed to fetch ga qarash
Kod CORS'ni tarmoq xatosidan ajrata olmaydi. Tuzatish: DevTools konsolidagi to'liq xabarni o'qing — sabab ikki nuqtadan keyin.
13.4 Preflight'ni unutish
Server POST /bronlar ni yozgan, lekin OPTIONS ga javob bermaydi. JSON so'rov preflight'da to'xtaydi. Tuzatish: server OPTIONS ga CORS sarlavhalari bilan javob bersin (CORS paketlari buni o'zi qiladi).
13.5 Keraksiz sarlavha preflight chaqiradi
Sardor har so'rovga X-Ilova-Versiya qo'shdi — endi hatto oddiy GET ham ikki so'rovga aylandi va server ro'yxatida bu sarlavha yo'q. Tuzatish: maxsus sarlavhalarni faqat kerak bo'lganda qo'shing.
14. Mashqlar
1-mashq (oson): Preflight bo'ladimi?
Har bir so'rov uchun "oddiy" yoki "preflight" deb javob bering. Keyin natija oynasida yoki Live Server'da DevTools → Network bilan tekshiring.
fetch(url)fetch(url, { method: "POST", body: "osh" })fetch(url, { method: "PUT", body: "osh" })fetch(url, { headers: { Accept: "application/json" } })fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: "{}" })
Yechim
- Oddiy —
GET, sarlavhasiz. - Oddiy —
POST,Content-Type: text/plain(satr tanasi uchunfetcho'zi qo'yadi). - Preflight —
PUToddiy metodlar ro'yxatida yo'q. - Oddiy —
Acceptruxsat etilgan sarlavhalardan biri. - Preflight —
application/jsonoddiyContent-Typeqiymatlaridan emas.
Eng ko'p xato 5-savolda bo'ladi: kundalik JSON POST — doim preflight bilan.
2-mashq (o'rta): Xabarni o'qing
Sardor DevTools'da shu xabarni ko'rdi:
Access to fetch at 'https://api.example.com/buyurtmalar' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.Uch savolga javob bering: (a) so'rov qaysi origin'dan qaysi manzilga ketdi? (b) Asosiy so'rov serverga yetib bordimi? (c) Muammo qayerda va kim tuzatadi?
Yechim
(a) http://127.0.0.1:5500 (Live Server) dan https://api.example.com/buyurtmalar ga.
(b) Yo'q. Xabarda preflight response bor — xato OPTIONS bosqichida chiqdi, asosiy so'rov yuborilmadi.
(c) So'rovda Authorization sarlavhasi bor (kirish tokeni), server esa uni Access-Control-Allow-Headers ro'yxatiga qo'shmagan. Tuzatish — serverda: ro'yxatga Authorization ni qo'shish. Frontend tokenni sarlavhasiz yubora olmaydi — u kerak. Token bilan so'rovlarni Autentifikatsiyali so'rovlar darsida yozamiz; mashq API'si Authorization ga ruxsat beradi.
3-mashq (qiyin): CORS'mi yoki tarmoqmi?
Kod Failed to fetch dan sababni bilmaydi. Lekin bitta hiyla bor: oddiy fetch muvaffaqiyatsiz bo'lsa, xuddi shu manzilga mode: "no-cors" bilan qayta so'rang. opaque javob kelsa — server javob bergan, demak muammo CORS ruxsatida. U ham rad etilsa — javob umuman olinmagan. corsniTekshir(url) funksiyasini yozing va uchta manzil bilan sinang: cors/ochiq, cors/yopiq, https://nomalum.example/menyu. Natija oynasida ishlating va kodni kurs/mashqlar/11/20-cors/tekshir.html ga saqlang.
Ishora: ichma-ich try/catch; catch da xato o'zgaruvchisi kerak bo'lmasa, catch { ... } deb qavssiz yozish mumkin (try / catch / finally).
Yechim
<p>Konsolga qarang.</p>
<script>
async function corsniTekshir(url) {
try {
const javob = await fetch(url);
return `ruxsat bor (${javob.status})`;
} catch {
try {
await fetch(url, { mode: "no-cors" });
return "server javob berdi, lekin CORS ruxsati yo'q";
} catch {
return "javob umuman olinmadi";
}
}
}
async function hammasi() {
const API = "https://ilmhamroh.uz/api/mashq";
const manzillar = [
`${API}/cors/ochiq`,
`${API}/cors/yopiq`,
"https://nomalum.example/menyu",
];
for (const url of manzillar) {
const nom = url.split("/").pop();
console.log(nom, "→", await corsniTekshir(url));
}
}
hammasi();
</script>Konsolda:
ochiq → ruxsat bor (200)
yopiq → server javob berdi, lekin CORS ruxsati yo'q
menyu → javob umuman olinmadiyopiq uchun no-cors so'rovi opaque javob bilan bajarildi — server bor va javob berdi. nomalum.example uchun ikkala so'rov ham rad etildi. Natija oynasida uni sayt CSP'si to'xtatadi, Live Server'da esa domen topilmaydi (net::ERR_NAME_NOT_RESOLVED) — ikkala holatda ham "javob olinmadi". Bu hiyla faqat GET uchun va faqat tashxis uchun: no-cors javobidan ma'lumot baribir olinmaydi.
git add 11/20-cors/tekshir.html
git commit -m "11/20: CORS va tarmoq xatosini ajrat"15. Real ishda
- Har bir frontend dasturchi CORS bilan birinchi haftasida uchrashadi: frontend
localhost:5173, backendlocalhost:3000— ikki origin. Jamoada odatiy yechim: ishlab chiqishda Vite proxy, production'da frontend va API bitta domenda (example.comvaexample.com/api) yoki serverda aniq origin ro'yxati. - Backend dasturchi CORS'ni sozlaydi: Express'da
corspaketi, NestJS'daapp.enableCors(). Mashq API'si NestJS'da aynan shunday sozlangan: hamma yo'llar ochiq, faqatcors/yopiq— ruxsatsiz. - Intervyu. "CORS nima va uni kim tuzatadi?", "Preflight qachon yuboriladi?", "
no-corsnima qiladi?" — frontend intervyularining doimiy savollari. Bu darsdagi jadvallar — tayyor javoblar.
Xulosa
- CORS — brauzer qoidasi: boshqa origin javobi kodga faqat server
Access-Control-Allow-Originbilan ruxsat bersa beriladi. Node,curl— CORS'siz. - Kod faqat
TypeError: Failed to fetchni ko'radi; sabab DevTools konsolida, ikki nuqtadan keyin. - Oddiy so'rov:
GET/HEAD/POST+ oddiy sarlavhalar + uch xilContent-Type. Qolgani — avvalOPTIONSpreflight;Max-Ageuni keshlaydi. credentials: "include"+*— har doim xato: server aniq origin vaAllow-Credentials: trueqaytarishi kerak.no-cors— tuzatish emas: javobopaque, status0, tana bo'sh.- CSP — sahifaning o'z qoidasi, CORS — serverning ruxsati. Tuzatish joyi: server, dev proxy yoki o'z serveringiz; frontend kodi emas.
Keyingi dars: Streams API va javobni oqim bilan o'qish — katta yoki asta keladigan javobni oxirini kutmasdan, bo'lakma-bo'lak o'qish: yuklash progressi va AI chatlaridagi "yozilayotgan" javoblar.
Manbalar
- MDN: "Cross-Origin Resource Sharing (CORS)", "CORS errors", "Request: mode property" — developer.mozilla.org
- WHATWG Fetch Standard: "CORS protocol", "CORS-safelisted request-header", "CORS-preflight fetch" — fetch.spec.whatwg.org
- Vite hujjatlari: "server.proxy" — vite.dev/config/server-options
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!