Bahasa Indonesia

Alat pengembang · URL encoder & decoder

escape() vs encodeURIComponent: caranya JavaScript'S URL pengkodean berevolusi

· Latar belakang

javascript pengkodean url sejarah

Tiga generasi fungsi pengkodean JavaScript URL
Ilustrasi vektor ToolAcre asli

JavaScript telah memiliki tiga generasi fungsi pengkodean URL, dan yang tertua masih tersembunyi dalam kode produksi. Posting ini menjelaskan kesalahan escape(), mengapa ES3 menambahkan fungsi URI dan mengapa fungsi tersebut dipertahankan! * ' ( ).

%u20AC dalam log lama — sidik jari escape() yang jelas dan kegagalan penguraian kode yang ditimbulkannya

File JavaScript lama berisi panggilan pengkodean URL menggunakan fungsi escape() yang tidak digunakan lagi. Output dalam file log atau pesan kesalahan mencakup urutan %u20AC—sidik jari yang jelas dari fungsi escape() yang tidak digunakan lagi. Urutan ini tidak cocok dengan pengkodean URL standar apa pun, dan dekoder yang dibuat berdasarkan aturan RFC 3986 atau WHATWG tidak akan mengenalinya. Data tidak bisa bolak-balik melalui alat modern. Ini adalah tanda umum kode yang ada sebelum ES3 dan belum diperbarui sejak tahun 1990an.

Fungsi escape() dirancang di era Netscape, sebelum JavaScript memiliki standar atau aturan pengkodean URL formal. Ini mengkodekan sebagian besar karakter non-ASCII menggunakan notasi %uXXXX, kode heksadesimal empat digit yang tidak digunakan orang lain dan tidak ada standar yang ditentukan di mana pun. Hal ini masuk akal untuk penggunaan satu kali dalam browser, namun hal ini merusak kompatibilitas dengan standar URL dan membuat data tidak mungkin didekode di tempat lain.

escape() dan unescape(): desain era Netscape — asumsi Latin-1, penemuan %uXXXX dan mengapa tidak pernah sesuai dengan standar apa pun

escape() dan unescape() menganggap inputnya adalah Latin-1 (ISO 8859-1), pengkodean karakter yang ada sebelum UTF-8 dan Unicode. Mereka mengonversi setiap karakter menjadi kode heksadesimal, menggunakan %XX untuk karakter Latin-1 bit tinggi dan %uXXXX untuk semua karakter di luar Latin-1. Karakter non-Latin-1 seperti emoji tidak dapat direpresentasikan sama sekali. Fungsinya sederhana dan cepat, tetapi juga sepenuhnya salah untuk kasus penggunaan modern mana pun.

Kedua fungsi tersebut ditambahkan ke JavaScript sebelum standar ada. Mereka tidak digunakan lagi segera setelah ES3 memperkenalkan pengkodean URL yang tepat di 1999. Mereka tetap berada di JavaScript untuk kompatibilitas ke belakang—menghapusnya akan merusak kode kuno. Namun kode baru apa pun tidak boleh menggunakannya. Mereka adalah peninggalan warisan.

ES3 (1999) menambahkan encodeURI dan encodeURIComponent — UTF-8 persen pengkodean selaras dengan RFC 2396

ES3 memperkenalkan dua fungsi: encodeURI dan encodeURIComponent. Keduanya melakukan pengkodean UTF-8 persen: mengonversi karakter non-ASCII menjadi UTF-8 byte, lalu menulis setiap byte sebagai %HH. Keduanya selaras dengan RFC 2396, yang berlaku pada saat itu. RFC 3986 datang kemudian dan tidak mengubah perilaku pengkodean. Fungsi-fungsi ini masih menjadi standar saat ini dan harus digunakan.

encodeURI dimaksudkan untuk menyandikan URI; encodeURIComponent dimaksudkan untuk menyandikan komponen di dalam URI, seperti nilai kueri atau segmen jalur. Perbedaannya sangat penting dan mudah disalahpahami. encodeURI mempertahankan karakter struktural seperti : / ? # @ = & dan ;. encodeURIComponent mengkodekan semua itu, menjadikannya aman untuk ditanamkan di dalam URI yang lebih besar.

Mengapa ! * ' ( ) masih belum dikodekan — karakter RFC 2396 'tanda' dibekukan ke dalam bahasa setelah RFC 3986 memindahkannya

Kedua fungsi membiarkan karakter ini tidak dikodekan: huruf, angka, tanda hubung (-), garis bawah (_), titik (.), tanda gelombang (~), dan lima tanda baca ! * ' ( ). Tanda tersebut berasal dari RFC 2396, yang mencantumkannya sebagai karakter "tanda" tanpa pamrih. RFC 3986 keluar di 2005 dan memindahkan kelimanya ke kategori berbeda, namun JavaScript telah membekukan encodeURI dan encodeURIComponent di 1999. Mengubah karakter mana yang mereka tinggalkan akan merusak kode yang ada, jadi mereka tetap tinggal.

