ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript における URL と URLSearchParams の落とし穴

JavaScript における URL と URLSearchParams の落とし穴

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-28 11:59:09488ブラウズ

Pitfalls of URL and URLSearchParams in JavaScript

すべてはバグから始まりました

JavaScript と Node.js での URL の操作は簡単なはずですが、プロジェクトの最近のバグにより、URL と URLSearchParams API の微妙な癖のウサギの穴に落ちました。この投稿では、これらの癖、それがコード内でどのように問題を引き起こす可能性があるか、そしてそれらを回避するために何ができるかを検討します。


問題: Axios での URL 処理

URL を生成し、それにハッシュ署名を追加しているときに、この問題が発生しました。クエリ パラメーターが一貫してパーセント エンコードされていないため、予期しない動作や間違ったハッシュ署名が発生しました。

URL オブジェクトと URLSearchParams オブジェクトの間の対話には特別な注意が必要であることが明らかになりました。


落とし穴 #1: URL.search と URLSearchParams.toString()

最初に驚いたのは、URL.search と URLSearchParams.toString() の違いでした。

WHATWG 仕様に従って、URLSearchParams オブジェクトはパーセント エンコードする文字を決定するために異なるルールを使用するため、.searchParams を使用して URL を変更する場合は注意してください。たとえば、URL オブジェクトは ASCII チルダ (~) 文字をパーセント エンコードしませんが、URLSearchParams は常にエンコードします。

// 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

私たちのプロジェクトでは、クエリ文字列が一貫してエンコードされていることを確認するために、 url.search = url.searchParams.toString() を明示的に再割り当てする必要がありました。


落とし穴 #2: プラス記号のジレンマ

もう 1 つの問題は、URLSearchParams による文字の処理方法です。デフォルトでは、URLSearchParams はスペースとして解釈されるため、バイナリ データまたは Base64 文字列をエンコードするときにデータ破損が発生する可能性があります。

const params = new URLSearchParams("bin=E+AXQB+A");
console.log(params.get("bin")); // "E AXQB A"

1 つの解決策は、URLSearchParams に値を追加する前に encodeURIComponent を使用することです:

params.append("bin", encodeURIComponent("E+AXQB+A"));

詳細については、MDN ドキュメントを参照してください。


落とし穴 #3: URLSearchParams.get と URLSearchParams.toString()

URLSearchParams.get と URLSearchParams.toString の出力を比較すると、別の微妙な点が生じます。例:

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)

複数値のシナリオでは、get は最初の値のみを返しますが、toString はすべてをシリアル化します。


コードベースの修正

私たちのプロジェクトでは、検索プロパティを明示的に再割り当てすることで問題を解決しました。

url.search = url.searchParams.toString();
url.searchParams.set(
  "hash",
  cryptography.createSha256HmacBase64UrlSafe(url.href, SECRET_KEY ?? "")
);

これにより、ハッシュ値を追加する前にすべてのクエリ パラメーターが適切にエンコードされることが保証されました。


Node.jsクエリ文字列モジュール

WHATWG URLSearchParams インターフェイスとクエリ文字列モジュールの目的は似ていますが、クエリ文字列モジュールの目的は区切り文字 (& と =) のカスタマイズが可能であるため、より一般的です。一方、URLSearchParams API は URL クエリ文字列専用に設計されています。

querystring は URLSearchParams よりもパフォーマンスが優れていますが、標準化された API ではありません。パフォーマンスが重要ではない場合、またはブラウザ コードとの互換性が望ましい場合は、URLSearchParams を使用します。

querystring モジュールとは異なり、URLSearchParams を使用する場合、配列値の形式での重複キーは許可されません。配列は array.toString() を使用して文字列化されます。これは、すべての配列要素をカンマで結合するだけです。

// 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

querystring モジュールを使用すると、クエリ文字列 'foo=bar&abc=xyz&abc=123' は次のように解析されます。

const params = new URLSearchParams("bin=E+AXQB+A");
console.log(params.get("bin")); // "E AXQB A"

テイクアウト

  1. URLSearchParams による特殊文字 (~) とスペースの処理方法には注意してください。必要に応じて encodeURIComponent を使用します。

  2. 予期しない動作を避けるために、 URL.search、URLSearchParams.get、URLSearchParams.toString の違いを理解してください。

  3. Node.js では、 クエリ文字列 モジュール if を使用して、重複するクエリ パラメーター キーを配列として解析します。

以上がJavaScript における URL と URLSearchParams の落とし穴の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。