URLパラメータに+が含まれる場合

サイトのページ遷移の際に、URLパラメータで変数渡しを行ったところ、
変数内に含まれていた+の文字がブランクになってしまった話。

JavaScript
// URLから 'product_id' パラメータを取得
const urlParams = new URLSearchParams(window.location.search);
const productIdParam = urlParams.get('product_id');

javascriptでURLパラメータを取得した際に、
パラメータ内の + が消えてスペースに変わってしまうのは、
URLのクエリパラメータにおける +が「スペース」を意味する特別な文字 だからです。

new URLSearchParams() は、このルールに従ってURLを自動的に解読(デコード)するため、+ を見つけると親切にスペースに変換してくれるのです。


解説

URL、特に ? 以降のクエリパラメータ部分では、一部の記号が特別な意味を持ちます。
(例: &はパラメータの区切り、=は値の指定)

スペース(空白文字)はそのままURLに含めることができないため、URLエンコーディングという方法で別の文字列に変換する必要があります。スペースのエンコードには、歴史的な経緯から2通りの方法があります。

  1. %20 : パーセントエンコーディングによる正式な表現。
  2. + : 主にフォーム送信などで使われる、より短い簡易的な表現。

URLSearchParams は、この両方をスペースとして解釈するように作られています。そのため、Product_001_2+1Product_001_2 1 として読み込まれてしまいます。


解決策

この問題を解決するには、URLを生成する元々のシステム側で、リテラルな + 記号を正しくエンコードする必要があります。

+ 記号自体のパーセントエンコーディングは %2B です。

修正前(問題が起きるURL)

https://…中略…&product_id=Product_001_2+1

修正後(正しく動作するURL)

https://…中略…&product_id=Product_001_2%2B1

このように、リンクを生成する段階で +%2B に置き換えておくことで、JavaScriptの URLSearchParams%2B を正しく + にデコードし、期待通りの文字列 Product_001_2+1 を取得できるようになります。

この修正は、URLを受け取る側のJavaScriptではなく、このURLを生成している側のシステム(サーバーサイドのプログラムなど)で行う必要があります。

とはいえ。
URLパラメータの内容はパターンが限られていること、
URL生成側を修正するよりも受け取り側を修正した方が影響が少なかったので、
受け取り側で「Product_001_2 1」で判定することで解決しました。

タイトルとURLをコピーしました