Menu

Cara Mengatasi Error CORS di Express, Dengan dan Tanpa cors

Error CORS berarti browser memblokir sebuah halaman membaca response API-mu karena response itu tidak mengizinkan origin halaman tersebut. Perbaiki di server dengan mengirim Access-Control-Allow-Origin dan menjawab request preflight OPTIONS, secara manual atau dengan package cors.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Error CORS ("No 'Access-Control-Allow-Origin' header is present") berarti sebuah halaman web di satu origin, seperti http://localhost:5173, memanggil API-mu di origin lain, dan browser menolak membiarkan halaman itu membaca response-nya karena response itu tidak menyatakan bahwa origin tersebut diizinkan. Perbaikannya ada di server: kirim Access-Control-Allow-Origin dengan origin halaman itu, dan jawab request preflight OPTIONS dari browser dengan method dan header yang kamu terima. Di Express, itu hanya beberapa baris middleware, atau app.use(cors()) dari package cors.

Response-nya adalah daftar produk, dan tab Headers-nya menampilkan access-control-allow-origin: https://app.example.com: halaman di origin itu boleh membacanya. Sekarang kirim OPTIONS /api/products/1 dengan header Origin: https://app.example.com dan Access-Control-Request-Method: PUT. Itulah preflight yang dikirim browser sebelum PUT, dan jawabannya 204 dengan method dan header yang diizinkan, tanpa body.

Apa yang dicek browser

Halaman same-origin tidak butuh apa-apa. Untuk request cross-origin, browser membaca header response berikut:

HeaderArtinya
Access-Control-Allow-OriginSatu origin yang boleh membaca response, atau * untuk semua
Access-Control-Allow-MethodsMethod yang diizinkan di request sebenarnya (hanya preflight)
Access-Control-Allow-HeadersHeader request yang boleh dikirim halaman, seperti Authorization (hanya preflight)
Access-Control-Allow-Credentialstrue kalau halaman boleh mengirim cookie dan membaca jawabannya
Access-Control-Max-AgeBerapa detik browser boleh menyimpan jawaban preflight di cache
Vary: OriginMemberi tahu cache bahwa jawabannya bergantung pada header request Origin

GET sederhana atau POST bergaya form langsung dikirim ke server, dan browser mengecek Access-Control-Allow-Origin di jawabannya. Server tetap menjalankan request-nya; CORS hanya menentukan apakah halaman bisa melihat hasilnya. Request dengan body JSON, header Authorization, atau method seperti PUT atau DELETE didahului request preflight OPTIONS, dan request sebenarnya hanya dikirim kalau jawaban preflight mengizinkannya. Itulah sebabnya middleware CORS harus menjawab OPTIONS sebelum route atau pengecekan auth mana pun berjalan.

Mengizinkan beberapa origin, dengan credentials

Access-Control-Allow-Origin berisi satu origin atau *, tidak pernah daftar. Untuk mengizinkan beberapa, bandingkan header Origin milik request dengan daftar yang diizinkan dan kembalikan nilai yang sama saat cocok:

Request pertama tidak punya header Origin, seperti panggilan dari curl atau halaman same-origin, jadi ia mendapat {"origin":null} dan tanpa header CORS. Kirim GET /api/me dengan header Origin: http://localhost:5173 dan tab Headers menampilkan origin itu dikembalikan, ditambah access-control-allow-credentials: true. Ganti header-nya menjadi Origin: https://evil.example dan kedua header CORS hilang: server tetap menjawab, tetapi browser akan memblokir halaman membacanya. Access-Control-Allow-Credentials: true membuat halaman boleh mengirim cookie (dengan fetch(url, { credentials: 'include' })), dan browser menolaknya kalau dipasangkan dengan *, jadi credentials selalu butuh origin yang persis.

Package cors

Package cors melakukan pekerjaan yang sama dengan opsi. Install dengan npm install cors:

const cors = require('cors');

// Any origin, no cookies: fine for a public read-only API.
app.use(cors());

// Only your frontend, with cookies.
app.use(cors({
    origin: ['https://app.example.com', 'http://localhost:5173'],
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
}));

// One route only.
app.get('/api/public', cors(), handler);

Kalau dipanggil tanpa opsi, cors() mengirim Access-Control-Allow-Origin: * dan menjawab setiap preflight. Pakai * hanya untuk data publik yang tidak butuh login.

Kesalahan umum

Menambahkan CORS setelah route atau setelah middleware auth. Request preflight OPTIONS tidak membawa header Authorization, jadi pengecekan auth yang ditaruh lebih dulu menjawabnya dengan 401 dan browser melaporkan error CORS. Daftarkan middleware CORS lebih dulu.

Memakai * bersama credentials. Browser menolak response-nya. Kembalikan origin yang spesifik.

Mencoba memperbaiki CORS di frontend. Opsi request seperti mode: 'no-cors' tidak mencabut pembatasannya; opsi itu memberimu response opaque yang tidak bisa kamu baca. Hanya header dari server yang bisa memperbaikinya.

Untuk cara kerja app.use() dan urutan middleware, lihat middleware Express.

Pertanyaan yang sering diajukan

Kenapa API-ku bekerja di Postman atau curl tetapi tidak di browser?

CORS hanya diterapkan oleh browser. Postman, curl, dan server lain mengabaikan header CORS, jadi mereka tetap bisa membaca response-nya. Browser menolak menyerahkan response ke script halaman dari origin lain kecuali server mengizinkan origin itu.

Apakah CORS fitur keamanan untuk server-ku?

CORS melindungi user, bukan server-mu. CORS mencegah halaman jahat membaca response dari API-mu dengan cookie milik user. Siapa pun tetap bisa memanggil API-mu dari script atau server, jadi autentikasi dan otorisasi tetap tugasmu.

Apa yang dihitung sebagai origin yang berbeda?

Origin adalah gabungan scheme, host, dan port. http://localhost:5173 dan http://localhost:3000 adalah origin yang berbeda karena port-nya berbeda, dan https://example.com serta https://api.example.com berbeda di host-nya.

Bisakah aku menghindari CORS saat development?

Bisa, dengan membuat request-nya same-origin: atur dev server frontend-mu (misalnya server.proxy milik Vite) untuk meneruskan /api ke server Express. Browser lalu berbicara dengan satu origin dan tidak perlu header CORS.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai