Cara Handle CORS Saat Pakai json-server

3 menit baca.
Tags: javascriptnode-js

CORS error adalah salah satu hal pertama yang langsung muncul saat kamu jalanin json-server sebagai mock API lokal. Ini cara fixnya.

Kenapa CORS Muncul di json-server

Browser enforce same-origin policy. Kalau frontend kamu jalan di http://localhost:3000 dan json-server jalan di http://localhost:3001, browser melihat keduanya sebagai origin yang berbeda karena portnya beda. Setiap fetch atau XHR dari frontend ke json-server akan diblok kecuali servernya balas dengan CORS header yang tepat.

Errornya biasanya terlihat seperti ini:

Access to fetch at 'http://localhost:3001/users' from origin 'http://localhost:3000'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present.

Solusinya adalah menjalankan json-server secara programmatic supaya kamu bisa pasang middleware sendiri.

Fix-nya: Custom server.js

Daripada pakai CLI, buat file server.js di root project:

const jsonServer = require('json-server');
const server = jsonServer.create();
const router = jsonServer.router('db.json');
const middlewares = jsonServer.defaults();

server.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Headers', '*');
  next();
});

server.use(middlewares);
server.use(router);

server.listen(3001, () => {
  console.log('JSON Server is running on port 3001');
});

Jalankan dengan:

node server.js

Middleware-nya jalan sebelum router json-server, jadi setiap response sudah dapat header tersebut. Sampai sini sudah cukup untuk CORS dasar.

Handling Preflight OPTIONS Request

Untuk request yang tidak sederhana - seperti yang punya JSON body, custom header seperti Authorization, atau method PUT, PATCH, DELETE - browser akan kirim preflight request OPTIONS duluan untuk mengecek apakah server mengizinkannya. Tanpa menangani ini, request DELETE atau PATCH kamu tetap akan gagal.

Tambahkan pengecekan OPTIONS di middleware yang sama:

server.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Headers', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');

  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }

  next();
});

Ketika browser kirim preflight check tersebut, server kamu langsung balas dengan 200 dan header yang tepat. Request yang sebenarnya pun bisa jalan tanpa masalah.

Wildcard vs Origin Spesifik

Access-Control-Allow-Origin: * aman untuk dev lokal. Ini mengizinkan request dari origin mana saja, yang memang kamu butuhkan saat mock API.

Satu kasus di mana ini tidak berfungsi: kalau kamu perlu kirim cookie atau pakai credentials: 'include' di fetch, browser akan reject wildcard origin. Untuk itu kamu perlu tentukan origin yang spesifik dan set credentials header:

res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Credentials', 'true');

Untuk mock server lokal ini hampir tidak pernah dibutuhkan, tapi bagus untuk tahu sebelum kamu debugging 20 menit kenapa credentialed request tidak mau jalan.

Kesimpulan

CORS di json-server bisa di-fix dengan tidak pakai CLI dan buat server.js kecil dengan middleware yang set Access-Control-Allow-Origin dan Access-Control-Allow-Headers. Kalau kamu buat request PUT, PATCH, DELETE, atau request dengan custom header, tambahkan handler OPTIONS juga. Wildcard origin sudah cukup untuk semua kebutuhan dev lokal kecuali kamu perlu credentials.