Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

undefined method `bytesize' for ActionDispatch::Response

#4274

I recently added Rack::JSONP middleware to my Rails 3 app.

It works like a charm when adding the ?callback=my_method to the json request, but explodes with the following when I omit it.

ERROR NoMethodError: undefined method bytesize' for #<ActionDispatch::Response:0x1039b3c88>

Reported by Mike (at coverallcrew) · March 26th, 2010 @ 03:58 PM

State: resolved
Milestone: 3.0.2
Assigned to: Yehuda Katz (wycats) Yehuda Katz (wycats)
Importance: Low

Activity

  1. Yehuda Katz (wycats)
    Yehuda Katz (wycats)
    • State changed from new to incomplete
    • Tag set to rails3
    • Assigned user set to Yehuda Katz (wycats)
    • Milestone cleared.

    Can you show the entire stack trace and also link me to the Rack::JSONP you're using?

    March 27th, 2010 @ 03:12 AM

  2. Mike (at coverallcrew)
    Mike (at coverallcrew)

    Hi Yehuda,

    It fails when using version 0.9.2 of rack-contrib... and upon further investigation it seems the culprit is simply when I add this to my Gemfile:

    gem 'rack-contrib', :require => 'rack/contrib'
    

    The stack trace is as follows:

    [2010-03-26 20:19:04] ERROR NoMethodError: undefined method `bytesize' for #<ActionDispatch::Response:0x104040a60>
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/utils.rb:228:in `bytesize'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/content_length.rb:22:in `call'
    /Library/Ruby/Gems/1.8/gems/mongo_mapper-0.7.2/lib/mongo_mapper/document.rb:285:in `inject'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/content_length.rb:22:in `each'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/content_length.rb:22:in `inject'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/content_length.rb:22:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/handler/webrick.rb:48:in `service'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:162:in `start'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:95:in `start'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:92:in `each'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:92:in `start'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:23:in `start'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/webrick/server.rb:82:in `start'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/handler/webrick.rb:14:in `run'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/server.rb:155:in `start'
    /Library/Ruby/Gems/1.8/gems/railties-3.0.0.beta/lib/rails/commands/server.rb:49:in `start'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/server.rb:83:in `start'
    /Library/Ruby/Gems/1.8/gems/railties-3.0.0.beta/lib/rails/commands.rb:39
    /Users/mike/Projects/attendease/script/rails:10:in `require'
    /Users/mike/Projects/attendease/script/rails:10
    

    Let me know if you need any more info.

    Cheers.

    March 27th, 2010 @ 03:40 AM

  3. Josh Graham
    Josh Graham

    This is because in the 0.9.2 rack-contrib gem, Rack::JSONP returns response in an array. It should only return response as an array if the callback param was included.

    For an appropriate guard that Rack::JSONP should be using, see
    http://github.com/lawrencepit/rack-contrib/commit/356dcdd0804fb6824...

    However, the returned string from the pad method should be put into an array so it can be enumerated.

    If you want a quick fix, you can open the gem and alter /rack-contrib-0.9.2/lib/rack/contrib/jsonp.rb to this:

    module Rack
    
      # A Rack middleware for providing JSON-P support.
      #
      # Full credit to Flinn Mueller (http://actsasflinn.com/) for this contribution.
      #
      class JSONP
    
        def initialize(app)
          @app = app
        end
    
        # Proxies the request to the application, stripping out the JSON-P callback
        # method and padding the response with the appropriate callback format.
        #
        # Changes nothing if no <tt>callback</tt> param is specified.
        #
        def call(env)
          status, headers, response = @app.call(env)
          request = Rack::Request.new(env)
          if request.params.include?('callback')
            response = [pad(request.params.delete('callback'), response)]
            headers['Content-Length'] = response.length.to_s
          end
          [status, headers, response]
        end
    
        # Pads the response with the appropriate callback format according to the
        # JSON-P spec/requirements.
        #
        # The Rack response spec indicates that it should be enumerable. The method
        # of combining all of the data into a single string makes sense since JSON
        # is returned as a full string.
        #
        def pad(callback, response, body = "")
          response.each{ |s| body << s.to_s }
          "#{callback}(#{body})"
        end
    
      end
    end
    

    June 5th, 2010 @ 06:11 PM

  4. Josh Graham
    Josh Graham

    Apologies, the code should be:

    module Rack
    
      # A Rack middleware for providing JSON-P support.
      #
      # Full credit to Flinn Mueller (http://actsasflinn.com/) for this contribution.
      #
      class JSONP
    
        def initialize(app)
          @app = app
        end
    
        # Proxies the request to the application, stripping out the JSON-P callback
        # method and padding the response with the appropriate callback format.
        #
        # Changes nothing if no <tt>callback</tt> param is specified.
        #
        def call(env)
          status, headers, response = @app.call(env)
          request = Rack::Request.new(env)
          if request.params.include?('callback')
            response = pad(request.params.delete('callback'), response)
            headers['Content-Length'] = response.length.to_s
            response = [response]
          end
          [status, headers, response]
        end
    
        # Pads the response with the appropriate callback format according to the
        # JSON-P spec/requirements.
        #
        # The Rack response spec indicates that it should be enumerable. The method
        # of combining all of the data into a single string makes sense since JSON
        # is returned as a full string.
        #
        def pad(callback, response, body = "")
          response.each{ |s| body << s.to_s }
          "#{callback}(#{body})"
        end
    
      end
    end
    

    June 5th, 2010 @ 07:38 PM

  5. Rune Botten
  6. Rune Botten
    Rune Botten

    rack-contrib 1.0.1 released, which fixes this.

    June 10th, 2010 @ 12:46 PM

  7. Ryan Bigg
    Ryan Bigg
    • State changed from incomplete to resolved

    June 12th, 2010 @ 02:52 AM

  8. Jeremy Kemper
    Jeremy Kemper
    • Milestone set to 3.0.2
    • Importance changed from to Low

    October 15th, 2010 @ 11:01 PM

  9. af001
    af001

    私の中で、総合評価のとっても低いアバアバクロホリスタークロ銀座店。アバクロは大好きなんですけどね。一昨日の東京駅付近での打ち合わせの後、散歩がてら久々に行ってきました。そしたらビックリ!相変わらアバクロず、踊っているだけの店員さんとかもいましたが、

    May 5th, 2011 @ 02:56 AM