Screenshot 2026-02-02 at 10.17.28

Fizzy adalah aplikasi web untuk mengelola tiket yang dirilis oleh Basecamp. Saya menemukan masalah saat mengunggah berkas ke Fizzy yang dihosting di S3, di mana unggahan gagal karena kebijakan Content Security Policy (CSP) dan Cross-Origin Resource Sharing (CORS) yang belum terkonfigurasi dengan benar.

Cara mencari tahu akar masalah

Sebagai software engineer, lebih penting mengetahui cara mencari tahu akar masalah daripada hanya mengetahui solusinya. Pertama-tama, saya mengecek log di server menggunakan Kamal:

bin/kamal logs

Kemudian saya mensimulasikan mengunggah berkas di Fizzy untuk melihat log yang muncul.

Dari log tersebut, ternyata tidak ada informasi yang berguna, karena tidak ada error. Selanjutnya, saya membuka alat pengembang di browser (DevTools) dan memeriksa tab β€œConsole”. Dan benar ternyata di situ letaknya masalahnya, jadi masalah ini bukan di server melainkan di sisi klien.

Akar masalah

Content Security Policy (CSP) memblokir unggahan langsung ke bucket S3. Directive connect-src pada CSP hanya mengizinkan 'self', sehingga browser tidak bisa melakukan koneksi ke URL bucket S3 untuk upload file secara langsung.

Solusi yang Diterapkan

  • Menambahkan S3 ke CSP: Mengatur environment variable CSP_CONNECT_SRC pada konfigurasi deployment Kamal agar mencakup URL bucket S3.
  • Konfigurasi CORS S3: Menambahkan kebijakan CORS pada bucket S3 yang mengizinkan request dari domain Fizzy saya.

Temuan Tambahan: Masalah Cache PWA

Pengguna Mobile Safari yang mengakses melalui shortcut pada Home Screen (PWA) masih mengalami kegagalan upload meskipun CSP sudah diperbaiki. Penyebabnya adalah PWA menyimpan cache header CSP lama.

Solusi Sementara untuk Pengguna

Hapus aplikasi dari Home Screen lalu tambahkan kembali untuk membersihkan cache kebijakan CSP.

Perubahan Konfigurasi CSP di Kamal:

# File: config/deploy.yml

env:
  clear:
    CSP_CONNECT_SRC: https://<%= ENV.fetch("S3_BUCKET") %>.s3.<%= ENV.fetch("S3_REGION") %>.amazonaws.com

Konfigurasi CORS S3:

{
  "AllowedHeaders": ["*"],
  "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
  "AllowedOrigins": ["https://domain-fizzy-saya.com"],
  "ExposeHeaders": ["ETag", "Content-Type", "Content-Length", "Date"],
  "MaxAgeSeconds": 3600
}

Hasil Pengujian

  • βœ… Upload web desktop berfungsi
  • βœ… Upload Mobile Safari berfungsi (setelah cache dibersihkan)
  • βœ… Header CSP terverifikasi:
    connect-src 'self' https://bucket-fizzy-saya.s3.region.amazonaws.com
    

Dengan konfigurasi ini, unggahan berkas di Fizzy menggunakan S3 kini berfungsi dengan baik tanpa masalah CSP dan CORS.

Catatan mengenai pengalaman debugging ini

CSP dan CORS adalah dua mekanisme yang sangat jarang ditemui dalam pengembangan web sehari-hari karena biasanya setelah selesai dikonfigurasi, kita tidak akan menemuinya kembali hingga ada perubahan besar pada aplikasi web atau infrastruktur hostingnya.

Namun saya sangat menyukai pengalaman debugging ini karena AI membantu saya untuk memahami bagaimana cara berpikir yang sistematis untuk menentukan cara debugging yang efektif sehingga saya bisa menemukan akar masalah dan memperbaikinya dengan cepat.

Contohnya saya baru tahu cara debugging untuk mobile Safari menggunakan Inspector di Mac setelah membaca saran dari AI.

Kalau saya debugging 5 tahun lalu, mungkin saya akan menghabiskan waktu berjam-jam untuk browsing dan mencari tahu akar masalahnya saja (dengan beberapa jam tambahan terdistraksi dengan konten gaming di YouTube πŸ˜…).