Cara Memperbaiki Error CORS (dan Mengapa Itu Terjadi)
Error CORS berarti halaman web kamu mencoba membaca respons dari origin lain (domain, port, atau protokol yang berbeda), dan server itu tidak mengirim header yang menyatakan bahwa hal tersebut diizinkan. Browser memblokir respons demi melindungi pengguna. Kamu memperbaikinya di server, dengan mengembalikan header Access-Control-Allow-Origin untuk origin situsmu dan menangani request preflight OPTIONS, atau kamu menghindarinya dengan mengirim request lewat back end sendiri di origin yang sama.
Ini termasuk error yang paling membingungkan dalam pengembangan web, karena request sering kali sampai ke server dengan baik. Panduan ini menjelaskan apa yang terjadi dan cara memperbaiki setiap variannya.
Apa arti “origin”
Origin adalah kombinasi protokol, domain, dan port:
| URL | Origin |
|---|---|
https://myapp.com/dashboard | https://myapp.com |
https://api.myapp.com/users | https://api.myapp.com (subdomain berbeda, jadi origin berbeda) |
http://localhost:5173 | http://localhost:5173 |
http://localhost:3000 | http://localhost:3000 (port berbeda, jadi origin berbeda) |
Browser mengikuti same-origin policy: JavaScript di halaman bebas membaca respons dari origin-nya sendiri, tetapi tidak dari origin lain. CORS (Cross-Origin Resource Sharing) adalah sistem yang memungkinkan server memilih untuk ikut serta: “respons dari saya boleh dibaca oleh halaman dari origin-origin ini.”
Dua konsekuensi yang membuat orang terkejut:
- Request sering kali sampai ke server. CORS biasanya memblokir kode kamu agar tidak bisa membaca respons, bukan mencegah server menerima request. Sebuah POST mungkin sudah tersimpan meski kamu melihat error.
- Hanya browser yang menerapkannya. curl, Postman, dan kode sisi server mengabaikan CORS sepenuhnya. Itu sebabnya “berfungsi di Postman” tidak memberi tahu apa pun tentang CORS.
Langkah 1: Baca error persisnya
Buka developer tools (klik kanan → Inspect), pilih tab Console, dan baca pesan lengkapnya. Kalimat Chrome menunjukkan masalah yang kamu hadapi:
| Pesan mengandung | Yang salah |
|---|---|
No 'Access-Control-Allow-Origin' header is present | Server tidak mengirim header sama sekali, atau request gagal sebelum mencapai kode CORS-mu (misalnya 404 atau 500) |
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin | Server mengizinkan origin yang berbeda dari origin-mu |
Response to preflight request doesn't pass access control check | Preflight OPTIONS gagal |
...must not be the wildcard '*' when the request's credentials mode is 'include' | Kamu mengirim cookie, dan server membalas dengan * |
Request header field authorization is not allowed | Server tidak mencantumkan header itu di Access-Control-Allow-Headers |
Lalu buka tab Network, cari request yang gagal (dan request OPTIONS sebelumnya jika ada), dan lihat status code serta header respons-nya.
Periksa status code lebih dulu. Banyak “error CORS” sebenarnya adalah error server yang menyamar. Jika server crash atau mengembalikan 404, respons error-nya sering kali tidak memiliki header CORS, sehingga browser melaporkan CORS alih-alih masalah yang sebenarnya. Perbaiki 500 atau 404-nya, dan error CORS mungkin ikut hilang.
Langkah 2: Putuskan apakah API itu sebaiknya dipanggil dari browser
Sebelum menambahkan header, tanyakan: apakah browser memang seharusnya memanggil API ini secara langsung?
- API pihak ketiga yang membutuhkan kunci rahasia (OpenAI, kunci secret Stripe, sebagian besar layanan email) tidak boleh dipanggil dari browser. Kuncinya akan terlihat oleh setiap pengunjung. Panggil dari back end kamu, dan masalah CORS hilang, karena request server-ke-server tidak tunduk pada CORS. Lihat cara menjaga kunci API tetap aman.
- API pihak ketiga yang tidak kamu kendalikan dan tidak mengirim header CORS tidak bisa diperbaiki dari sisimu. Panggil dari back end kamu.
- API milikmu sendiri bisa diperbaiki dengan mengonfigurasinya dengan benar. Lanjutkan di bawah.
Langkah 3: Perbaiki di server kamu
Server harus menambahkan header yang tepat pada setiap respons, termasuk respons error.
Untuk request sebenarnya, kirim:
Access-Control-Allow-Origin: https://myapp.com(origin frontend persis, tanpa trailing slash)Vary: Origin, jika nilainya bergantung pada origin mana yang meminta
Untuk request preflight OPTIONS, balas dengan status sukses (200 atau 204) dan:
Access-Control-Allow-Origin: https://myapp.comAccess-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETEAccess-Control-Allow-Headers: Content-Type, Authorization(setiap header kustom yang kamu kirim)- Opsional
Access-Control-Max-Age: 600, agar browser menyimpan preflight di cache untuk beberapa waktu
Kebanyakan framework punya paket atau pengaturan untuk ini. Di Express, paket cors; di FastAPI, CORSMiddleware; di ASP.NET Core, AddCors; di Spring, @CrossOrigin atau konfigurasi CORS. Contoh pengaturan Express yang umum:
import cors from "cors";
app.use(cors({
origin: ["https://myapp.com", "http://localhost:5173"],
credentials: true,
}));
Letakkan penanganan CORS sebelum route dan autentikasi kamu, agar request preflight (yang tidak membawa login) tidak ditolak dengan 401.
Dengan pembuat aplikasi AI, jelaskan setup-nya dengan tepat:
Frontend di
https://myapp.commemanggil API dihttps://api.myapp.comdan mendapat "Response to preflight request doesn't pass access control check". Konfigurasi CORS di API agar hanya mengizinkanhttps://myapp.comdan origin pratinjau, izinkan GET, POST, PATCH, DELETE dengan header Content-Type dan Authorization, tangani OPTIONS sebelum autentikasi, dan sertakan juga header CORS pada respons error.
Langkah 4: Tangani cookie dan kredensial
Jika frontend kamu mengirim cookie (misalnya sesi login) ke origin lain, kedua sisi harus sepakat:
- Frontend mengatur
credentials: "include"padafetch, atauwithCredentials: truedi axios. - Server mengirim
Access-Control-Allow-Credentials: true. Access-Control-Allow-Origindi server harus berupa origin yang persis sama, bukan*.
Cookie lintas situs juga membutuhkan SameSite=None; Secure pada cookie, dan beberapa browser membatasi cookie pihak ketiga lebih jauh. Itu satu alasan lagi untuk lebih memilih pendekatan di Langkah 5.
Langkah 5: Hindari CORS dengan setup satu origin
Sering kali perbaikan terbersih adalah tidak membuat request lintas origin sama sekali. Sajikan API dari origin yang sama dengan halaman, misalnya di https://myapp.com/api/...:
- Saat development, kebanyakan dev server bisa melakukan proxy. Pengaturan
server.proxydi Vite dapat meneruskan/apike back end kamu di port lain, sehingga browser hanya berbicara dengan satu origin. - Di produksi, arahkan
/apike back end lewat pengaturan rewrite atau proxy host kamu, atau sajikan frontend dan API dari satu server.
Frontend kemudian memanggil path relatif seperti fetch("/api/orders"). Tidak ada request lintas origin, tidak ada preflight antar origin, dan tidak ada masalah cookie. Ini juga berarti kamu tidak perlu menulis domain API secara tetap yang berbeda antara pratinjau dan produksi.
Ubah frontend agar memanggil backend dengan path /api yang relatif, bukan URL lengkap, dan atur proxy development sehingga /api diteruskan ke server API. Lalu hapus pengaturan CORS yang tidak diperlukan lagi.
Yang sebaiknya tidak dilakukan
mode: "no-cors"difetch. Ini tidak melewati apa pun; ia hanya memberi kode kamu respons kosong yang tidak bisa dibaca.- Ekstensi browser yang menonaktifkan CORS. Itu hanya mengubah browser kamu. Setiap pengunjung tetap melihat error.
- Layanan “CORS proxy” publik untuk aplikasi sungguhan. Mereka bisa membaca dan mengubah semua yang melewatinya, dan sering mati.
Access-Control-Allow-Origin: *pada API yang memakai login. Ini tidak berfungsi dengan kredensial, dan merupakan default yang salah untuk data privat.- Memantulkan kembali header
Originapa pun dengan kredensial diizinkan. Ini memungkinkan situs web mana pun membuat request yang sudah login atas nama penggunamu. Gunakan allowlist.
Penyebab umum di aplikasi buatan AI
| Situasi | Perbaikan |
|---|---|
| Frontend memanggil API pihak ketiga dengan kunci rahasia | Pindahkan pemanggilan ke back end |
| Berfungsi di pratinjau, gagal di domain yang dipublikasikan | Tambahkan origin yang dipublikasikan dan domain kustom ke allowlist, atau gunakan path /api yang relatif |
| Error hanya pada POST, PUT, atau DELETE | Preflight belum ditangani; tambahkan penanganan OPTIONS dan header yang diizinkan |
| Error muncul setelah menambahkan login | Kredensial membutuhkan origin yang persis dan Allow-Credentials |
| “Error CORS” tetapi tab Network menampilkan 500 | Perbaiki error server dulu |
URL API tertanam keras sebagai localhost | Gunakan path relatif atau pengaturan per lingkungan |
CORS di Mythex
Ketika proyek Mythex punya situs web dan server API, keduanya berjalan sebagai layanan di proyek yang sama, dan kamu bisa berpindah di antara keduanya di pratinjau. Meminta agen agar frontend memanggil backend lewat path /api yang relatif, yang diproxy saat development, menghindari sebagian besar masalah CORS. Jika kamu memang membutuhkan panggilan lintas origin, berikan agen error persis dari console dan origin yang terlibat. Periksa hasilnya juga di aplikasi yang sudah dipublikasikan, karena alamatnya berbeda dari pratinjau. Lihat Aplikasi multi-layanan dan Backend API di dokumentasi, serta panduan kami tentang men-debug aplikasi buatan AI dan frontend vs backend.
Checklist CORS
- Membaca error console lengkap dan status code request yang gagal
- Memastikan tidak ada 404 atau 500 tersembunyi
- API dengan kunci rahasia dipanggil dari back end, bukan browser
- Server mengirim
Access-Control-Allow-Origindengan origin yang diizinkan secara persis - Preflight
OPTIONSdijawab dengan metode dan header yang diizinkan, sebelum autentikasi - Header CORS ada pada respons error juga
- Kredensial: origin persis,
Allow-Credentials: true, dan pengaturan cookie yang benar - Origin pratinjau, yang dipublikasikan, dan domain kustom semuanya tercakup, atau path /api relatif digunakan
- Tidak ada
no-cors, proxy publik, atau pintasan memantulkan origin apa pun
Pertanyaan
Apa arti error CORS?
Halaman kamu, yang dimuat dari satu origin, mencoba membaca respons dari origin lain, dan server tersebut tidak menyertakan header yang mengizinkannya. Browser memblokir kode kamu agar tidak bisa membaca respons. Perbaikannya ada di server, atau di cara request di-route, bukan di kode frontend.
Bisakah saya memperbaiki error CORS dari frontend?
Tidak dengan benar. Pengaturan seperti mode: 'no-cors' hanya menyembunyikan respons dari kode kamu. Kamu memperbaikinya dengan membuat server mengirim header Access-Control-Allow-Origin yang tepat, atau dengan memanggil API dari back end sendiri atau proxy satu origin.
Apakah Access-Control-Allow-Origin: * aman?
Aman untuk data publik yang boleh dibaca siapa saja, seperti API publik tanpa login. Header ini tidak bisa dipakai bersama cookie atau kredensial lain, dan untuk API privat sebaiknya cantumkan origin yang diizinkan secara tepat.
Kenapa request saya berfungsi di Postman atau curl tetapi tidak di browser?
CORS hanya diterapkan oleh browser. Alat seperti Postman dan curl tidak menerapkannya, sehingga request bisa berhasil di sana dan tetap diblokir saat JavaScript halaman yang membuatnya.
Apa itu preflight request?
Untuk request yang tidak sederhana, seperti POST JSON atau request dengan header Authorization, browser lebih dulu mengirim request OPTIONS untuk menanyakan metode dan header apa saja yang diizinkan server. Jika request OPTIONS itu gagal atau tidak memiliki header yang benar, request sebenarnya tidak pernah dikirim.