URLエンコードによってパラメータの空白スペースが+に書き換わる問題(Rails)

【結論】

・URLパラメータ(クエリ文字列)とは、URLの末尾にを付け続けて&キー=値と記述することで、サーバーに情報を送るためにURLに付け加える変数

・application/x-www-form-urlencodedのURLエンコードとは、URLにおいて使用できない文字を使う際に行われるエンコード

・URLエンコードによって、パラメーターの値の空白が+になったり、+から空白に変わったりと、バグの原因となり得るので注意が必要

【目次】

【本題】

URLパラメータ(クエリ文字列)とは

URLパラメータ(クエリ文字列)とは、サーバーに情報を送るためにURLに付け加える変数のことです。

以下の様に、URLの末尾にを付け続けて&キー=値と記述することで、

http://sample.com/index?&user=3

Railsであれば、params[:キー]で値を取得することが可能です。

application/x-www-form-urlencodedのURLエンコードとは

application/x-www-form-urlencodedのURLエンコードとは、URLにおいて使用できない文字を使う際に行われるエンコードです。

通常、URLではひらがな等の文字は利用出来ません

それらを%2F%24…という様な16進数に符号化することでサーバーに送信します。

URLエンコードの弊害(空白→+)

なお、URLエンコードには弊害があります。

例えば、以下の様なコードを実装したとします。

= link_to root_path(title: 'タイトル と 空白')

そうすると、HTMLに以下の文言が埋め込まれます。

/?title=%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB%E3%80%80%E3%81%A8%E3%80%80%E7%A9%BA%E7%99%BD

このリンクの遷移先でparams[:title]を取得すると、以下の文言が取得出来ます。

タイトル+と+空白

この様に、URLエンコードによってデコードされた際に、空白が+に置き換わってしまいます。

URLエンコードの弊害(+→空白)

また、他にもRailsCSRF保護でHEADタグに埋め込まれる以下のcsrf-tokenがありますが

<meta name="csrf-token" content="7S9WFCP3Bl0vTOm4KqDmwu/Db0zYpzbG+mxgUYdAKEZf5ZjKniBa+QIK2wCgCABRTO0+uIhUKnRJNFbJ/TViGg==">

これをURLパラメータでサーバーに送信すると、以下の様になります。

'7S9WFCP3Bl0vTOm4KqDmwu/Db0zYpzbG mxgUYdAKEZf5ZjKniBa QIK2wCgCABRTO0+uIhUKnRJNFbJ/TViGg=='

URLエンコードによってエンコードされた際に、+が空白に置き換わってしまいます。

これにより、CSRF保護が正常に動作しない問題が発生します。

この様に、URLエンコードの仕様を理解しておかないと、思わぬバグを引き起こす恐れがあり、注意が必要です。

参考情報

URL Standard

URLエンコードについておさらいしてみた - Qiita

URLエンコードとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

POST - HTTP | MDN

URLエンコード

Railsを使ってURLパラメータの引き渡しと読み込みを行う方法 (1/2)|CodeZine(コードジン)

空白スペースが+になる理由(railsソースコードリーディング) - Qiita