Kamu baru selesai membuat API dengan Express. Di Postman semuanya lancar, data muncul sempurna. Lalu kamu memanggil API yang sama dari aplikasi React, dan console browser langsung dipenuhi tulisan merah:
Access to fetch at 'http://localhost:3000/api/users' from origin
'http://localhost:5173' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested resource.
Selamat datang di CORS error, salah satu error yang hampir pasti dialami setiap developer web. Kabar baiknya, error ini bukan bug di kodemu. Browser sedang menjalankan aturan keamanan, dan solusinya ada di sisi server. Di artikel ini, kamu akan memahami penyebabnya dan mempelajari 5 cara mengatasinya di Express, lengkap dengan contoh kode.
Daftar Isi
- Apa Itu CORS?
- Mengapa CORS Error Terjadi?
- Apa Itu Preflight Request?
- 5 Cara Mengatasi CORS Error di Express
- Kesalahan Umum saat Mengatasi CORS Error
- Tips Keamanan CORS
- Checklist Debugging CORS Error
- FAQ
- Kesimpulan
Apa Itu CORS?
CORS adalah singkatan dari Cross-Origin Resource Sharing. Ini adalah mekanisme berbasis header HTTP yang memberi tahu browser apakah sebuah halaman web boleh mengambil data dari origin yang berbeda.
Agar paham, kamu perlu tahu dulu arti origin. Origin terdiri dari tiga bagian: protokol, domain, dan port. Dua alamat dianggap satu origin hanya jika ketiganya sama persis.
| Alamat A | Alamat B | Satu origin? |
|---|---|---|
http://localhost:3000 | http://localhost:3000/api | Ya |
http://localhost:3000 | http://localhost:5173 | Tidak (port beda) |
http://contoh.com | https://contoh.com | Tidak (protokol beda) |
https://contoh.com | https://api.contoh.com | Tidak (subdomain beda) |
Jadi, saat frontend di localhost:5173 memanggil API di localhost:3000, browser menganggapnya permintaan cross-origin. Di sinilah CORS berperan.
Mengapa CORS Error Terjadi?
Browser menerapkan kebijakan keamanan bernama same-origin policy. Tanpa aturan ini, situs jahat bisa diam-diam membaca data dari situs lain yang sedang kamu buka, misalnya data akun bank yang sedang login di tab sebelah.
CORS adalah cara resmi untuk melonggarkan aturan tersebut. Server harus menyatakan secara eksplisit bahwa origin tertentu boleh mengakses datanya, lewat header Access-Control-Allow-Origin. Jika header itu tidak ada, atau tidak cocok dengan origin pemanggil, browser memblokir respons dan muncul CORS error.
Ada tiga hal penting yang sering disalahpahami:
- CORS error dikeluarkan oleh browser, bukan server. Itu sebabnya Postman, cURL, atau pemanggilan dari server lain berjalan normal tanpa error.
- Request biasanya sampai ke server. Server tetap memprosesnya. Yang diblokir adalah kemampuan browser untuk membaca responsnya.
- Solusinya ada di server. Kamu tidak bisa memperbaiki CORS error dari kode frontend saja.
Apa Itu Preflight Request?
Untuk permintaan yang dianggap “tidak sederhana”, browser lebih dulu mengirim permintaan pengecekan dengan metode OPTIONS. Ini disebut preflight request. Browser bertanya ke server: “Boleh nggak saya mengirim permintaan seperti ini dari origin ini?”
Preflight muncul jika permintaanmu memenuhi salah satu kondisi berikut:
- Memakai metode selain
GET,POST, atauHEAD, misalnyaPUT,PATCH, atauDELETE. - Mengirim header khusus, seperti
Authorization. - Mengirim
Content-Type: application/json.
Karena hampir semua API modern memakai JSON dan token, preflight akan sangat sering kamu temui. Jika server tidak menjawab preflight dengan benar, kamu akan melihat CORS error meski endpoint aslinya sudah benar.
Untuk membandingkan gaya API yang kamu bangun, baca juga perbandingan REST API vs GraphQL.
5 Cara Mengatasi CORS Error di Express
Semua contoh di bawah memakai Express. Bayangkan struktur API sederhana berikut:
javascript
// server.js
const express = require('express');
const app = express();
app.use(express.json());
app.get('/api/users', (req, res) => {
res.json([{ id: 1, nama: 'Ayu' }, { id: 2, nama: 'Budi' }]);
});
app.listen(3000, () => console.log('Server jalan di port 3000'));
Tanpa konfigurasi tambahan, pemanggilan dari localhost:5173 akan memunculkan CORS error.
Cara 1: Pakai Package cors (Paling Mudah)
Ini solusi yang paling sering dipakai. Instal package-nya:
bash
npm install cors
Lalu pasang sebagai middleware sebelum route:
javascript
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());
app.get('/api/users', (req, res) => {
res.json([{ id: 1, nama: 'Ayu' }]);
});
app.listen(3000);
cors() tanpa opsi akan mengizinkan semua origin. Ini praktis untuk belajar atau tahap development, tetapi tidak disarankan untuk produksi, terutama jika API-mu menyimpan data sensitif.
Cara 2: Batasi Origin yang Diizinkan (Whitelist)
Untuk produksi, izinkan hanya origin yang kamu percaya:
javascript
const corsOptions = {
origin: ['http://localhost:5173', 'https://aplikasiku.com'],
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
};
app.use(cors(corsOptions));
Jika daftar origin berubah-ubah antar lingkungan, simpan di environment variable. Panduan lengkapnya ada di artikel kami tentang environment variable dan cara pakai .env di Node.js.
javascript
const allowedOrigins = process.env.ALLOWED_ORIGINS.split(',');
app.use(cors({
origin: (origin, callback) => {
// izinkan request tanpa origin (Postman, server-to-server)
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Origin tidak diizinkan oleh CORS'));
}
},
}));
Isi file .env-nya:
ALLOWED_ORIGINS=http://localhost:5173,https://aplikasiku.com
Cara 3: Atur Header CORS Secara Manual
Jika tidak ingin menambah dependensi, kamu bisa menulis middleware sendiri. Cara ini juga bagus untuk memahami apa yang sebenarnya dilakukan package cors.
javascript
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'http://localhost:5173');
res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
// jawab preflight langsung
if (req.method === 'OPTIONS') {
return res.sendStatus(204);
}
next();
});
Perhatikan bagian OPTIONS. Tanpa penanganan ini, preflight akan gagal dan request aslinya tidak pernah dikirim.
Cara 4: Aktifkan Credentials (Cookie dan Token Sesi)
Jika frontend perlu mengirim cookie atau kredensial, konfigurasinya berbeda. Dua aturan wajib:
- Server harus mengirim
Access-Control-Allow-Credentials: true. - Origin tidak boleh memakai wildcard
*. Harus origin yang spesifik.
Di server:
javascript
app.use(cors({
origin: 'http://localhost:5173',
credentials: true,
}));
Di frontend, ikut aktifkan kredensialnya:
javascript
fetch('http://localhost:3000/api/profile', {
credentials: 'include',
})
.then((res) => res.json())
.then((data) => console.log(data));
Jika memakai Axios, gunakan withCredentials: true. Untuk memahami perbedaan tempat menyimpan data di browser, baca perbedaan local storage, session storage, dan cookies.
Cara 5: Pakai Proxy di Lingkungan Development
Alternatifnya, kamu bisa membuat browser menganggap frontend dan API berasal dari origin yang sama. Di Vite, caranya lewat proxy:
javascript
// vite.config.js
export default {
server: {
proxy: {
'/api': 'http://localhost:3000',
},
},
};
Sekarang frontend cukup memanggil /api/users, tanpa menulis localhost:3000:
javascript
fetch('/api/users').then((res) => res.json());
Vite akan meneruskan permintaan ke server Express, sehingga browser tidak melihatnya sebagai cross-origin. Perlu diingat, proxy ini hanya berlaku di development. Untuk produksi, kamu tetap perlu konfigurasi CORS di server atau reverse proxy seperti Nginx.
Kesalahan Umum saat Mengatasi CORS Error
Beberapa kesalahan di bawah sering membuat CORS error terasa “tidak mau hilang”.
1. Memasang cors() Setelah Route
Express menjalankan middleware sesuai urutan. Jika app.use(cors()) ditaruh setelah route, header CORS tidak akan ikut terkirim. Letakkan di bagian paling atas.
2. Memakai Wildcard bersama Credentials
Kombinasi Access-Control-Allow-Origin: * dan credentials: true ditolak browser. Gunakan origin yang spesifik.
3. Salah Menulis Origin
Origin harus cocok persis. http://localhost:5173/ (dengan garis miring di akhir) berbeda dengan http://localhost:5173. Begitu juga http dan https, atau www dan non-www.
4. Memakai mode: 'no-cors' di fetch
Banyak tutorial menyarankan mode: 'no-cors'. Memang error-nya hilang, tetapi kamu akan mendapat respons opaque yang isinya tidak bisa dibaca. Ini bukan solusi, hanya menyembunyikan masalah.
5. Server Error Tapi Dikira CORS Error
Jika server crash atau melempar error 500 sebelum header CORS terpasang, browser tetap melaporkan CORS error. Selalu cek tab Network dan log server untuk melihat status asli permintaan.
6. Menggunakan Ekstensi “Disable CORS” sebagai Solusi Tetap
Ekstensi seperti itu hanya mematikan pengecekan di browsermu sendiri. Pengguna lain tetap akan melihat error. Pakai hanya untuk pengujian cepat, bukan untuk perbaikan.
Tips Keamanan CORS
CORS sering diatasi dengan cara yang terlalu longgar. Beberapa prinsip berikut membantu menjaga keamanan API:
- Jangan pakai
origin: '*'di produksi untuk API yang memuat data pribadi. - Gunakan whitelist origin yang dikenal, dan simpan di konfigurasi lingkungan.
- Batasi metode dan header yang diizinkan sesuai kebutuhan saja.
- Jangan anggap CORS sebagai autentikasi. CORS hanya mengatur browser. Orang tetap bisa memanggil API-mu langsung lewat cURL atau skrip, jadi pasang autentikasi dan otorisasi yang benar.
- Kombinasikan dengan pembatasan request. Pelajari rate limiting API di Express agar API tidak dibanjiri permintaan.
Untuk referensi resmi dan detail teknis tiap header, kamu bisa membaca dokumentasi CORS di MDN Web Docs.
Checklist Debugging CORS Error
Saat CORS error muncul, periksa berurutan:
- Buka tab Network di DevTools dan lihat permintaan yang gagal.
- Cek apakah ada permintaan
OPTIONS(preflight) dan apa statusnya. - Lihat header respons: apakah
Access-Control-Allow-Originada dan sesuai? - Pastikan origin di server sama persis dengan origin frontend.
- Jika memakai cookie, cek
credentialsdi server dan frontend. - Pastikan middleware
corsdipasang sebelum route. - Periksa log server untuk memastikan tidak ada error 500 di baliknya.
- Setelah mengubah server, restart dan hard refresh browser.
Pertanyaan yang Sering Diajukan (FAQ)
Apa arti CORS error?
CORS error berarti browser memblokir akses ke respons dari server karena server tidak mengizinkan origin tempat halamanmu berjalan. Ini bagian dari mekanisme keamanan browser, bukan kesalahan pada logika kodemu.
Mengapa CORS error tidak muncul di Postman?
Karena CORS hanya diterapkan oleh browser. Postman bukan browser dan tidak menjalankan kebijakan same-origin, sehingga permintaan berjalan tanpa pengecekan CORS.
Apakah aman memakai cors() tanpa opsi?
Aman untuk belajar dan development. Untuk produksi, sebaiknya batasi origin lewat whitelist, terutama jika API menangani data pengguna.
Apakah CORS error bisa diperbaiki dari frontend?
Tidak. Header CORS harus dikirim oleh server. Yang bisa dilakukan di sisi frontend hanya memakai proxy saat development, yang pada dasarnya membuat permintaan tampak berasal dari origin yang sama.
Apa bedanya CORS dan autentikasi?
CORS mengatur origin mana yang boleh dibaca responsnya oleh browser. Autentikasi memastikan siapa yang boleh mengakses data. Keduanya berbeda dan sebaiknya dipakai bersamaan.
Mengapa CORS error masih muncul padahal sudah memasang cors()?
Penyebab umumnya: middleware dipasang setelah route, origin tidak cocok persis, preflight tidak ditangani, server mengembalikan error 500, atau ada konflik wildcard dengan credentials. Ikuti checklist debugging di atas.
Kesimpulan
CORS error terlihat menakutkan, tetapi sebenarnya sederhana: browser meminta izin, dan server harus memberikannya lewat header yang tepat. Untuk belajar, app.use(cors()) sudah cukup. Untuk produksi, gunakan whitelist origin, aktifkan credentials dengan benar jika perlu, dan jangan lupa menangani preflight.
Ingat tiga hal inti: CORS dikeluarkan oleh browser, solusinya ada di server, dan CORS bukan pengganti autentikasi. Dengan pemahaman ini, kamu tidak perlu lagi panik setiap kali tulisan merah itu muncul di console.
Sedang membangun API dan ingin melanjutkan belajar? Lanjutkan dengan belajar Git dan GitHub lengkap agar proyekmu rapi dan siap dikerjakan bersama tim.