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

f:id:ryoutaku_jo:20190827015850p:plain

【結論】

・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

https://wa3.i-3-i.info/word13354.html

POST - HTTP | MDN

URLエンコード

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

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

《今日の学習進捗(3年以内に10000時間に向けて)》

画像がアップロード出来ない問題が発生した。
原因を調査すると、URLパラメーターで渡しているCSRFトークンに「+」が入っていると、スペースに置換されてしまうことで、セッションの情報と一致せず、認証エラーになっていた。

URLパラメータではなく、ヘッダにトークンを記述することで改善した。
しかし、場当たり的に検証を行ったり、Railsのgemなど深い部分の動作検証がスムーズに行えなかったりと、デバックの効率の悪さで課題を感じた。

今回の内容であれば、HTTP通信の基本的な仕様を理解していれば、ある程度当たりをつけることが出来た内容なので、基礎知識の補強に努めたい。
また、RubyMineのデバック機能を用いれば、Rails自体のコードを深掘りするのもスムーズに行える様なので、ツールの活用と併せて効率の改善を図りたい。

学習開始からの期間 :262日
今日までの合計時間:2470h
一日あたりの平均学習時間:9.5h
今日までに到達すべき目標時間:2393h
目標との解離:77h
「10,000時間」まで、

残り・・・「7530時間!」