Keputusan untuk membiarkan kelima tanda tersebut tidak dikodekan untuk kompatibilitas mundur berarti pengkodean JavaScript tidak cocok secara sempurna dengan standar RFC 3986 atau WHATWG. Ini cukup dekat untuk penggunaan praktis, dan mengubahnya sekarang sangatlah mustahil. Ini adalah pelajaran tentang stabilitas API: setelah Anda membekukan perilaku, Anda tidak dapat mengubahnya meskipun standarnya berkembang.

Contoh praktis: string yang sama melalui escape, encodeURI dan encodeURIComponent - tiga keluaran dibandingkan

Ambil string "R&D (penelitian) = kafe". Jalankan melalui escape(), encodeURI dan encodeURIComponent. escape() menghasilkan "R%26D%20(penelitian)%20%3D%20caf%E9", menggabungkan tanda kurung dan tanda kutip yang tidak dikodekan dengan ampersand dan sama dengan yang dikodekan dalam persen. encodeURI menghasilkan "R&D%20(penelitian)%20=%20caf%C3%A9's", membiarkan tanda ampersand dan sama dengan saja karena bersifat struktural. encodeURIComponent menghasilkan "R%26D%20%28research%29%20%3D%20caf%C3%A9%27s", menyandikan semuanya termasuk tanda kurung dan tanda kutip.

Tempelkan string yang sama ke encoder & decoder URL dan beralih antara encodeURI dan encodeURIComponent untuk melihat perbedaannya. Kemudian periksa apa yang escape() akan hasilkan (Anda dapat memanggilnya di konsol browser, meskipun ia akan memperingatkan Anda). Anda segera melihat bahwa ketiga fungsi tersebut menghasilkan tiga hasil yang sangat berbeda.

Bermigrasi keluar dari escape() — memetakan panggilan lama ke fungsi modern yang tepat dan menangani data %uXXXX yang disimpan

Kode lama yang menggunakan escape() harus diperbarui. Jika escape() digunakan untuk menyandikan komponen URI, gantilah dengan encodeURIComponent. Jika digunakan untuk menyandikan URI lengkap, gunakan encodeURI. Untuk data tersimpan yang berisi urutan %uXXXX, Anda memerlukan dekoder khusus: ubah setiap %uXXXX menjadi titik kode Unicode, lalu kumpulkan titik kode tersebut menjadi string. Unescape() bawaan JavaScript akan membaca %uXXXX, namun hasilnya mungkin tidak benar UTF-8.

Setelah mengganti escape(), uji kode dengan string yang berisi karakter non-ASCII, tanda baca, dan karakter khusus. Outputnya sekarang harus sesuai dengan apa yang diharapkan oleh alat dan standar modern. Jika kode Anda jauh lebih tua dari ES3, kode tersebut mungkin juga menggunakan pola lama lainnya; audit yang komprehensif sepadan dengan usaha yang dilakukan.

Yang tidak tercakup di sini — API URL dan URLSearchParams, yang dibahas secara terpisah

API URL dan URLSearchParams, yang ditambahkan kemudian, menyediakan antarmuka tingkat yang lebih tinggi untuk konstruksi URL dan pengkodean komponen. Mereka menangani semua pelolosan secara otomatis dan sama persis dengan Standar WHATWG URL. Ini adalah cara yang lebih disukai untuk membuat URL secara terprogram di JavaScript modern.

Postingan ini hanya mencakup fungsi pengkodean, bukan API tingkat yang lebih tinggi. URL dan URLSearchParams mengurai struktur, memilih aturan komponen dan membuat serialisasi hasilnya, sedangkan encodeURIComponent mengubah satu string yang disediakan tanpa mengetahui di mana ia akan ditempatkan. Perbedaan tersebut adalah batasannya: migrasikan panggilan escape() lama sesuai dengan apakah panggilan tersebut menangani nilai atau alamat, lalu pertimbangkan untuk mengganti jaringan manual di sekitarnya dengan API terstruktur sebagai pemfaktoran ulang terpisah.

Kesimpulan: tiga fungsi, satu pasangan yang bertahan — bagaimana encoder & decoder URL menunjukkan perilaku encodeURI dan encodeURIComponent modern secara berdampingan

Pengembangan JavaScript modern harus menggunakan encodeURI atau encodeURIComponent, jangan pernah escape(). Fungsinya distandarisasi di 1999 dan tidak berubah sejak saat itu. Mereka mengkodekan karakter non-ASCII sebagai UTF-8 byte dan menangani karakter standar yang dicadangkan dengan benar. Alat encoder & decoder URL mengimplementasikan kedua fungsi tersebut dan memungkinkan Anda melihat perilakunya secara berdampingan, sehingga memudahkan Anda memilih fungsi yang tepat untuk komponen Anda.

Jika Anda menemukan urutan %u di log lama atau data yang disimpan, urutan tersebut adalah keluaran escape() dan harus dimigrasi. Migrasinya mudah dilakukan setelah Anda mengidentifikasi polanya. Kode modern tidak boleh memproduksinya.