URL query string を意味を失わずに分解・再構築する
重複パラメータ、空値、エンコード済みの入れ子 URL は parser ごとに扱いが違います。並べ替えや再エンコードの前に意味を分けて確認しましょう。
ログやブラウザーのアドレスバーでは、query string が一つの長い文字列に見えます。しかし OAuth callback、webhook 検証、analytics tag では、各 parameter が往復後も同じ意味を保つことが重要です。
失敗の原因は、多くの場合「URL parser が壊れている」ことではありません。encode、sort、serialize を一つの可逆操作だと思い込むことです。
URL 全体と query string を分ける
URL 全体には scheme、host、path、query、fragment があります。query string はその一部です。
たとえば path の / と query value の / は同じ文字でも意味が違います。URL 全体を処理したいのか、query value だけを処理したいのかを分けないと、必要な区切り文字までエンコードしたり、逆にデータとしての文字を区切り文字として扱ったりします。
重複パラメータ
次の query string は、parser によって配列、最後の値、最初の値として扱われることがあります。
?tag=api&tag=json&tag=debugging
API が重複パラメータを許すなら、再構築時にその順序と個数を保持する必要があります。単純な object へ変換すると、情報が失われることがあります。
空値と欠落値
?debug、?debug=、?debug=false は同じではありません。boolean flag、空文字列、文字列 "false" として意味が変わる可能性があります。
query string を正規化するときは、空値を削除してよいのか、明示的な空値として保持すべきかを API 契約で確認します。
再構築の安全な進め方
まず query を parameter の一覧として分解します。次に、各値がすでにエンコードされているのか、まだ生の文字列なのかを確認します。最後に、必要な文脈で一度だけエンコードして serialize します。
URL の不具合は見た目では分かりにくいので、変更前後の query string を diff で比べると、消えた値、順序変更、二重エンコードを見つけやすくなります。