Thursday

19-06-2025 Vol 19

How to fix CORS errors in Node.js

Cara Memperbaiki Kesalahan CORS di Node.js: Panduan Lengkap

Kesalahan CORS (Cross-Origin Resource Sharing) adalah masalah umum yang dihadapi pengembang web saat mencoba membuat permintaan dari satu domain ke domain lain. Di Node.js, masalah ini sering muncul saat API Anda berjalan di satu domain (misalnya, http://localhost:3000) dan aplikasi front-end Anda berjalan di domain lain (misalnya, http://localhost:8080). Artikel ini akan memberikan panduan mendalam tentang apa itu CORS, mengapa kesalahan CORS terjadi, dan bagaimana cara memperbaikinya di aplikasi Node.js Anda.

Apa itu CORS?

CORS (Cross-Origin Resource Sharing) adalah mekanisme keamanan browser yang membatasi permintaan HTTP lintas asal untuk situs web. Sebuah “asal” didefinisikan oleh skema (protokol), host (nama domain), dan port. Jadi, http://example.com:8080 dan https://example.com:8080 dianggap sebagai asal yang berbeda, meskipun host-nya sama.

Kebijakan Same-Origin Policy (SOP) adalah kebijakan keamanan browser dasar yang mencegah JavaScript yang berjalan di satu asal untuk membuat permintaan ke asal yang berbeda. CORS adalah mekanisme yang memperluas SOP, memungkinkan server untuk memberi tahu browser bahwa mereka mengizinkan permintaan lintas asal dari asal-asal tertentu.

Mengapa Kesalahan CORS Terjadi?

Kesalahan CORS terjadi ketika browser mendeteksi bahwa respons dari server tidak menyertakan header CORS yang diperlukan yang menunjukkan bahwa asal permintaan diizinkan. Browser kemudian memblokir respons tersebut dan menampilkan kesalahan CORS di konsol pengembang.

Berikut adalah beberapa alasan umum mengapa kesalahan CORS terjadi:

  1. Tidak ada header CORS: Server tidak mengirim header Access-Control-Allow-Origin dalam responsnya.
  2. Header CORS yang salah: Header Access-Control-Allow-Origin tidak berisi asal permintaan atau wildcard (*).
  3. Metode HTTP tidak diizinkan: Server tidak mengizinkan metode HTTP yang digunakan dalam permintaan lintas asal (misalnya, PUT, DELETE).
  4. Header yang tidak diizinkan: Permintaan menyertakan header kustom yang tidak diizinkan oleh server.
  5. Kredensial tidak ditangani dengan benar: Permintaan memerlukan kredensial (misalnya, cookie, header otorisasi), tetapi header Access-Control-Allow-Credentials tidak disetel ke true.

Bagaimana Cara Memperbaiki Kesalahan CORS di Node.js?

Berikut adalah beberapa cara untuk memperbaiki kesalahan CORS di aplikasi Node.js Anda:

1. Menggunakan Paket cors (Cara yang Direkomendasikan)

Paket cors adalah middleware Node.js yang populer dan mudah digunakan untuk mengaktifkan CORS. Ini adalah cara yang paling direkomendasikan karena fleksibilitas dan kemudahannya.

a. Instal Paket cors:

Buka terminal Anda dan jalankan perintah berikut:

npm install cors

b. Impor dan Gunakan Middleware cors:

Di aplikasi Node.js Anda (biasanya di file app.js atau server.js), impor paket cors dan gunakan sebagai middleware.

Contoh Dasar (Mengizinkan Semua Asal):

const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors()); // Mengaktifkan CORS untuk semua asal

app.get('/api/data', (req, res) => {
  res.json({ message: 'Data dari API' });
});

app.listen(3000, () => {
  console.log('Server berjalan di port 3000');
});

Penjelasan:

  • require('cors'): Mengimpor paket cors.
  • app.use(cors()): Menggunakan middleware cors untuk *semua* rute. Ini secara efektif menambahkan header Access-Control-Allow-Origin: * ke setiap respons, yang mengizinkan permintaan dari *asal mana pun*.

Contoh dengan Konfigurasi Spesifik (Mengizinkan Asal Tertentu):

Untuk keamanan yang lebih baik, Anda sebaiknya hanya mengizinkan asal tertentu yang diizinkan untuk mengakses API Anda.

const express = require('express');
const cors = require('cors');
const app = express();

const corsOptions = {
  origin: 'http://localhost:8080' // Hanya mengizinkan asal ini
};

app.use(cors(corsOptions));

app.get('/api/data', (req, res) => {
  res.json({ message: 'Data dari API' });
});

app.listen(3000, () => {
  console.log('Server berjalan di port 3000');
});

Penjelasan:

  • origin: 'http://localhost:8080': Hanya mengizinkan permintaan dari http://localhost:8080. Jika permintaan datang dari asal lain, browser akan memblokirnya.

Konfigurasi Lebih Lanjut dengan Fungsi origin:

Anda juga dapat menggunakan fungsi untuk menentukan asal mana yang diizinkan secara dinamis. Ini berguna jika Anda memiliki beberapa asal yang diizinkan atau jika Anda ingin melakukan logika yang lebih kompleks untuk menentukan apakah suatu asal harus diizinkan.

const express = require('express');
const cors = require('cors');
const app = express();

const whitelist = ['http://localhost:8080', 'http://example.com'];
const corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1 || !origin) { // Memeriksa apakah asal ada di daftar putih atau jika asal tidak ada (permintaan server-ke-server)
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
};

app.use(cors(corsOptions));

app.get('/api/data', (req, res) => {
  res.json({ message: 'Data dari API' });
});

app.listen(3000, () => {
  console.log('Server berjalan di port 3000');
});

Penjelasan:

  • whitelist: Array dari asal yang diizinkan.
  • Fungsi origin:
    • Menerima origin sebagai argumen (asal dari permintaan).
    • Menerima callback sebagai argumen (fungsi yang harus dipanggil dengan hasil).
    • Memeriksa apakah origin ada di whitelist atau jika origin adalah undefined (yang bisa terjadi untuk permintaan server-ke-server).
    • Jika diizinkan, panggil callback(null, true).
    • Jika tidak diizinkan, panggil callback(new Error('Not allowed by CORS')).

Opsi Konfigurasi Lainnya pada corsOptions:

Paket cors menawarkan banyak opsi konfigurasi lainnya. Beberapa yang paling umum adalah:

  • methods: Array metode HTTP yang diizinkan (misalnya, ['GET', 'POST', 'PUT', 'DELETE']). Secara default, ini adalah GET,HEAD,PUT,PATCH,POST,DELETE.
  • allowedHeaders: Array header HTTP yang diizinkan dalam permintaan lintas asal. Secara default, ini adalah semua header.
  • exposedHeaders: Array header HTTP yang dapat diakses oleh browser dari respons. Secara default, tidak ada header yang diekspos.
  • credentials: Boolean yang menunjukkan apakah permintaan lintas asal dapat menyertakan kredensial (misalnya, cookie, header otorisasi). Harus disetel ke true jika Anda ingin browser mengirim kredensial dan server memprosesnya.
  • preflightContinue: Boolean yang menunjukkan apakah middleware harus melanjutkan pemrosesan setelah permintaan preflight.
  • optionsSuccessStatus: Kode status HTTP yang akan dikembalikan untuk permintaan preflight yang berhasil.

Contoh Penggunaan Opsi Lainnya:

const express = require('express');
const cors = require('cors');
const app = express();

const corsOptions = {
  origin: 'http://localhost:8080',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
};

app.use(cors(corsOptions));

app.get('/api/data', (req, res) => {
  res.json({ message: 'Data dari API' });
});

app.listen(3000, () => {
  console.log('Server berjalan di port 3000');
});

2. Menetapkan Header CORS Secara Manual (Tidak Direkomendasikan untuk Proyek Besar)

Anda dapat menetapkan header CORS secara manual dalam setiap respons. Meskipun ini memungkinkan, *sangat tidak direkomendasikan* untuk aplikasi yang lebih besar karena mudah membuat kesalahan dan sulit dikelola. Paket cors menyediakan cara yang jauh lebih efisien dan aman.

Contoh:

const express = require('express');
const app = express();

app.get('/api/data', (req, res) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  res.json({ message: 'Data dari API' });
});

app.listen(3000, () => {
  console.log('Server berjalan di port 3000');
});

Penjelasan:

  • Access-Control-Allow-Origin: Menentukan asal yang diizinkan.
  • Access-Control-Allow-Methods: Menentukan metode HTTP yang diizinkan.
  • Access-Control-Allow-Headers: Menentukan header yang diizinkan.
  • Access-Control-Allow-Credentials: Menentukan apakah kredensial diizinkan.

Mengapa Ini Tidak Direkomendasikan?

  • Pengulangan: Anda harus menambahkan header ini ke setiap respons, yang sangat membosankan dan rawan kesalahan.
  • Kesalahan: Mudah lupa untuk menambahkan header ke beberapa respons, menyebabkan kesalahan CORS yang sporadis.
  • Pemeliharaan: Jika Anda perlu mengubah konfigurasi CORS Anda, Anda harus mengubah kode di banyak tempat.

