codedecoder

breaking into the unknown…


Leave a comment

undefined method `eof?’ for #

Below is one of my API code in my new Rails application

module Api
  module V1
    class VendorOnboardingController < Api::BaseController
      include Concerns::Api::V1::VendorOnboardingApipie
      def enrollment
        result = Parse::Vendor.new(Hash.from_xml(request.body).deep_symbolize_keys!)
        ...remaining code----
      end
    end
  end
end

The API working fine locally and on server running thin as application server.After testing we moved the code to UAT server running on Passenger as application server and the API boomed with below error:

“undefined method `eof?’ for PhusionPassenger::Utils::TeeInput:0x000056122fc69a20”

After breaking a lot of head and changing code with hit and trial method realized the culprit code is request.body in below line of code.

result = Parse::Vendor.new(Hash.from_xml(request.body).deep_symbolize_keys!)

changing it to request.body.read as below fixed the issue.

result = Parse::Vendor.new(Hash.from_xml(request.body.read).deep_symbolize_keys!)

Understanding the Problem:
Rails communicate with application server through Rack.

Infact Rack sits between all the frameworks (Rails, Sinatra, Rulers) and all the app servers (thin, unicorn, Rainbows, mongrel) as an adapter. Now if you see  rack spec it says

The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to gets, each, read and rewind.

So in my local or with thin the request body was always coming as a StringIO object, so not causing any problem when the subsequent line of my code operating on it, but with passenger some how, this is not the case so code is breaking.

calling request.body.read will explicitly convert the request body to StringIO object and so fixed the problem.


		
Advertisements