Twitter以上ブログ以下

ただの読み物

faraday-middleware と Oj の組み合わせで動かなくなる話

背景

faraday-middleware が突如として ArgumentError: options must be a hash. というエラーを吐いて落ちた この原因を探ってしまったので(本当は issue にあった)、記録として残しておく。現状この問題は解決済み

結論

Oj で mimic mode を使っていると、 faraday-middleware の v0.12.0 で入った改修により、落ちる。

github.com

回避方法としては Oj のアップデートを行うか、 mimic mode を利用しない。

faraday middleware 側の改修も Master には取り込まれているが、 2017-08-03時点ではReleaseされていない。

概要

Oj という Gem は、Rubyの早いJsonParseであり、大部分がCで実装されている。 また、Oj は mimic というモードを備えており、これを利用すると、既存の JSON.parse などのコードをOjのコードに差し替える。

Faraday Middleware の https://github.com/lostisland/faraday_middleware/pull/156/files#diff-5af7802308edb2ce67e963810b810354R11 この改修により、 parse_option を特に指定しない場合において JSON.parse(body, nil) が実行されるようになった。

しかし、 Oj の mimic mode によって上書きされた JSON.parse は、第二引数が Hash かどうかだけをチェックしており、ここで落ちる https://github.com/ohler55/oj/blob/b1504563d8eaadad549aa56b1eaac1845bb63a3d/ext/oj/mimic_json.c#L513

元の JSON.parse では、 オプションが nil の場合はOptionのパースは実行されないので、落ちない https://github.com/flori/json/blob/master/ext/json/ext/parser/parser.c#L1734-L1739

よって、今回の問題は Oj を利用しており、 Oj の mimic mode を利用している場合のみ発生していた。

というのが ↑ の issue にまとまってるので読むと良い。