3. Menggunakan Middleware Kustom (Alternatif yang Lebih Terkendali)

Jika Anda ingin kontrol penuh atas logika CORS Anda, Anda dapat membuat middleware kustom. Ini memungkinkan Anda untuk melakukan logika yang lebih kompleks daripada yang mungkin dengan paket cors.

Contoh:

const express = require('express');
const app = express();

const corsMiddleware = (req, res, next) => {
  const allowedOrigins = ['http://localhost:8080', 'http://example.com'];
  const origin = req.headers.origin;

  if (allowedOrigins.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }

  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.setHeader('Access-Control-Allow-Credentials', 'true');

  // Handle preflight requests
  if (req.method === 'OPTIONS') {
    res.sendStatus(204); // No Content
  } else {
    next();
  }
};

app.use(corsMiddleware);

app.get('/api/data', (req, res) => {
  res.json({ message: 'Data dari API' });
});

app.listen(3000, () => {
  console.log('Server berjalan di port 3000');
});

Penjelasan:

  • corsMiddleware: Fungsi middleware yang menangani logika CORS.
  • allowedOrigins: Array dari asal yang diizinkan.
  • req.headers.origin: Asal dari permintaan.
  • allowedOrigins.includes(origin): Memeriksa apakah asal ada di daftar putih.
  • req.method === 'OPTIONS': Memeriksa apakah permintaan adalah permintaan preflight (OPTIONS).
  • res.sendStatus(204): Mengirim kode status 204 No Content untuk permintaan preflight yang berhasil.
  • next(): Melewati kontrol ke middleware berikutnya dalam tumpukan.

Keuntungan dari Middleware Kustom:

  • Kontrol penuh: Anda memiliki kendali penuh atas logika CORS.
  • Fleksibilitas: Anda dapat melakukan logika yang lebih kompleks daripada yang mungkin dengan paket cors.

Kekurangan dari Middleware Kustom:

  • Lebih banyak kode: Anda perlu menulis lebih banyak kode daripada menggunakan paket cors.
  • Lebih banyak tanggung jawab: Anda bertanggung jawab untuk memastikan bahwa logika CORS Anda benar dan aman.

4. Menangani Permintaan Preflight (OPTIONS)

Browser modern membuat “permintaan preflight” OPTIONS sebelum membuat permintaan lintas asal yang “kompleks”. Permintaan kompleks adalah permintaan yang menggunakan metode HTTP selain GET, HEAD, atau POST dengan jenis konten application/x-www-form-urlencoded, multipart/form-data, atau text/plain, atau yang menyertakan header kustom.

Tujuan dari permintaan preflight adalah untuk memastikan bahwa server mengizinkan permintaan lintas asal yang sebenarnya sebelum browser mengirimnya. Server harus menanggapi permintaan preflight dengan header yang sesuai yang menunjukkan apakah permintaan lintas asal yang sebenarnya diizinkan.

Jika Anda menggunakan paket cors atau middleware kustom, Anda biasanya tidak perlu menangani permintaan preflight secara eksplisit. Paket cors secara otomatis menangani permintaan preflight, dan middleware kustom sering kali menyertakan logika untuk menangani permintaan preflight.

Namun, jika Anda menetapkan header CORS secara manual, Anda *harus* menangani permintaan preflight. Kegagalan untuk menangani permintaan preflight akan mengakibatkan kesalahan CORS.

Contoh Menangani Permintaan Preflight (dengan Middleware Kustom):

Perhatikan kode middleware kustom di atas. Bagian ini secara khusus menangani permintaan OPTIONS:

if (req.method === 'OPTIONS') {
  res.sendStatus(204); // No Content
} else {
  next();
}

Penjelasan:

  • req.method === 'OPTIONS': Memeriksa apakah permintaan adalah permintaan preflight.
  • res.sendStatus(204): Mengirim kode status 204 No Content untuk permintaan preflight yang berhasil. Kode status 204 menunjukkan bahwa server telah menerima permintaan tetapi tidak memiliki konten untuk dikembalikan. Ini adalah respons yang tepat untuk permintaan preflight yang berhasil.
  • next(): Melewati kontrol ke middleware berikutnya dalam tumpukan untuk permintaan non-preflight.

5. Menangani Kredensial (Cookie, Header Otorisasi)

Jika aplikasi front-end Anda perlu mengirim kredensial (seperti cookie atau header otorisasi) dengan permintaan lintas asal, Anda perlu melakukan beberapa langkah tambahan.

a. Setel credentials: true di Aplikasi Front-End:

Di aplikasi front-end Anda (misalnya, menggunakan fetch atau XMLHttpRequest), Anda perlu menyetel opsi credentials ke 'include'.

