Kode Status HTTP yang Sebenarnya Menyerang Anda — 301 vs 302, 401 vs 403, dan Area 5xx yang Berbahaya
Bukan kamus. Panduan fokus tentang kode status HTTP yang menyebabkan bug di produksi nyata — redirect yang salah yang kini disimpan secara tak terbatas, kekeliruan antara 401/403 yang mengungkapkan logika autentikasi Anda, 429 tanpa Retry-After, dan kebingungan antara 503 dan 5-04 yang membuat Anda memperbaiki lapisan yang salah.
Anda telah mengirimkan redirect dengan tipe yang salah. Sekarang setiap browser yang mengalami hal tersebut sebelum Anda menyadari telah menyimpannya secara permanen, dan satu-satunya cara memperbaikinya adalah menunggu kadaluwarsa cache atau meminta pengguna untuk menghapus riwayat browser mereka. Itu adalah kode 301.
Ini bukan kamus kode status — ada banyak kamus seperti itu. Ini panduan yang Anda butuhkan setelah membaca tabel dan tetap mengirimkan kode yang salah. Kita sedang melalui kasus-kasus yang menyebabkan bug nyata: cache permanen saat yang diinginkan adalah sementara, kesalahan autentikasi yang mengungkapkan informasi, respons batas laju yang tidak ditangani dengan benar, dan timeout gateway yang menunjuk ke lapisan yang salah.
301 vs 302 vs 307 vs 308: Matriks Redirect
Kesalahan yang dilakukan setiap orang setidaknya sekali: Anda menggunakan 301 Moved Permanently saat menguji restrukturisasi URL. Ini bekerja. Anda melanjutkan. Lalu Anda restrukturisasi lagi. Dan sekarang sebagian pengguna Anda — siapa saja yang mengunjungi sebelum perubahan kedua — dikirim ke tujuan lama secara permanen, dan disimpan langsung di browser mereka.
301 adalah permanen dan menyimpan cache secara agresif. Browser menetapkan TTL redirect yang disimpan ke hampir tak terbatas kecuali Anda menetapkan Cache-Control header. Tidak ada cara programatis untuk membatalkan cache dari browser pengguna. Jika Anda masih memperbaiki struktur URL, gunakan 302.
Masalah pelestarian metode adalah makhluk yang berbeda. Ketika browser mengikuti 301 atau 302, ia mungkin (dan dalam praktiknya, hampir selalu dilakukan) mengurangi POST menjadi GET pada redirect. Ini secara teknis merupakan pelanggaran spesifikasi HTTP/1.0, tetapi browser telah menormalisasi hal ini sejak lama sehingga RFC 7231 mengakui perilakunya sebagai standar. Jika Anda mengalihkan POST — misalnya, setelah pengiriman formulir — dan Anda mengharapkan metode tetap terjaga, Anda perlu menggunakan 307 atau 308.
| Kode | Permanen? | Menjaga Metode? | Gunakan untuk |
|---|---|---|---|
| 301 | Ya | Tidak (POST → GET) | Pindah URL permanen di mana GET cukup setelah redirect |
| 302 | TIDAK | Tidak (POST → GET) | Redirect sementara, fitur flag, uji A/B |
| 307 | TIDAK | Ya | Redirect sementara di mana metode harus dipertahankan |
| 308 | Ya | Ya | Redirect permanen di mana metode harus dipertahankan |
Dukungan 308 saat ini sangat kuat — Chrome, Firefox, Safari, dan Edge semua menangani hal ini dengan benar. Kecuali: beberapa klien API dan library HTTP yang lebih tua masih tidak mengikuti 308 dengan benar, jadi jika Anda mengalihkan lalu lintas mesin ke mesin dan tidak mengontrol klien maupun library HTTP-nya, uji secara eksplisit.
401 vs 403: Autentikasi vs Otorisasi
401 berarti “Anda belum mengidentifikasi diri Anda.” Spesifikasi memerlukan agar terdapat WWW-Authenticate header yang memberi tahu klien bagaimana mengautentikasi. Ini adalah kode yang benar ketika tidak ada sesi yang valid, tidak ada token, atau token telah kedaluwarsa.
403 berarti “Saya tahu siapa Anda, dan jawabannya adalah tidak.” Pengguna telah diotentikasi tetapi kurang memiliki izin. Mengembalikan 403 pada token yang kedaluwarsa adalah salah — itu adalah 401. Mengembalikan 401 pada permintaan dengan izin yang valid tetapi tidak cukup juga salah, dan lebih buruk lagi, ini membingungkan debugging autentikasi Anda: Anda akan mencari kehilangan kredensial saat sebenarnya masalahnya adalah penugasan peran.
Argumen keamanan untuk mengembalikan 404 daripada 403 adalah nyata. Jika API Anda mengembalikan 403 pada GET /admin/users, Anda telah memberi tahu setiap penyerang bahwa endpoint tersebut ada dan mereka perlu hak akses lebih tinggi untuk mengaksesnya. Mengembalikan 404 justru tidak mengungkapkan informasi tentang keberadaan sumber daya. Ini adalah keputusan yang harus dipertimbangkan: 403 secara teknis benar dan lebih mudah untuk debugging; 404 adalah pilihan yang lebih aman untuk endpoint yang sensitif di mana keberadaan harus dihindari.
429: Batas laju tidak berguna tanpa Retry-After
Respons 429 tanpa Retry-After header adalah kotak hitam. Klien tahu bahwa mereka telah terlalu banyak mengakses. Mereka tidak tahu apakah mereka harus menunggu 100ms atau 24 jam. Sebagian besar implementasi klien akan mencoba ulang segera (menekan rate limiter Anda) atau menyerah sepenuhnya.
Retry-After mengambil nilai integer (detik yang harus ditunggu) atau HTTP-date (kapan harus mencoba kembali):
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1749254400
Itu X-RateLimit-* header tidak ada dalam RFC — mereka adalah standar de facto dari API GitHub yang diadopsi oleh semua orang. Sertakan bersama dengan Retry-After. Triad Limit/Remaining/Reset memberi tahu klien di mana mereka berada sebelum mencapai batas, yang lebih berguna daripada hanya tahu bahwa mereka telah mencapai batas.
Satu hal yang perlu ditekankan: Retry-After juga valid pada respons 503, dan berarti hal yang sama — “kembali dalam jumlah detik ini.” Jika layanan Anda sementara tidak tersedia karena jendela pemeliharaan, kirim 503 dengan Retry-After alih-alih hanya menutup koneksi.
503 vs 504: Di mana Kegagalan Terjadi?
Kedua kode ini terlihat mirip tetapi menunjuk ke lapisan kegagalan yang berbeda, dan membingungkan keduanya akan mengarahkan debugging ke arah yang salah.
503 Layanan Tidak Tersedia berarti server yang Anda capai saat ini tidak dapat menangani permintaan — ia terlalu berat, sedang dalam mode pemeliharaan, atau ketergantungan backend down. Server itu sendiri telah merespons; ia hanya menolak pekerjaan tersebut.
504 Gateway Timeout berarti proxy atau gateway (load balancer Anda, nginx, API gateway, CDN) mencoba menghubungi server upstream dan tidak mendapatkan respons dalam waktu yang ditentukan. Server yang Anda capai masih hidup. Yang ada di belakangnya tidak merespons.
Dalam praktiknya: jika Anda berada di balik nginx dan server aplikasi Anda (Node, Rails, Django, atau apa saja) crash, Anda mendapatkan 502 Bad Gateway — nginx mendapatkan respons tetapi responsnya tidak valid. Jika server aplikasi berhenti merespons secara total, Anda mendapatkan 504. Jika Anda secara sengaja mengembalikan kesalahan dari lapisan aplikasi, Anda mendapatkan 503. Perbedaan ini penting saat Anda melakukan triage: 504 berarti periksa layanan upstream, konfigurasi timeout Anda, dan jaringan Anda. 503 berarti periksa aplikasi itu sendiri.
422 vs 400: Kesalahan Validasi Memiliki Kode Sendiri
400 Permintaan Buruk digunakan untuk permintaan yang tidak dapat diproses oleh server — JSON yang tidak valid, sintaks query string yang salah, atau header yang hilang. Ini adalah masalah struktur.
422 Entity Tidak Dapat Diproses digunakan untuk permintaan yang dipahami oleh server tetapi tidak dapat diaktifkan karena data gagal validasi — rentang tanggal di mana awalnya setelah akhir, field email dengan alamat yang tidak valid, field jumlah yang negatif. Permintaan ini secara sintaksis benar. Semantiknya salah.
Sebagian besar API menggabungkan keduanya ke dalam 400 dan menyembunyikan detail validasi dalam tubuh respons. Ini bekerja, tetapi membuat pengaturan kesalahan di sisi klien menjadi lebih sulit: klien harus memarsing tubuh respons untuk tahu apakah itu kesalahan parsing atau kesalahan validasi. Menggunakan 422 untuk kesalahan validasi memungkinkan klien untuk mengandalkan kode status. Rails telah melakukannya dengan benar sejak lama; spesifikasi JSON:API juga menentukan 422 untuk kesalahan validasi.
Nuansa satu-satunya: 422 didefinisikan dalam WebDAV (RFC 4918), bukan dalam spesifikasi HTTP utama. Dalam praktiknya ini tidak penting — setiap klien dan server HTTP menangani hal ini dengan baik — tetapi Anda akan menemui seorang penganut yang berpendapat Anda harus menggunakan 400 sebagai gantinya. Mereka tidak salah secara teknis. Tetapi 422 lebih spesifik dan lebih luas dipahami.
204 vs 200 dengan tubuh kosong: Salah Satu Benar untuk DELETE
Ketika DELETE berhasil, respons yang benar adalah 204 Tidak Ada Isi — bukan 200 dengan tubuh kosong, dan bukan 200 dengan {"success": true}.
204 adalah sinyal eksplisit bahwa “ini berhasil dan tidak ada tubuh respons yang dimaksud.” 200 dengan tubuh kosong secara teknis valid, tetapi ambigu — klien tidak tahu apakah tubuh seharusnya ada dan hilang, atau apakah ketidakhadiran itu sengaja. 204 menghilangkan ambiguitas tersebut.
Logika yang sama berlaku untuk PUT dan PATCH ketika Anda tidak mengembalikan sumber daya yang diperbarui. Jika API mengembalikan objek yang diperbarui setelah PATCH, gunakan 200. Jika tidak, gunakan 204. Jangan kembalikan 200 dengan tubuh {} atau null — itu adalah 204 yang memakai kostum.
Satu hal yang perlu diperhatikan: 204 tidak boleh mencakup tubuh pesan menurut RFC 9110. Jika Anda mengembalikan 204 dan secara tidak sengaja mencakup tubuh (beberapa kerangka kerja memungkinkan hal ini), beberapa klien HTTP akan menangani hal ini secara baik, tetapi yang lain tidak. Hapus tubuh dari handler respons Anda, bukan hanya dari niat Anda.
Referensi Cepat: Kode-Kode yang Menyerang dan Mengapa
| Kode | Arti | Kesalahan Umum | Solusi |
|---|---|---|---|
| 301 | Redirect permanen | Menggunakan selama pengujian — sekarang ini disimpan selamanya | Gunakan 302 hingga redirect dikonfirmasi permanen |
| 302 | Redirect sementara | POST turun ke GET saat diikuti | Gunakan 307 jika metode harus dipertahankan |
| 307 | Redirect sementara (amana metode) | Bingung dengan 302 | Gunakan saat mengalihkan POST/PUT/PATCH secara sementara |
| 308 | Redirect permanen (amana metode) | Dilewatkan dalam favorit 301 | Gunakan alih-alih 301 saat metode penting |
| 400 | Permintaan tidak valid (kesalahan parsing) | Digunakan untuk kesalahan validasi juga | Gunakan 422 untuk kesalahan validasi semantik |
| 401 | Tidak terautentikasi | Dikembalikan saat pengguna tidak memiliki izin (seharusnya 403) | Kembalikan 401 hanya saat kredensial hilang atau kedaluwarsa |
| 403 | Dilarang | Dikembalikan alih-alih 404 untuk endpoint yang sensitif terhadap keamanan | Pertimbangkan 404 saat menyembunyikan keberadaan endpoint penting |
| 422 | Entitas tidak dapat diproses | Dikompresi ke dalam 400 | Gunakan untuk kesalahan validasi di mana tubuh dapat diparsing |
| 429 | Dibatasi laju | Tidak ada header Retry-After | Selalu sertakan header Retry-After + X-RateLimit-* |
| 503 | Tidak tersedia | Bingung dengan 504 | Gunakan saat server yang dicapai tidak dapat menangani permintaan |
| 504 | Timeout gateway | Bingung dengan 503 | Periksa layanan upstream, bukan gateway |
| 204 | Tidak ada konten | Mengembalikan 200 dengan tubuh kosong alih-alih | Gunakan 204 untuk DELETE/PUT/PATCH yang berhasil tanpa tubuh respons |
Jika Anda perlu cepat mencari kode status saat debugging, IO Tools memiliki Lookup Kode Status HTTP yang mencakup rentang lengkap dengan deskripsi dan catatan tentang kapan harus menggunakan setiap kode.
Polanya di Balik Semua Ini
Kebanyakan kesalahan ini berasal dari tempat yang sama: menganggap kode status sebagai kategori yang longgar (“4xx adalah kesalahan klien, 5xx adalah kesalahan server, selesai”) daripada sebagai protokol dengan semantik khusus. Semantik ini penting karena klien — browser, library HTTP, CDN, alat pemantauan — sebenarnya mengandalkan kode tersebut. CDN tidak akan menyimpan 200 dan 204 dengan cara yang sama. Klien HTTP tidak akan mencoba ulang 400 dan 503 dengan logika yang sama. Browser tidak akan menyimpan 302 dan 301 dengan TTL yang sama.
Gunakan kode yang benar. Biaya overheadnya nol. Manfaat debugging saat sesuatu gagal adalah tidak.
Anda mungkin juga menyukai
Instal Ekstensi Kami
Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat
恵 Papan Skor Telah Tiba!
Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!
Alat Wajib Coba
Lihat semua Pendatang baru
Lihat semuaMemperbarui: Kita alat terbaru ditambahkan pada 8 Juni 2026
