Menggunakan URL dalam JavaScript dan Node.js sepatutnya mudah, tetapi pepijat baru-baru ini dalam projek kami membawa saya ke dalam lubang arnab dengan ciri-ciri halus dalam URL dan URLSearchParams API. Siaran ini akan meneroka kebiasaan ini, cara ia boleh menyebabkan masalah dalam kod anda dan perkara yang boleh anda lakukan untuk mengelakkannya.
Kami menghadapi isu ini semasa menjana URL dan menambahkan tandatangan cincang padanya. Parameter pertanyaan tidak dikod peratus secara konsisten, membawa kepada tingkah laku yang tidak dijangka dan tandatangan cincang yang salah.
Menjadi jelas bahawa interaksi antara URL dan objek URLSearchParams memerlukan penjagaan tambahan.
Kejutan pertama ialah perbezaan antara URL.search dan URLSearchParams.toString().
Berhati-hati apabila menggunakan .searchParams untuk mengubah suai URL kerana, mengikut spesifikasi WHATWG, objek URLSearchParams menggunakan peraturan yang berbeza untuk menentukan aksara yang hendak dikodkan peratus. Sebagai contoh, objek URL tidak akan mengekod peratusan aksara ASCII tilde (~), manakala URLSearchParams akan sentiasa mengekodnya.
// Example 1 const url = new URL("https://example.com?param=foo bar"); console.log(url.search); // prints param=foo%20bar console.log(url.searchParams.toString()); // prints ?param=foo+bar // Example 2 const myURL = new URL('https://example.org/abc?foo=~bar'); console.log(myURL.search); // prints ?foo=~bar // Modify the URL via searchParams... myURL.searchParams.sort(); console.log(myURL.search); // prints ?foo=%7Ebar
Dalam projek kami, kami perlu menetapkan semula secara eksplisit url.search = url.searchParams.toString() untuk memastikan rentetan pertanyaan dikodkan secara konsisten.
Satu lagi gotcha ialah cara URLSearchParams mengendalikan aksara. Secara lalai, URLSearchParams mentafsirkan sebagai ruang, yang mungkin membawa kepada kerosakan data apabila mengekod data binari atau rentetan Base64.
const params = new URLSearchParams("bin=E+AXQB+A"); console.log(params.get("bin")); // "E AXQB A"
Satu penyelesaian ialah menggunakan encodeURIComponent sebelum menambahkan nilai pada URLSearchParams:
params.append("bin", encodeURIComponent("E+AXQB+A"));
Maklumat lanjut tersedia dalam dokumentasi MDN.
Kehalusan lain timbul apabila membandingkan output URLSearchParams.get dan URLSearchParams.toString. Contohnya:
const params = new URLSearchParams("?key=value&key=other"); console.log(params.get("key")); // "value" (first occurrence) console.log(params.toString()); // "key=value&key=other" (all occurrences serialized)
Dalam senario berbilang nilai, dapatkan pulangan hanya nilai pertama, manakala toString menyerikan semua.
Dalam projek kami, kami menyelesaikan isu tersebut dengan menugaskan semula sifat carian secara eksplisit:
url.search = url.searchParams.toString(); url.searchParams.set( "hash", cryptography.createSha256HmacBase64UrlSafe(url.href, SECRET_KEY ?? "") );
Ini memastikan semua parameter pertanyaan dikodkan dengan betul sebelum menambah nilai cincang.
Antara muka WHATWG URLSearchParams dan modul rentetan pertanyaan mempunyai tujuan yang sama, tetapi tujuan modul rentetan pertanyaan adalah lebih umum, kerana ia membenarkan penyesuaian aksara pembatas (& dan =). Sebaliknya, URLSearchParams API direka bentuk semata-mata untuk rentetan pertanyaan URL.
querystring lebih berprestasi daripada URLSearchParams tetapi bukan API standard. Gunakan URLSearchParams apabila prestasi tidak kritikal atau apabila keserasian dengan kod penyemak imbas diingini.
Apabila menggunakan URLSearchParams tidak seperti modul rentetan pertanyaan, kunci pendua dalam bentuk nilai tatasusunan tidak dibenarkan. Tatasusunan dirangkaikan menggunakan tatasusunan.toString(), yang hanya menggabungkan semua elemen tatasusunan dengan koma.
// Example 1 const url = new URL("https://example.com?param=foo bar"); console.log(url.search); // prints param=foo%20bar console.log(url.searchParams.toString()); // prints ?param=foo+bar // Example 2 const myURL = new URL('https://example.org/abc?foo=~bar'); console.log(myURL.search); // prints ?foo=~bar // Modify the URL via searchParams... myURL.searchParams.sort(); console.log(myURL.search); // prints ?foo=%7Ebar
Dengan modul rentetan pertanyaan, rentetan pertanyaan 'foo=bar&abc=xyz&abc=123' dihuraikan ke dalam:
const params = new URLSearchParams("bin=E+AXQB+A"); console.log(params.get("bin")); // "E AXQB A"
Berhati-hati dengan cara URLSearchParams mengendalikan aksara khas (cth. ~) dan ruang. Gunakan encodeURIComponent apabila perlu.
Fahami perbezaan antara URL.search, URLSearchParams.get dan URLSearchParams.toString untuk mengelakkan tingkah laku yang tidak dijangka.
Dalam Node.js gunakan rentetan pertanyaan modul jika anda mahu menghuraikan kunci parameter pertanyaan pendua sebagai tatasusunan.
Atas ialah kandungan terperinci Perangkap URL dan URLSearchParams dalam JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!