Contoh (menggunakan fetch):

fetch('http://localhost:3000/api/data', {
  method: 'GET',
  credentials: 'include' // Penting untuk mengirim cookie
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

b. Setel Access-Control-Allow-Credentials: true di Server:

Di server Node.js Anda, Anda perlu menyetel header Access-Control-Allow-Credentials ke true dalam respons Anda. Anda juga harus *tidak* menggunakan wildcard (*) untuk Access-Control-Allow-Origin. Sebaliknya, Anda harus menentukan asal yang tepat.

Contoh (menggunakan paket cors):

const express = require('express');
const cors = require('cors');
const app = express();

const corsOptions = {
  origin: 'http://localhost:8080', // *Tidak* boleh menggunakan '*' jika credentials: true
  credentials: true
};

app.use(cors(corsOptions));

app.get('/api/data', (req, res) => {
  res.json({ message: 'Data dari API' });
});

app.listen(3000, () => {
  console.log('Server berjalan di port 3000');
});

Contoh (menggunakan middleware kustom):

const express = require('express');
const app = express();

const corsMiddleware = (req, res, next) => {
  const allowedOrigins = ['http://localhost:8080'];
  const origin = req.headers.origin;

  if (allowedOrigins.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin); // *Tidak* boleh menggunakan '*'
  }

  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.setHeader('Access-Control-Allow-Credentials', 'true'); // Penting untuk mengizinkan kredensial

  if (req.method === 'OPTIONS') {
    res.sendStatus(204);
  } else {
    next();
  }
};

app.use(corsMiddleware);

app.get('/api/data', (req, res) => {
  res.json({ message: 'Data dari API' });
});

app.listen(3000, () => {
  console.log('Server berjalan di port 3000');
});

Peringatan Penting:

Ketika Access-Control-Allow-Credentials disetel ke true, Anda *tidak boleh* menggunakan wildcard (*) untuk Access-Control-Allow-Origin. Browser akan memblokir permintaan jika Anda melakukannya. Anda harus menentukan asal yang tepat yang diizinkan untuk mengakses API Anda.

6. Debugging Kesalahan CORS

Kesalahan CORS bisa sulit di-debug, terutama jika Anda tidak yakin apa yang menyebabkannya. Berikut adalah beberapa tips untuk debugging kesalahan CORS:

  1. Periksa Konsol Pengembang Browser: Pesan kesalahan CORS di konsol pengembang browser biasanya memberikan informasi yang berguna tentang apa yang salah. Perhatikan baik-baik pesan kesalahan dan header yang disebutkan.
  2. Gunakan Alat Pengembang Browser untuk Memeriksa Header: Gunakan alat pengembang browser untuk memeriksa header permintaan dan respons HTTP. Pastikan bahwa header CORS yang benar disetel dalam respons.
  3. Gunakan Alat CORS Online: Ada beberapa alat CORS online yang dapat membantu Anda mendiagnosis kesalahan CORS. Alat-alat ini akan mengirim permintaan lintas asal ke server Anda dan memeriksa header respons untuk memastikan bahwa semuanya sudah dikonfigurasi dengan benar.
  4. Periksa Konfigurasi Server Anda: Pastikan bahwa server Node.js Anda dikonfigurasi untuk mengizinkan permintaan lintas asal dari asal yang benar. Periksa kode Anda untuk memastikan bahwa header CORS yang benar disetel.
  5. Periksa Konfigurasi Front-End Anda: Pastikan bahwa aplikasi front-end Anda dikonfigurasi untuk mengirim kredensial (jika diperlukan) dan untuk menangani respons dengan benar.
  6. Pastikan Tidak Ada Middleware yang Bertentangan: Terkadang, middleware lain dalam tumpukan middleware Anda dapat mengganggu header CORS. Pastikan tidak ada middleware lain yang memodifikasi atau menghapus header CORS.
  7. Bersihkan Cache Browser Anda: Terkadang, cache browser Anda dapat menyebabkan kesalahan CORS yang salah. Coba bersihkan cache browser Anda dan coba lagi.

Kesimpulan

Kesalahan CORS dapat membuat frustrasi, tetapi dengan pemahaman yang baik tentang CORS dan langkah-langkah yang dijelaskan dalam artikel ini, Anda dapat memperbaiki kesalahan CORS di aplikasi Node.js Anda dan mengizinkan permintaan lintas asal yang aman. Gunakan paket cors untuk kemudahan dan fleksibilitas, dan selalu ikuti praktik terbaik untuk keamanan saat menangani CORS.

“`

omcoding

Leave a Reply

Your email address will not be published. Required fields are marked *