Kesalahannya terlihat begini. Sebuah integrasi mengirim POST ke endpoint Anda. Endpoint-nya berfungsi, rutenya ada, semuanya lolos saat dicek manual. Tetapi di log muncul GET ke rute yang hanya menerima POST, dijawab dengan 404 atau 405.
Penyebabnya hampir selalu sama: di antara klien dan endpoint ada pengalihan berkode 301 atau 302. Dan kode-kode itu tidak mewajibkan klien mempertahankan metode.
Memeriksanya butuh sepuluh detik:
curl -sS -o /dev/null -L -d 'test=1' \
-w 'metode setelah pengalihan: %{method}\n' \
'https://httpbingo.org/redirect-to?url=/anything&status_code=301'
Keluaran: metode setelah pengalihan: GET. Body permintaan hilang bersamanya.
Ganti 301 menjadi 308 pada perintah yang sama, Anda akan mendapat POST. Bedanya hanya kode status.
Lima kode, dua sifat
Pengalihan dibedakan pada dua sumbu yang saling bebas: permanen atau sementara, dan apakah metode permintaan bertahan.
| Kode | Nama | Kepermanenan | Metode dipertahankan |
|---|---|---|---|
| 301 | Moved Permanently | permanen | tidak |
| 302 | Found | sementara | tidak |
| 303 | See Other | — | tidak, selalu GET |
| 307 | Temporary Redirect | sementara | ya |
| 308 | Permanent Redirect | permanen | ya |
Perhatikan simetrinya: 307 adalah 302 dengan jaminan metode, dan 308 adalah 301 dengan jaminan metode.
Dari mana kebingungan ini berasal
Secara formal, spesifikasi tidak pernah mewajibkan penggantian metode pada 301 dan 302. Namun peramban dan klien awal justru melakukan itu, dan ketika ketidaksesuaian itu disadari, seluruh web sudah bekerja dengan cara tersebut.
Maka perilaku itu dikodifikasi sebagai «diizinkan»: RFC 9110, spesifikasi semantik HTTP yang berlaku, mengizinkan klien mengganti POST menjadi GET pada 301 dan 302. Mengizinkan, tetapi tidak mewajibkan — artinya perilaku itu diserahkan kepada klien dan tidak bisa diandalkan.
Untuk menyediakan pilihan yang tegas, diperkenalkanlah 307 dan 308. Pada keduanya, mengganti metode dilarang: klien wajib mengulang permintaan dengan metode dan body yang sama. Kode 308 didefinisikan dalam RFC 7538 tersendiri, dengan uraian rujukan pada dokumentasi MDN.
Kesimpulan praktis: 301 dan 302 hanya aman di tempat yang permintaannya pasti GET. Di mana pun POST bisa datang, dibutuhkan 307 atau 308.
Jebakan kedua: pengalihan permanen di-cache
Yang ini bahkan lebih sering dilupakan daripada soal metode.
301 dan 308 menyatakan perpindahan bersifat permanen, dan peramban berhak menyimpannya di cache untuk waktu lama — kadang sampai pengguna membersihkan cache. Setelah itu server bahkan tidak ditanya lagi.
Dari sini muncul aturannya: 301 yang salah pasang nyaris mustahil dibatalkan. Anda akan memperbaiki konfigurasi, tetapi pengunjung yang sudah menerima respons lama akan terus dialihkan. Pada 302 dan 307 masalah ini tidak ada — keduanya bersifat sementara menurut definisi.
Saran praktis: selama skema perpindahan belum mapan, gunakan kode sementara. Menaikkan 302 menjadi 301 belakangan itu mudah; arah sebaliknya tidak.
Apa yang dipilih
Halaman pindah selamanya dan hanya menerima GET → 301. Kasus klasik: URL artikel lama, perubahan struktur alamat.
Sama, tetapi endpoint menerima POST → 308. Ini mencakup API, webhook, dan formulir.
Tujuan berubah sementara, hanya GET → 302.
Sementara, dan metode harus bertahan → 307.
Setelah POST, mengirim pengguna ke halaman hasil → 303. Ini pola POST/Redirect/GET: ia sengaja mengubah permintaan menjadi GET agar memuat ulang halaman tidak mengirim ulang formulir. Di sini penggantian metode adalah tujuannya, bukan cacat.
Di mana ini patah dalam praktik
Pengalihan http→https di depan API. Kasus paling sering dan paling menjengkelkan. Klien dikonfigurasi dengan http://, server menjawab 301 menunjuk ke https://, metodenya hilang. Gejalanya: GET di log pada rute POST. Diperbaiki dengan mengganti 301 menjadi 308.
Kanonikalisasi host. Pengalihan dari www ke non-www (atau sebaliknya) biasanya dipasang sebagai 301. Untuk halaman tidak masalah, tetapi jika di host yang sama ada API, persoalan yang persis sama berlaku.
Pengiriman formulir. Formulir dikirim ke alamat yang mengalihkan. Pengguna melihat «tidak terjadi apa-apa» karena datanya tak pernah sampai ke handler.
Webhook. Layanan eksternal mengirim POST ke alamat yang pernah Anda berikan. Jika alamat itu pindah di balik 301, webhook berhenti bekerja tanpa suara, sementara log pengirim menunjukkan respons sukses terhadap pengalihan.
Keempatnya punya tanda yang sama: endpoint-nya sehat tetapi permintaan tidak sampai dalam bentuk aslinya. Karena itu diagnosis berjalan ke arah yang keliru — orang mencari bug di handler, padahal letaknya di konfigurasi server web.
Mengapa pemendek tautan memakai 302
Tautan pendek hampir selalu mengembalikan 302, dan itu pilihan yang disengaja, bukan kelalaian.
Alasannya soal kepermanenan, bukan metode: tujuan sebuah tautan pendek bisa berubah. Memakai 301 berarti mengizinkan peramban menyimpan lompatan itu di cache selamanya, dan setelah tujuannya diubah sebagian pengunjung akan terus mendarat di alamat lama. Metode tidak relevan di sini — tautan pendek diikuti dengan permintaan GET.
Mekanismenya sendiri dibahas terpisah di cara kerja pemendek tautan.
Yang tidak diubah oleh pilihan kode
Dua salah kaprah yang tersebar luas.
Bobot tautan. Memilih antara 301 dan 302 tidak memengaruhi penerusan bobot — Google sudah memastikannya pada 2016. Uraian lengkapnya ada di apakah tautan pendek meneruskan bobot tautan?.
Pemilihan URL kanonis. Pengalihan dan rel="canonical" menyelesaikan masalah berbeda: pengalihan menarik satu alamat dari peredaran, canonical membiarkan keduanya dapat diakses dan menunjuk mana yang utama. Kapan memakai yang mana dijelaskan di panduan canonical.
Daftar periksa singkat
- Pada rute yang menerima
POST, gunakan 307 atau 308, bukan 302 dan 301. - Periksa pengalihan http→https secara terpisah: biasanya dipasang dengan aturan menyeluruh dan API-nya terlupakan.
- Selama skema belum mapan, pakai kode sementara. 301 dan 308 di-cache dan nyaris tak bisa dibatalkan.
- Setelah memproses formulir, gunakan 303 — itu perilaku yang benar, bukan kesalahan.
- Pendekkan rantai menjadi satu lompatan: setiap lompatan tambahan menambah latensi sekaligus risiko.