URL エンコーディングの説明: パーセント エンコーディング、encodeURI と encodeURIComponent、および %2520 バグ

2026年7月11日 · 7 分で読了

ユーザー入力を使用して URL を構築したすべての開発者は、スペースまたはアンパサンドを含む検索語によってリンクが切断され、サーバー上で突然クエリの半分が失われるという問題に遭遇したことがあります。修正方法は URL エンコーディング (パーセント エンコーディングとも呼ばれます) ですが、これには混同しやすい 2 つの機能と、リンク内に不可解な %2520 を生成する 1 つのバグが含まれています。このガイドではそれをすべて解決します。

そもそもなぜ URL にエンコードが必要なのか

URL には、RFC 3986 と呼ばれる標準で定義されている、限られた文字セットのみを含めることが許可されています。そのセットは基本的に、予約されていない文字、文字、数字、およびハイフンやアンダースコアなどのいくつかの記号に加えて、? などの特別な構造的意味を持つ少数の予約文字です。クエリを開始するには &、パラメータを区切るには =、キーと値をペアにするには /、パス セグメントには /、フラグメントには # を使用します。このセットの外にあるもの、スペース、アクセント付き文字、絵文字、または構造ではなくデータとして使用される予約記号はすべてエンコードする必要があり、エンコードしないと URL が壊れます。

パーセント エンコーディングは、安全でない文字をパーセント記号とその後に続く 2 桁の 16 進バイト値に置き換えることによってこれを行います。スペースは%20となります。アンパサンドは%26になります。アットマークは %40 になります。一方、サーバーはこれらをデコードして元の文字に戻します。システム全体は、任意のテキストが URL の厳密な構造の一部と誤認されることなく、その構造の内部に乗り込むことができるように存在します。

The core problem: data vs structure

ほとんどのバグが発生する状況は次のとおりです。 「猫と犬」という文字通りのテキストを検索すると想像してください。これを q=cats & Dogs としてクエリ文字列に直接ドロップすると、& がパラメータ区切り文字として読み取られ、サーバーはパラメータ q=cats と 2 番目の無意味なパラメータ Dogs を認識し、検索は失敗します。スペースもトラブルの原因になります。サーバーが URL 構造ではなく値の一部であることを理解できるように、アンパサンドは %26 になり、スペースは %20 になる必要があります。エンコーディングとは、「この文字はデータであり、区切り文字ではない」と言う方法です。

encodeURI と encodeURIComponent

JavaScript には 2 つのエンコーディング関数があり、間違った関数を選択することは、最も一般的な URL バグの 1 つです。違いは、何を「安全」と考えて放置するかです。

encodeURIComponent は、/? を含む予約済みのものをすべてエンコードします。 & = # など。これは、URL、クエリ パラメータ値、検索語、リダイレクト ターゲットに挿入する単一の値をエンコードすることを目的としています。ピースに使用します。対照的に、encodeURI は、機能を維持しながら、既に組み立てられた URL 全体をエンコードすることを目的としているため、意図的に URL 構造文字 (/ ? & =) をそのまま残します。全体的に使用することはほとんどありません。

経験則: URL 内に入る値をエンコードする場合は、encodeURIComponent を使用します。完全な URL をエンコードしていて、その構造を壊すことなく、不正な文字だけを修正したい場合は、encodeURI を使用します。ほとんどの場合値をエンコードするため、迷った場合は、ほとんどの場合 encodeURIComponent が必要になります。

間違った選択の例: リダイレクト パラメーターで encodeURI を使用すると、リダイレクト自体のクエリ文字列の & と = がエンコードされないままになるため、外側の URL がそれらを誤って読み取ります。その値の encodeURIComponent は、値をそのまま維持したまま、それらを %26 および %3D にエンコードします。

%2520 のバグ: 二重エンコーディング

これは最初は誰もが混乱します。 %20 が予想される URL に %2520 が表示され、リンクが壊れています。何が起こったのかというと、すでにエンコードされた文字列が再度エンコードされました。最初のエンコードによりスペースが %20 に変換されました。次に 2 番目のエンコードではパーセント記号自体がエンコードされ、% は %25 になり、%20 は %2520 になります。現在、サーバーはこれをスペースではなく %20 (文字通りのテキスト "%20") に一度デコードしますが、ダウンストリームの内容はすべて間違っています。

ほとんどの場合、原因はすでにエンコードされた値をエンコードすることです。たとえば、すでに URL エンコードされた文字列から URL を構築し、それをエンコーダで再度実行します。これを避けるためのルールは、エンコードされていない生のテキストのみをエンコードすることです。すでにエンコードされている URL または値を決してエンコードしないでください。文字列がすでにエンコードされているかどうかが不明な場合は、まず文字列をデコードしてから、一度だけエンコードしてください。

プラス記号の曖昧さ

もう一つの罠。クエリ文字列では、プラス記号 (+) がスペースとして解釈されることがあります。これは、古い HTML フォーム エンコーディング application/x-www-form-urlencoded の遺産です。ただし、URL パスでは、+ は文字通りのプラスです。この不一致は、データ内の + がある場所ではスペースとして読み取られ、別の場所ではプラスとして読み取られる可能性があることを意味します。安全な方法は、+ に依存するのではなく、スペースを常に %20 としてエンコードすることです。これはどこでも明確です。スペースがプラスに変わったり、その逆が見られる場合は、通常、この曖昧さが原因です。

実践的なポイント

URL に入力する値をエンコードし、それらの値には encodeURIComponent を使用し、%2520 の二重エンコードのバグを避けるために生のテキストのみをエンコードし、スペースには + よりも %20 を優先します。 URL を手動で構築または検査する必要がある場合、クイック エンコーダとデコーダを使用すると、文字列がどのようになるかを正確に確認し、出荷前に問題を検出できます。

TextCaret URL エンコード / デコード ツールは、encodeURIComponent と同じ方法でテキストをパーセント エンコードするため、ブラウザ内で安全にクエリ値を準備したり、謎の %2520 をデコードして何が問題になったのかを確認したりできます。