SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|

2024-03-06(Wed) SinatraのPOSTでrequest.body.rewindが動かない

  先日、Sinatraに認証機能を付けたのだが、その際にbundle addをやり直してGem関係を最新にしたらPOSTの内容がreadできなくなってしまった。

NoMethodError at / undefined method `rewind' for #<Rack::Lint::Wrapper::InputWrapper:0xXXXX @input=#<StringIO:0xXXXX>>

  なんて出る。何かやらかしたかと思ったが、特段イジっていない。該当のコードは「request.body.rewind」らしいのだが、だいぶ前なので、なんでそんなコードを書いたのか覚えていない。が、どうもSinatraのオフィシャルサイトのサンプルコードから持ってきていたようだ。

post "/api" do
  request.body.rewind  # in case someone already read it
  data = JSON.parse request.body.read
  "Hello #{data['name']}!"
end

  それなのに動かないってどういうことよ。と思って追跡していくと、どうもRackのバージョンアップの影響らしい。Gemfileの記述を戻すと動く。「request.body」のメソッドを表示させてみると、実際に変わってしまっていて「rewind」メソッドがなくなってる。そら動かん。bundleの仕組みは、今回のようにバージョンアップの影響で動かなくなることを防ぐ意図もあるのだが、実際にこんなことあるんやな。

# 動くバージョン
request.body: #<Rack::Lint::InputWrapper:0xXXXX @input=#<StringIO:0xXXXX>>
request.body.methods: [:!, :!=, :!~, :<=>, :==, :===, :__id__,
:__send__, :assert, :class, :clone, :close, :define_singleton_method,
:display, :dup, :each, :enum_for, :eql?, :equal?, :extend, :freeze,
:frozen?, :gem, :gets, :hash, :inspect, :instance_eval,
:instance_exec, :instance_of?, :instance_variable_defined?,
:instance_variable_get, :instance_variable_set, :instance_variables,
:is_a?, :itself, :kind_of?, :method, :methods, :nil?, :object_id,
:private_methods, :protected_methods, :public_method, :public_methods,
:public_send, :read, :remove_instance_variable, :respond_to?, :rewind,
:send, :singleton_class, :singleton_method, :singleton_methods, :tap,
:then, :to_enum, :to_json, :to_s, :yield_self]
request.body.read: "key=value1&key=value2&commit=do+POST+test"
# 動かないバージョン
request.body: #<Rack::Lint::Wrapper::InputWrapper:0xXXXX @input=#<StringIO:0xXXXX>>
request.body.methods: [:!, :!=, :!~, :<=>, :==, :===, :__id__,
:__send__, ※, :class, :clone, :close, :define_singleton_method, 
:display, :dup, :each, :enum_for, :eql?, :equal?, :extend, :freeze,
:frozen?, :gem, :gets, :hash, :inspect, :instance_eval,
:instance_exec, :instance_of?, :instance_variable_defined?,
:instance_variable_get, :instance_variable_set, :instance_variables,
:is_a?, :itself, :kind_of?, :method, :methods, :nil?, :object_id,
:private_methods, :protected_methods, :public_method, :public_methods,
:public_send, :read, :remove_instance_variable, :respond_to?, ※,
:send, :singleton_class, :singleton_method, :singleton_methods, :tap,
:then, :to_enum, :to_json, :to_s, :yield_self]
request.body.read: ""

  そんなら、バージョンを指定する仕組みもあるんかいな、と思ったらシッカリある。

$ gem search '^rack$' --all
rack (3.0.9.1, 3.0.9, 3.0.8, 3.0.7, 3.0.6.1, 3.0.6, 3.0.5, 3.0.4.2,
3.0.4.1, 3.0.4, 3.0.3, 3.0.2, 3.0.1, 3.0.0, 2.2.8.1, 2.2.8, 2.2.7,
2.2.6.4, 2.2.6.3, 2.2.6.2, 2.2.6.1, 2.2.6, 2.2.5, 2.2.4, 2.2.3.1,
2.2.3, 2.2.2, 2.2.1, 2.2.0, 2.1.4.4, 2.1.4.3, 2.1.4.2, 2.1.4.1, 2.1.4,
2.1.3, 2.1.2, 2.1.1, 2.1.0, 2.0.9.4, 2.0.9.3, 2.0.9.2, 2.0.9.1, 2.0.9,
2.0.8, 2.0.7, 2.0.6, 2.0.5, 2.0.4, 2.0.3, 2.0.2, 2.0.1, 1.6.13,
1.6.12, 1.6.11, 1.6.10, 1.6.9, 1.6.8, 1.6.7, 1.6.6, 1.6.5, 1.6.4,
1.6.3, 1.6.2, 1.6.1, 1.6.0, 1.5.5, 1.5.4, 1.5.3, 1.5.2, 1.5.1, 1.5.0,
1.4.7, 1.4.6, 1.4.5, 1.4.4, 1.4.3, 1.4.2, 1.4.1, 1.4.0, 1.3.10, 1.3.9,
1.3.8, 1.3.7, 1.3.6, 1.3.5, 1.3.4, 1.3.3, 1.3.2, 1.3.1, 1.3.0, 1.2.8,
1.2.7, 1.2.6, 1.2.5, 1.2.4, 1.2.3, 1.2.2, 1.2.1, 1.2.0, 1.1.6, 1.1.5,
1.1.4, 1.1.3, 1.1.2, 1.1.1, 1.1.0, 1.0.1, 1.0.0, 0.9.1, 0.9.0, 0.4.0,
0.3.0, 0.2.0, 0.1.0)
$ bundle add rack --version=2.2.8.1 --skip-install
$ bundle add puma sinatra net-ldap --skip-install

  バージョンを検索する仕組みもあるし、指定する仕組みもある。これはよくできているな。

  問題は「3.0.0」から起こるようだ。根も深そうなので、今回はバージョンを戻す形で対処することにする。

  エラく時間を浪費させられたので憤慨する気持ちもないわけではないが、まぁ、近年のフレームワークのラクチンさは、恐ろしく多数の物件を積み上げた成果なわけで、たまにはこういうのもしゃーない。というわけで、他の人の時間の浪費が防がれることを祈って、ここに記録しておく。

  というような作業の合間に引き続きドルアーガ。ついに1人を残して59階に到達。いくのか? いってしまうのか? あ゛ぁー……連続のミスで打倒ならず。まぁ、だいぶ精度は上がってきているけどなぁ。もう少しだなぁ。

  画像の説明