ruby-grape / grape

An opinionated framework for creating REST-like APIs in Ruby.

Home Page:http://www.ruby-grape.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

undefined method `rewind' for #<Rack::Lint::Wrapper::InputWrapper w/Rack >= 3.0

andrius opened this issue · comments

I use a simple ruby (not rails) API with grape, grape-entiry and grape-swagger gems, along with the mongoid. For POST or PUT endpoints it does throw the following error:

NoMethodError: undefined method `rewind' for #<Rack::Lint::Wrapper::InputWrapper:0x0000ffffa610b728 @input=#<StringIO:0x0000ffffa610bf48>> (NoMethodError)

        input.rewind
             ^^^^^^^
	/usr/local/bundle/gems/grape-2.0.0/lib/grape/middleware/formatter.rb:87:in `read_body_input'
	/usr/local/bundle/gems/grape-2.0.0/lib/grape/middleware/formatter.rb:20:in `before'
	/usr/local/bundle/gems/grape-2.0.0/lib/grape/middleware/base.rb:34:in `call!'
	/usr/local/bundle/gems/grape-2.0.0/lib/grape/middleware/base.rb:29:in `call'
	/usr/local/bundle/gems/grape-2.0.0/lib/grape/middleware/error.rb:39:in `block in call!'
	/usr/local/bundle/gems/grape-2.0.0/lib/grape/middleware/error.rb:38:in `catch'
	/usr/local/bundle/gems/grape-2.0.0/lib/grape/middleware/error.rb:38:in `call!'
	/usr/local/bundle/gems/grape-2.0.0/lib/grape/middleware/base.rb:29:in `call'
	/usr/local/bundle/gems/rack-3.0.8/lib/rack/head.rb:15:in `call'

Based on online search I've found that similar issues were long time ago and were fixed, but here it is. Any ideas how to fix it? Happy to share more details or code snippets!

This is caused by lack of rewind on the input in Rack. Typically that would extend https://github.com/rack/rack/blob/main/lib/rack/rewindable_input.rb, but it looks like Rack::Lint::Wrapper::InputWrapper doesn't have that. What is the actual setup you have that makes the content that type? Try building a minimal repro?

Thank you. I've included minimal example in this gist: https://gist.github.com/andrius/50e2965a9b0936a7c76f9d7f77bdc2a7

To run:

docker compose build && docker compose run --rm --interactive --service-ports api

To test:

curl -X POST \
  'http://localhost:3000/v1/users' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"name": "foo", "lastname": "bar", "email": "foo@bar.foo", "telephone": "+1234567890", "role": "user"}'

Found the issue, rack/rack#1972. Adding use Rack::RewindableInput::Middleware fixed the issue for me, so would downgrading to Rack 2.x.

require_relative 'api'
use Rack::RewindableInput::Middleware
run API::Root

We should do something about this in Grape. Would you like to help @andrius? We have https://github.com/ruby-grape/grape/tree/master/spec/integration/rack/v3 and https://github.com/ruby-grape/grape/blob/master/gemfiles/rack_3_0.gemfile, but we're not catching this error. The first thing to figure out is how to reproduce it in CI, then we can see whether we should just recommend including this middleware manually, or more likely have to write some code to include it when Rack version is >= 3.0.

Your suggestion with use Rack::RewindableInput::Middleware helped and API start working!

Would you like to help @andrius?

I will try but it will take time. Just check'ed the GitHub workflows