Skip to content

YouTube Mati di Produksi: Header Referrer yang Menekan Referer

Adityo Guni Waluyo

Embed YouTube jalan di lokal, mati di produksi karena header Referrer-Policy same-origin. Satu atribut referrerPolicy per iframe menyelesaikannya.

Ringkasan

Iframe YouTube tidak muncul di produksi. Penyebabnya adalah header Referrer-Policy yang memotong referer. Penyelesaiannya dengan menambahkan atribut referrerPolicy di iframe.

Video YouTube di beranda tampil sebagai kotak gelap tanpa tombol putar, di produksi. Di mesin lokal, build yang sama jalan normal: poster muncul, tombol play ada, video main. Saya pindahkan tab ke produksi, refresh, dan hasilnya tetap kotak gelap. Tidak ada pesan error di console, tidak ada request yang gagal merah di network tab, cuma player yang menolak hidup.

Yang bikin bingung: aset lain aman. Gambar, font, JSON dari API, semuanya 200. Yang rusak hanya iframe YouTube, dan rusaknya seragam di tiga tempat sekaligus: embed video per entitas, daftar putar, dan hero slider di halaman depan.

Tebakan pertama: iframe-nya diblokir sesuatu. Saya cek header respons, tidak ada X-Frame-Options yang melarang, tidak ada CSP yang memotong frame-src. Tebakan kedua: ID video-nya salah atau videonya private. Saya buka URL embed-nya langsung di tab baru, videonya main. Tebakan ketiga: adblock di browser saya. Saya coba di profil browser bersih, hasilnya sama.

Yang akhirnya membuka jalan bukan ketiga tebakan itu, tapi satu pertanyaan berbeda: apa yang beda antara mesin lokal dan produksi? Jawaban yang paling tidak saya duga adalah header respons. Edge produksi mengirim Referrer-Policy: same-origin. Di mesin lokal, header itu tidak ada sama sekali, jadi browser memakai default-nya sendiri.

Header yang memotong referer, dan player yang menolak tanpa identitas

Direktif same-origin artinya browser tetap mengirim path dan query untuk request ke origin yang sama, tapi tidak mengirim header Referer untuk request lintas origin [1]. Iframe YouTube adalah request lintas origin, jadi praktis tidak ada referer yang terkirim.

Masalahnya, player YouTube memang butuh referer itu. Dokumentasi YouTube API Services menyebut klien yang memakai embedded player wajib menyediakan identitas lewat header HTTP Referer, dan klien cukup memastikan tidak memasang Referrer-Policy dengan cara yang menekan nilai referer tersebut. Rekomendasi resminya juga disebut eksplisit: strict-origin-when-cross-origin [3]. Tanpa identitas itu, player gagal mengonfigurasi dirinya dan berhenti di layar kosong.

Kenapa lokal aman? Karena tidak ada header yang menekan referer di sana, sehingga browser jatuh ke default strict-origin-when-cross-origin. Default itu tetap mengirim origin untuk request lintas origin, cukup untuk player [1][5]. Chrome sudah memindahkan default-nya ke policy ini sejak versi 85 justru untuk memotong kebocoran path dan query antar-origin, bukan untuk mematikan referer seluruhnya [2].

Satu atribut per iframe, bukan pelonggaran header situs

Perbaikannya tidak menyentuh konfigurasi server. Saya tambahkan atribut referrerPolicy di tiap iframe YouTube, dengan nilai strict-origin-when-cross-origin. Atribut referrerpolicy pada elemen iframe mendeklarasikan referer mana yang dikirim saat mengambil resource frame tersebut [4], jadi policy level elemen yang berlaku untuk request frame itu.

const embed = (
  <iframe
    src={`https://www.youtube-nocookie.com/embed/${videoId}`}
    title="Video YouTube"
    referrerPolicy="strict-origin-when-cross-origin"
    allow="encrypted-media; picture-in-picture"
    allowFullScreen
    className="aspect-video w-full"
  />
);

Saya sengaja tidak mengubah header situs jadi lebih longgar. Header same-origin itu tetap berguna untuk halaman lain: dia menahan path dan query supaya tidak bocor ke pihak ketiga. Kalau saya ganti header global demi satu iframe, seluruh situs ikut mengirim referer lebih banyak. Atribut per elemen jauh lebih sempit dampaknya, dan cuma berlaku untuk frame yang memang butuh.

Verifikasi di produksi: setelah deploy, player yang tadinya kotak gelap berubah jadi poster dengan tombol putar yang berfungsi, tanpa satu pun perubahan di nginx atau Cloudflare. Tiga permukaan yang rusak tadi pulih bersamaan, sesuai dugaan bahwa penyebabnya satu dan sama.

Catatan kecil yang saya pertahankan: embed tetap memakai domain youtube-nocookie.com, jadi cookie YouTube tidak dipasang sebelum video benar-benar diputar. Policy referer dan domain embed itu dua hal terpisah, dan keduanya bisa dipakai bersamaan.

Pelajaran yang saya bawa: header keamanan itu berlaku per fetch, bukan per situs. Header yang melindungi halaman bisa persis jadi header yang membuat frame pihak ketiga kelaparan identitas, dan solusi paling presisi biasanya ada di level elemen yang bermasalah, bukan di level server yang berlaku untuk semua.

Sumber

Artikel terkait