PostmanでRequest Paramsに入力した+がスペースに変換されてしまうのを防ぐ
小ネタ。
Railsのフォーム経由でリクエストするときはAuthenticity Token
を付与する必要がある
CSRF対策として、Railsはフォームから送信されたリクエストを処理する前に、渡ってきたAuthenticity Token
が正しいかチェックする。
form_with
などで生成したFormタグには、CSRF対策に生成されたトークンが<input type=hidden>
に追加されるので、それをauthenticity_token
paramに乗せて渡す必要がある。
素朴なPOSTリクエストを行うフォームであれば、そのままSubmit
するだけで勝手に付与されるのだけど、JavaScriptやPostmanなどのHTTPクライアントから送信する場合は自前でparamsに設定してやる必要がある。
ここで問題が
PostmanのParamsはvalueに+
が含まれていた場合、スペースとして認識されてしまう。
# Railsのログ Parameters: {"authenticity_token"=>"123 test=="} Can't verify CSRF token authenticity.
解決策
+
ではなく、%2B
とエンコードした状態で送信する必要がある。
Parameters: {"authenticity_token"=>"123+test=="}
なぜこうなる?
上記のIssueに書いてある通り。
In query params '+' needs to be encoded to %2B instead of %20 - This is the expected behavior as + has a special meaning of (space) in query params which needs to encoded as %20 (space).
クエリパラメータに含まれる+
は%2Bではなく%20にエンコードされる。これはPostman側で想定している挙動らしい。
なぜかというと、HTMLの仕様の 17.13.4 Form content typesにこんな記述がある。
application/x-www-form-urlencoded
This is the default content type. Forms submitted with this content type must be encoded as follows:Control names and values are escaped. Space characters are replaced by
+
, and then reserved characters are escaped as described in [RFC1738], section 2.2: Non-alphanumeric characters are replaced by%HH
, a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as "CR LF" pairs (i.e., `%0D%0A').
どうやら、クエリパラメータに含まれているスペースは+
に置換されるらしい。で、クエリパラメータの+
はスペースを表すので、パラメータに+
が含まれた文字列を指定するとこのような結果となる。
おわりに
Postmanで+
をちゃんと送りたいだけの小ネタ記事だったはずなんだけど、クエリパラメータとかHTMLの仕様とか調べてたら意外と時間かかった...。