Enkoder dan Dekoder URL
Komponen juga meng-escape / ? & = — pakai untuk satu nilai query. URL lengkap membiarkannya utuh sehingga alamatnya tetap valid.
Apa pun yang Anda masukkan di sini tidak disimpan, dicatat, atau dibagikan.
Enkode teks agar aman dipakai di URL, atau kembalikan lagi. Pilih apakah Anda mengenkode satu nilai query atau URL utuh, karena keduanya butuh escape yang berbeda.
Cara memakai
- Pilih enkode atau dekode.
- Saat mengenkode, pilih Komponen untuk satu nilai atau URL lengkap untuk alamat utuh.
- Tempel teks Anda lalu salin hasilnya.
Mengapa ada dua mode
RFC 3986 membagi karakter yang bisa muncul di URL menjadi dua kelompok. Karakter tak tercadang - huruf, angka, dan empat tanda - _ . ~ - selalu berarti dirinya sendiri dan tidak pernah di-encode. Karakter tercadang punya makna struktural: titik dua setelah skema, garis miring di antara segmen path, tanda tanya yang membuka query, ampersand dan sama dengan yang memisahkan parameter, serta tanda pagar yang memulai fragmen.
Kedua mode hanya berbeda dalam cara menangani kelompok kedua itu. Mode komponen juga meng-escape karakter tercadang, yang Anda perlukan saat teks dimasukkan ke satu slot - satu nilai query, satu segmen path - dan tidak boleh dibaca sebagai struktur. Mode URL penuh membiarkannya, sehingga seluruh alamat tetap utuh dengan skema, garis miring, dan pemisahnya masih berfungsi.
Memakai mode yang salah biasanya langsung terlihat. Masukkan seluruh alamat ke mode komponen, dan https://example.com menjadi https%3A%2F%2Fexample.com yang tidak bisa dibuka lagi. Masukkan satu nilai ke mode URL penuh, dan ampersand yang terselip di dalamnya diam-diam memecah parameter Anda menjadi dua.
Karakter yang sering bermasalah
Spasi adalah yang pertama kali ditemui orang. Di path atau query, spasi menjadi %20. Pada pengiriman formulir HTML, spasi menjadi +, karena begitulah aturan application/x-www-form-urlencoded yang lebih lama, dan kedua konvensi masih dipakai setiap hari. Itulah sebabnya ada opsi plus-sebagai-spasi saat decoding: aktifkan untuk query string formulir, matikan untuk path, karena di path + adalah tanda plus sungguhan dan mengubahnya menjadi spasi akan merusak nilainya.
Ampersand dan tanda sama dengan wajib di-escape di dalam nilai, atau server akan memotong query di tempat yang salah - contoh klasiknya adalah kata kunci pencarian atau blob Base64 yang kebetulan mengandungnya. Tanda pagar tidak pernah dikirim ke server sama sekali: semua setelahnya adalah fragmen yang ditangani browser, sehingga # yang tidak di-escape di dalam parameter diam-diam memotong request.
Garis miring di dalam nilai perlu perhatian khusus. Jika di-encode sebagai %2F, hasilnya sah, tetapi cukup banyak server dan proxy mendekodenya sebelum routing, sehingga tetap bisa dibaca sebagai pemisah path. Jika sebuah nilai bisa berisi garis miring, menaruhnya di query alih-alih path akan menghindari masalah ini sepenuhnya.
Encoding ganda
Percent-encoding tidak idempoten. Tanda persen sendiri adalah karakter yang perlu di-encode, sehingga menjadi %25, dan meng-encode string yang sudah di-encode mengubah %20 menjadi %2520. Urutan itu adalah jejak nyata URL yang melewati satu langkah encoding terlalu banyak, dan sekali Anda mengenalinya, Anda akan melihatnya di mana-mana.
Ini terjadi ketika nilai di-encode oleh kode aplikasi lalu di-encode lagi oleh framework, klien HTTP, atau template yang mengira menerima teks mentah. Perbaikannya adalah menghapus salah satu dari dua langkah itu, bukan mendekode dua kali di sisi penerima, yang hanya memindahkan bug. Mendekode di sini sekali per lapisan sambil memperhatikan apakah %2520 menjadi %20 lalu spasi akan menunjukkan berapa lapisan yang sebenarnya ada.
Karakter non-ASCII, dan yang tidak ditangani percent-encoding
Teks diubah ke UTF-8 terlebih dahulu, lalu setiap byte-nya di-percent-encode, sehingga satu karakter Jepang menjadi tiga urutan escape, bukan satu. Inilah yang diwajibkan standar URL, dan itulah sebabnya bahasa Jepang, Mandarin, Korea, huruf Latin beraksen, dan emoji bisa bolak-balik dengan bersih di sini.
Nama domain adalah pengecualian, dan perbedaannya penting. Bagian host dari URL tidak di-percent-encode: domain internasional dikonversi dengan Punycode, menghasilkan nama yang diawali xn--. Meng-percent-encode nama host menghasilkan sesuatu yang tampak ter-encode tetapi tidak mengarah ke mana pun. Alat ini hanya menangani path, query, dan fragmen.
Anatomi sebuah URL
URL punya lebih banyak bagian daripada yang biasa dipakai kebanyakan orang: skema, bagian userinfo yang opsional, host, port opsional, path, query, dan fragment. Ditulis lengkap, https://user:[email protected]:8443/a/b?x=1#top memuat semuanya. Bentuk userinfo sudah tidak dianjurkan untuk HTTP dan peramban menghapusnya atau memberi peringatan, justru karena bentuk itu pernah dipakai agar host yang berbahaya tampak seperti host yang sudah dikenal.
Tiap bagian punya aturan berbeda. Host tidak membedakan huruf besar-kecil dan tidak boleh mengandung percent-encoding; path membedakan huruf besar-kecil di sebagian besar server; query tidak punya tata bahasa baku selain berupa string, dan pasangan key=value yang dipisah ampersand hanyalah kebiasaan, bukan spesifikasi; sedangkan fragment tidak pernah meninggalkan peramban.
Resolusi rujukan relatif adalah bagian yang sering mengejutkan. Tautan ke b/c dari /a/page akan menjadi /a/b/c, tetapi dari /a/page hasilnya /a/page/b/c - garis miring di akhir mengubah basisnya. Inilah sebabnya satu garis miring yang kurang atau berlebih bisa merusak seluruh aset relatif di sebuah halaman, dan sebabnya pengalihan kanonis antara kedua bentuk itu layak disiapkan sekali dengan benar.
Query string punya kebiasaan, bukan aturan
Tidak ada standar untuk menyatakan array di dalam query string, itulah sebabnya setiap framework melakukannya dengan caranya sendiri: tags=a&tags=b mengulang kuncinya, tags[]=a&tags[]=b menambahkan kurung siku, dan tags=a,b memakai pemisah. Ketiganya sama-sama URL yang sah, dan masing-masing diurai menjadi sesuatu yang berbeda tergantung pustaka di sisi penerima.
Hal yang sama berlaku untuk struktur bersarang, nilai boolean, dan nilai kosong. Apakah flag= berarti false, string kosong, atau ada tetapi tanpa nilai? Jawabannya tergantung keputusan parser yang menerimanya, jadi API yang memedulikan hal ini sebaiknya mendokumentasikannya dan melakukan validasi, bukan berasumsi.
Di JavaScript, URLSearchParams menangani encoding dan kunci berulang dengan benar, sehingga lebih baik dipakai daripada merangkai string secara manual. Perlu dicatat bahwa ia mengodekan spasi menjadi tanda plus, mengikuti kebiasaan formulir, sedangkan encodeURIComponent menghasilkan %20 - keduanya sama-sama terbaca sebagai spasi di query string, tetapi hanya salah satunya yang begitu di dalam path.
Masalah keamanan yang bersarang di penanganan URL
Open redirect adalah endpoint yang mengirim pengunjung ke URL yang diberikan lewat parameter tanpa memeriksanya. Teknik ini dipakai agar tautan phishing bermula di domain yang dipercaya korban, dan sampai sekarang masih sering muncul dalam tinjauan keamanan. Perbaikannya adalah daftar tujuan yang diizinkan, atau hanya menerima path alih-alih URL absolut.
Server-side request forgery adalah masalah sejenis yang diarahkan ke dalam: server mengambil URL yang diberikan pengguna, lalu pengguna memberikan alamat internal, endpoint metadata cloud, atau pengalihan menuju keduanya. Perbedaan cara mengurai antarpustaka telah berulang kali dieksploitasi di sini, sebab dua parser bisa berbeda pendapat soal host mana yang sebenarnya dirujuk oleh sebuah URL yang dirancang khusus.
Serangan homograf memanfaatkan nama domain internasional, di mana karakter Kiril dan Latin yang tampil identik menghasilkan host yang berbeda. Peramban bertahan dengan menampilkan bentuk punycode ketika sebuah nama mencampur beberapa sistem tulisan, dan itulah sebabnya tautan yang mencurigakan kadang terlihat diawali xn-- di bilah alamat. Awalan itu layak dikenali.
URL kanonis, duplikat, dan parameter pelacakan
Halaman yang sama biasanya bisa dijangkau lewat beberapa alamat: dengan dan tanpa www, dengan dan tanpa garis miring di akhir, lewat http dan https, dengan akhiran index.html, serta dengan sejumlah parameter pelacakan yang ditempelkan. Di mata mesin pencari, semua itu bisa tampak seperti halaman terpisah dengan isi yang sama, sehingga otoritas yang sudah dikumpulkan halaman tersebut jadi terpecah.
Ada dua mekanisme untuk mengatasinya. Pengalihan 301 menyelesaikan variasi struktural dengan memilih satu bentuk dan mengarahkan semua bentuk lain ke sana. Elemen link canonical di dalam head menyebutkan alamat yang dikehendaki untuk variasi yang tidak bisa dialihkan, yang umumnya adalah kasus berparameter.
Parameter pelacakan perlu catatan tersendiri: utm_source dan kawan-kawannya ditambahkan oleh sistem perujuk dan menghasilkan URL yang berbeda untuk setiap kampanye. Tempatnya ada di analitik, bukan di URL kanonis, dan menghapusnya di sisi klien setelah tercatat akan menjaga tautan yang dibagikan tetap bersih. Hal yang sama berlaku untuk parameter fbclid dan gclid yang ditambahkan sebagian platform secara otomatis.
Merancang path yang tetap relevan
URL adalah sebuah janji, karena orang lain menautkannya dan Anda tidak mengendalikan tautan-tautan itu. Karena itu buatlah path yang menggambarkan sumber dayanya, bukan implementasinya: /guides/subnetting alih-alih /page.php?id=4718, dan tanpa ekstensi berkas yang mengikat alamat itu pada teknologi yang melayaninya.
Gunakan huruf kecil semua dan tanda hubung. Karena server membedakan huruf besar-kecil, /About dan /about bisa menjadi dua halaman berbeda, dan itu tidak pernah disengaja; sementara tanda hubung adalah pemisah kata yang lazim dalam sebuah slug. Hindari tanggal di dalam path kecuali isinya memang sebuah arsip, sebab /2024/pricing terlihat usang setahun kemudian meski isinya masih mutakhir.
Ketika sebuah URL memang harus berubah, alihkan URL lama secara permanen dan pertahankan pengalihan itu tanpa batas waktu. Merusak tautan adalah satu-satunya keputusan dalam daftar ini yang tidak bisa Anda batalkan dari sisi Anda, sebab tautan yang paling penting justru berada di situs-situs yang belum pernah Anda dengar namanya.
Pertanyaan umum
- Apa beda Komponen dan URL lengkap?
- Komponen memakai encodeURIComponent dan ikut meng-escape karakter khusus / ? & = :, yang tepat untuk satu nilai query atau satu segmen jalur. URL lengkap memakai encodeURI dan membiarkan karakter itu utuh supaya alamatnya tetap valid. Mengenkode URL utuh dengan mode Komponen mengubah https:// menjadi https%3A%2F%2F dan merusaknya.
- Mana yang harus saya pakai untuk parameter query?
- Komponen. Nilai yang mengandung & atau = harus di-escape, kalau tidak server akan membacanya sebagai pemisah dan memotong parameter Anda di tempat yang salah.
- Kenapa dekode gagal dengan escape yang rusak?
- Tanda persen harus diikuti tepat dua digit heksadesimal. Tanda % yang berdiri sendiri (seperti pada "100%") atau urutan terpotong seperti %E4%B8 tidak valid, jadi dekode berhenti alih-alih menebak.
- Kapan saya perlu opsi + sebagai spasi?
- Pengiriman formulir mengenkode spasi sebagai + alih-alih %20. Aktifkan opsi ini saat mendekode query string dari formulir HTML. Matikan untuk segmen jalur, tempat + berarti tanda tambah yang sesungguhnya.
- Apakah ini menangani teks non-Latin?
- Ya. Teks diubah ke UTF-8 sebelum percent-encoding, jadi bahasa Jepang, Tionghoa, Korea, dan emoji tetap utuh bolak-balik.
Terakhir diperbarui:
Sertakan langkah, hasil yang diharapkan, dan hasil sebenarnya. Hapus rahasia dan data pribadi.
