バージョン

  • Rails: 5.2.4.6

結論

Content-Typejsonapplication/json 等) ではない場合にこの現象が発生するようです。

Content-Typejson 以外でどうしても複数回呼びたい場合は request.raw_post を使用するとよさそうです。

次に説明しますが Content-Typejson に該当する場合であれば内部的に request.raw_post が呼ばれ、その中で RAW_POST_DATA という特殊なヘッダーに値が設定されて request.body.read が呼ばれた時もそのヘッダーから値が使用されるため複数回呼び出しても値が返ってくるようになっています。

ソースコード

request.bodyrequest.raw_post

https://github.com/rails/rails/blob/v5.2.4.6/actionpack/lib/action_dispatch/http/request.rb#L311-L329

Content-Typejson に該当する場合に raw_post が呼ばれる処理

https://github.com/rails/rails/blob/v5.2.4.6/actionpack/lib/action_dispatch/http/parameters.rb#L106-L119