Alat pengembang · URL encoder & decoder
WHATWG URL Standar vs RFC 3986: mengapa browser dan perpustakaan tidak setuju
· Latar belakang
pengkodean url standar alat pengembang
Ada dua definisi hidup tentang URL, dan keduanya sengaja tidak setuju. Posting ini menjelaskan mengapa WHATWG menulis standarnya sendiri, di mana keduanya berbeda dalam pengkodean dan penguraian, dan mana yang diikuti oleh kode Anda.
URL yang ditolak oleh perpustakaan ketat dan dengan senang hati dimuat oleh browser — satu string, dua putusan
String dengan garis miring terbalik di JavaScript mungkin ditafsirkan dengan lancar oleh browser Anda sebagai bagian dari jalur URL. String yang sama mencapai backend perpustakaan Python, dan menolak untuk menguraikannya karena garis miring terbalik tidak diperbolehkan. Satu URL, dua hasil berbeda. Tidak ada yang salah—mereka mengikuti standar yang berbeda. Standar WHATWG menjelaskan apa yang sebenarnya dilakukan browser dengan URL dunia nyata, termasuk cara browser menangani masukan yang salah. RFC 3986 mendefinisikan tata bahasa formal yang idealnya harus dipatuhi oleh URL. Banyak perpustakaan backend yang dibangun di atas RFC 3986 menerapkan tata bahasa tersebut dengan ketat dan menolak apa pun di luarnya.
Divergensi ini penting saat Anda memindahkan data antar lingkungan. Browser yang menerima URL mungkin gagal dalam validasi di alat backend. Memahami standar mana yang diterapkan kode Anda akan mencegah proses debug masalah hantu—URL berfungsi dengan baik di satu tempat tetapi gagal secara misterius di tempat lain tanpa alasan yang jelas.
Mengapa WHATWG dimulai kembali — menjelaskan apa yang sebenarnya dilakukan browser dengan format masukan yang salah, bukan yang valid
Kelompok Kerja WHATWG dibentuk pada 2004 untuk menstandardisasi cara browser sebenarnya menangani URL dalam praktiknya, daripada mendefinisikan aturan formal yang lebih ketat yang tidak akan diikuti oleh browser. RFC 2396 mendeskripsikan spesifikasi tata bahasa formal, namun dalam praktiknya browser tidak pernah mengikutinya dengan benar. Browser dunia nyata mengembangkan aturan praktis untuk menoleransi spasi, menangani karakter yang lolos, dan memulihkan masukan dalam format salah yang tidak diantisipasi atau diharapkan oleh RFC.
RFC 3986 tiba di 2005 dengan tata bahasa formal untuk URL yang disusun dengan baik dan persyaratan yang ketat. Browser menerapkan WHATWG; perpustakaan backend sering mengimplementasikan RFC 3986.
Kumpulan kode versus karakter yang dicadangkan — bagaimana daftar per komponen Standar URL berhubungan dengan kategori RFC 3986
RFC 3986 membagi karakter menjadi tiga kategori: dicadangkan, tidak dicadangkan, dan semua karakter lainnya yang harus dikodekan. Karakter khusus seperti titik dua, garis miring, tanda tanya, dan hash memiliki arti struktural dalam URL. Karakter yang tidak dicadangkan adalah huruf, angka, tanda hubung, garis bawah, titik, dan tanda gelombang; ini selalu aman. Segala sesuatu yang lain dikodekan persen sebagai byte. Standar ini memberikan satu aturan yang jelas: ketahui kategori mana yang termasuk dalam karakter Anda.
Standar WHATWG URL menggunakan pendekatan berbasis komponen. Ini menentukan aturan pengkodean yang berbeda untuk skema, otoritas, jalur, kueri, dan fragmen secara terpisah daripada menggunakan kategori global. Sebuah ampersand mungkin dikodekan dalam suatu jalur tetapi dibiarkan begitu saja dalam string kueri. Sebuah spasi selalu dikodekan, namun representasi persisnya bervariasi berdasarkan konteks. Desain per komponen ini jauh lebih cocok dengan perilaku browser, namun perlu diketahui bagian mana dari URL yang Anda enkode.
Toleransi kesalahan: spasi, garis miring terbalik, dan tab — memasukkan satu penolakan standar dan perbaikan lainnya
Spasi harus menjadi %20 berdasarkan kedua standar, namun browser secara diam-diam mengonversi spasi literal. Garis miring terbalik dilarang oleh kedua standar tersebut, namun beberapa browser memperlakukannya sebagai pemisah jalur. Tab, baris baru, dan karakter kontrol dilarang. WHATWG menentukan perilaku parser yang lunak: konversikan atau abaikan saja.
Karakter non-ASCII seperti é atau 中 harus dikodekan persen menggunakan pengkodean UTF-8. RFC 3986 sebenarnya tidak menentukan langkah pengkodean karakter itu sendiri; ia mengasumsikan byte ada tetapi tidak menjelaskan cara mendapatkannya dari teks. Standar WHATWG secara eksplisit memerlukan UTF-8: ubah string menjadi UTF-8 byte terlebih dahulu, lalu enkodekan persennya. Kedua standar tersebut mencapai hasil pengkodean yang sama, namun dimulai dari asumsi dasar yang berbeda dan tidak eksplisit mengenai hal yang sama.
Contoh praktis: menguraikan URL dengan garis miring terbalik dan spasi di kedua model — keluarannya dibandingkan
Ambil contoh string "https://example.com/café\ pencarian". Browser menemukan garis miring terbalik dan melihatnya sebagai karakter jalur; ia melihat spasi dan menyandikannya ke %20, menghasilkan sesuatu seperti https://example.com/café%5C%20search. Parser RFC 3986 segera menolak seluruh URL karena garis miring terbalik dilarang dan spasi dilarang. Browser melanjutkan penguraian; parser ketat berhenti sepenuhnya. Coba contoh lain: "https://user@example.com:80/path?q=a&b=c". Kedua standar mengidentifikasi info pengguna, host, port, jalur, dan kueri dengan jelas. Keduanya setuju sepenuhnya pada URL terstruktur ini. Ketidaksepakatan hanya terjadi pada masukan yang tidak biasa atau formatnya salah.
Buka encoder & decoder URL dan bandingkan mode RFC 3986 dengan perilaku browser. Tempelkan string dengan spasi, garis miring terbalik, atau huruf tepi lainnya. Alat ini menunjukkan dengan tepat bagaimana setiap standar mengubah masukan yang sama secara berbeda. Anda segera melihat mana yang lebih ketat dan apa yang dilakukan masing-masingnya.
Yang mana yang digunakan lingkungan Anda — browser dan Node mengikuti Standar URL; banyak perpustakaan server mengikuti RFC, dijelaskan secara umum
Di browser, JavaScript menggunakan Standar WHATWG URL secara default. URL API mengimplementasikannya dengan tepat. Node.js juga menggunakan WHATWG. Pustaka Python cenderung mengimplementasikan RFC 3986; urllib mengikutinya dengan cermat. Perpustakaan Java bervariasi; java.net.URL cenderung menuju RFC 3986. Peti url Rust mengikuti WHATWG. Net/url Go dipengaruhi oleh WHATWG. Ini adalah pola umum, bukan aturan mutlak.
Saat Anda membuat URL secara terprogram dan URL tersebut berpindah antara browser dan backend, pilih satu standar dan patuhi standar tersebut. Gunakan URL API browser untuk WHATWG. Jika perpustakaan backend Anda lebih ketat, itu bukan kontradiksi melainkan pilihan desain.
Apa yang tidak tercakup di sini — penguraian nama host, literal IPv6, dan pemrosesan IDNA
Penguraian nama host melibatkan IDNA, kode puny, dan aturan registrar yang melampaui penguraian URL sepenuhnya. Alamat IPv6, skema khusus seperti mailto: atau data:, dan komponen kosong merupakan topik terpisah yang berbeda dari pengkodean persen sepenuhnya. Batasan panjang domain dan validitas nama host berbeda-beda menurut registrar dan tidak relevan dengan diskusi ini. Juga dikecualikan: referensi relatif dan aturan penguraian khusus skema. Posting ini hanya berfokus pada pengkodean dan penguraian perbedaan.
Diskusi ini berfokus pada perbedaan pengkodean dan penguraian yang membedakan standar-standar ini. Tidak termasuk aturan nama host, aturan DNS, dan perilaku spesifik skema mencegah kebingungan tentang aturan pengkodean persen.
Kesimpulan: URL yang sama berlaku di satu dunia dan kesalahan di dunia lain — bagaimana encoder & decoder URL memberi Anda pengkodean RFC 3986 yang sederhana sehingga Anda dapat melihat apa yang dinormalisasi oleh browser
String URL yang sama dapat valid menurut satu standar dan tidak valid menurut standar lainnya. Keduanya benar dalam tujuan desainnya masing-masing. Saat mengkodekan komponen URL secara terprogram, gunakan alat yang tepat untuk lingkungan Anda. WHATWG menjelaskan apa yang sebenarnya dilakukan browser; RFC 3986 mendefinisikan tata bahasa formal. Encoder & decoder URL menunjukkan aturan RFC 3986 di samping perilaku browser sehingga Anda dapat melihat perbedaan yang tepat dan memilih mana yang sesuai dengan situasi Anda.
Masalah paling sering muncul ketika URL melintasi batas browser-ke-backend. Memahami perbedaan ini berarti menangani penyeberangan itu dengan sengaja, bukan secara tidak sengaja atau karena kesalahan.