# Mengelola Cookies di Hono: Development, Testing, & Produksi

Cookies adalah bagian fundamental dari aplikasi web modern. Mereka digunakan untuk mengelola sesi login, menyimpan preferensi pengguna, dan melacak aktivitas. Namun, mengonfigurasi cookies dengan benar di berbagai lingkungan—mulai dari [`localhost`](http://localhost) untuk development, server produksi dengan subdomain, hingga lingkungan testing otomatis—seringkali menjadi tantangan.

Artikel ini akan memandu Anda secara lengkap dan mudah untuk mengelola cookies di Hono, dengan contoh kode yang siap diimplementasikan.

---

### \## Konsep Dasar Atribut Cookie

Sebelum masuk ke kode, mari kita pahami "aturan main" atau atribut utama dari sebuah cookie. Memahami ini adalah kunci untuk konfigurasi yang benar.

* `httpOnly`: Jika `true`, cookie tidak bisa diakses oleh JavaScript sisi klien (`document.cookie`). Ini adalah **pertahanan wajib** terhadap serangan XSS.
    
* `secure`: Jika `true`, cookie hanya akan dikirim melalui koneksi HTTPS. Wajib di lingkungan produksi.
    
* `path`: Menentukan URL path mana yang bisa menerima cookie. Mengaturnya ke `/` membuatnya tersedia di seluruh situs Anda.
    
* `domain`: Mengontrol subdomain mana yang bisa menerima cookie. Ini adalah kunci untuk arsitektur dengan API di subdomain terpisah.
    
* `sameSite`: Perlindungan utama terhadap serangan CSRF.
    
    * `Strict`: Paling ketat, cookie hanya dikirim jika permintaan berasal dari situs yang sama persis.
        
    * `Lax`: Default yang seimbang. Cookie dikirim saat navigasi dari situs eksternal (misal: klik link), tapi tidak pada *sub-request* seperti `POST` dari situs lain.
        
    * `None`: Paling longgar. Cookie dikirim di semua konteks lintas situs, tetapi **wajib** digunakan bersama `secure: true`.
        
* `maxAge`: Menentukan masa aktif cookie dalam detik.
    

---

### \## 1. Lingkungan Development (Lokal) 💻

Di lingkungan development, prioritas kita adalah kemudahan dan kecepatan. Kita biasanya bekerja di [`localhost`](http://localhost), di mana frontend dan backend dianggap berasal dari "situs yang sama" (*same-site*).

**Tujuan**: Membuat cookie berfungsi di [`localhost`](http://localhost) tanpa konfigurasi yang rumit.

**Konfigurasi Kunci**:

* `domain`: Biarkan kosong. Browser akan otomatis mengaturnya ke [`localhost`](http://localhost).
    
* `sameSite`: `Lax` adalah pilihan terbaik. Aman dan berfungsi tanpa masalah.
    
* `secure`: Boleh `false` karena kita sering bekerja dengan [`http://localhost`](http://localhost).
    

Contoh Implementasi:

Kita akan menggunakan helper setCookie dan getCookie dari hono/cookie.

TypeScript

```typescript
// src/index.ts
import { Hono } from 'hono';
import { getCookie, setCookie } from 'hono/cookie';

const app = new Hono();

app.get('/login-dev', (c) => {
  const userInfo = { userId: '123', name: 'Dev User' };

  setCookie(c, 'session', JSON.stringify(userInfo), {
    path: '/',
    sameSite: 'Lax', // Pilihan aman dan mudah untuk localhost
    httpOnly: true,
    maxAge: 60 * 60 * 24, // 1 hari
  });

  return c.json({ message: 'Login successful for development' });
});

app.get('/profile-dev', (c) => {
  const session = getCookie(c, 'session');

  if (!session) {
    return c.json({ error: 'Not authenticated' }, 401);
  }

  return c.json({ data: JSON.parse(session) });
});

export default app;
```

---

### \## 2. Lingkungan Produksi 🌐

Di produksi, keamanan dan fungsionalitas di domain nyata adalah prioritas utama. Skenario umum adalah frontend di [`app.yourdomain.com`](http://app.yourdomain.com) dan backend di [`api.yourdomain.com`](http://api.yourdomain.com).

**Tujuan**: Memastikan cookie aman dan bisa dibagikan antar subdomain.

**Konfigurasi Kunci**:

* `domain`: Wajib diatur ke domain induk dengan titik di depan: `.`[`yourdomain.com`](http://yourdomain.com).
    
* `sameSite`: Wajib `None` agar browser mau mengirim cookie dari `app` ke `api`.
    
* `secure`: Wajib `true` karena `SameSite=None` memerlukannya dan untuk keamanan umum.
    

**Contoh Implementasi**:

TypeScript

```typescript
// src/index.ts
// ... (lanjutan dari kode sebelumnya)

app.post('/login-prod', (c) => {
  const userInfo = { userId: '456', role: 'admin' };

  setCookie(c, 'session', JSON.stringify(userInfo), {
    path: '/',
    domain: '.yourdomain.com', // Penting untuk berbagi antar subdomain
    sameSite: 'None',          // Wajib untuk permintaan cross-subdomain
    secure: true,              // Wajib untuk SameSite=None dan HTTPS
    httpOnly: true,
    maxAge: 60 * 60 * 24 * 7, // 7 hari
  });

  return c.json({ message: 'Login successful for production' });
});
```

---

### \## 3. Lingkungan Testing (Otomatis) 🧪

Dalam testing otomatis (misalnya dengan Vitest atau Jest), kita tidak memiliki browser sungguhan. Kita tidak menguji apakah browser *menyimpan* cookie, melainkan apakah server kita *mengirim header* `Set-Cookie` yang benar.

**Tujuan**: Memverifikasi bahwa respons dari server berisi header `Set-Cookie` dengan atribut yang tepat.

Konsep Kunci:

Kita akan membuat request ke aplikasi Hono kita dalam script tes, lalu memeriksa header Set-Cookie pada objek respons.

**Contoh Implementasi (dengan Vitest)**:

TypeScript

```typescript
// src/index.test.ts
import { describe, it, expect } from 'vitest';
import app from './index'; // Impor aplikasi Hono Anda

describe('Cookie Handling', () => {

  it('should set the correct development cookie header', async () => {
    const res = await app.request('/login-dev');
    
    // Ambil header Set-Cookie
    const cookieHeader = res.headers.get('Set-Cookie');

    // Verifikasi bahwa headernya ada dan berisi atribut yang benar
    expect(cookieHeader).not.toBeNull();
    expect(cookieHeader).toContain('session=');
    expect(cookieHeader).toContain('Path=/');
    expect(cookieHeader).toContain('SameSite=Lax');
    expect(cookieHeader).toContain('HttpOnly');
  });

  it('should set the correct production cookie header', async () => {
    const res = await app.request('/login-prod', { method: 'POST' });
    const cookieHeader = res.headers.get('Set-Cookie');

    expect(cookieHeader).not.toBeNull();
    expect(cookieHeader).toContain('Domain=.yourdomain.com');
    expect(cookieHeader).toContain('SameSite=None');
    expect(cookieHeader).toContain('Secure');
  });
});
```

---

### \## Implementasi Gabungan: Praktik Terbaik

Mengelola konfigurasi berbeda secara manual sangat tidak efisien. Solusinya adalah menggunakan variabel lingkungan (`process.env.NODE_ENV`) untuk mengatur atribut cookie secara dinamis.

Buat sebuah fungsi helper untuk membungkus logika ini.

TypeScript

```typescript
// src/utils/cookies.ts
import { Context } from 'hono';
import { setCookie as honoSetCookie } from 'hono/cookie';

type CookieOptions = {
  path?: string;
  domain?: string;
  sameSite?: 'Strict' | 'Lax' | 'None';
  secure?: boolean;
  httpOnly?: boolean;
  maxAge?: number;
};

export function setAppCookie(c: Context, name: string, value: string) {
  const isProd = process.env.NODE_ENV === 'production';

  const options: CookieOptions = {
    path: '/',
    httpOnly: true,
    // Atur berdasarkan lingkungan
    domain: isProd ? '.yourdomain.com' : undefined,
    sameSite: isProd ? 'None' : 'Lax',
    secure: isProd,
    maxAge: 60 * 60 * 24 * 7, // 7 hari
  };

  honoSetCookie(c, name, value, options);
}
```

Cara Menggunakannya:

Sekarang, Anda bisa menggunakan satu fungsi ini di seluruh aplikasi Anda.

TypeScript

```typescript
// src/index.ts
import { setAppCookie } from './utils/cookies';

// ...
app.post('/auth/login', (c) => {
    const user = { id: '789', username: 'unified-user' };
    setAppCookie(c, 'session', JSON.stringify(user));
    return c.json({ message: 'Login handled dynamically!' });
});
```

---

### \## Menghapus Cookie

Untuk logout, gunakan helper `deleteCookie`. Pastikan Anda menyertakan `path` dan `domain` yang sama agar browser tahu cookie mana yang harus dihapus.

TypeScript

```typescript
import { deleteCookie } from 'hono/cookie';

app.post('/auth/logout', (c) => {
    const isProd = process.env.NODE_ENV === 'production';
    
    deleteCookie(c, 'session', {
        path: '/',
        domain: isProd ? '.yourdomain.com' : undefined,
    });
    
    return c.json({ message: 'Logged out' });
});
```

Dengan mengikuti panduan ini, Anda dapat mengelola cookies di Hono secara efektif, aman, dan mudah di-maintain di semua lingkungan aplikasi Anda.
