This project is archived and is in readonly mode.
[Patch] XML Mini Parser NoMethodError :getc when application running through Phusion Passenger
-
Hongli Lai
Instead of referring to Phusion Passenger specifically, you should refer to Rack, because Phusion Passenger is just implementing the Rack specification and the restriction is in Rack.
-
Simon Chiu
Agreed, it should be referred to the rack.input rather than Passenger specifically. Updated the patch to reflect that in the tests. Libxml and Nokogiri parsers have also been updated.
-
Simon Chiu
- Title changed from XML Mini Parser NoMethodError :getc when application running through Phusion Passenger to [Patch] XML Mini Parser NoMethodError :getc when application running through Phusion Passenger
-
ieuser
applied the patch to rails3 beta3 but still get
PhusionPassenger::Utils::RewindableInput is not a valid input stream. It must walk like either a String, an IO, or a Source.
-
Simon Chiu
ieuser, Which XML parser backend are you using with your Rails 3 app?
-
Si
Hi Simon, I just tried the patch and get the same error:
PhusionPassenger::Utils::RewindableInput is not a valid input stream. It must walk like either a String, an IO, or a Source.I'm using rexml and here's the backtrace:
/Users/Si/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rexml/source.rb:22:in `create_from' /Users/Si/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rexml/parsers/baseparser.rb:146:in `stream=' /Users/Si/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rexml/parsers/baseparser.rb:123:in `initialize' /Users/Si/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rexml/parsers/treeparser.rb:9:in `new' /Users/Si/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rexml/parsers/treeparser.rb:9:in `initialize' /Users/Si/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rexml/document.rb:230:in `new' /Users/Si/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rexml/document.rb:230:in `build' /Users/Si/.rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/rexml/document.rb:43:in `initialize' vendor/rails/activesupport/lib/active_support/xml_mini/rexml.rb:38:in `new' vendor/rails/activesupport/lib/active_support/xml_mini/rexml.rb:38:in `parse' vendor/rails/activesupport/lib/active_support/xml_mini.rb:13:in `parse' -
Jan Kubr
You'll need to call .read on the received data before passing it to REXML::Document.new. Something like this seems to work:
def parse(data) if !data.respond_to?(:read) data = StringIO.new(data || '') end str = data.gets if str.nil? {} else data.rewind silence_warnings { require 'rexml/document' } unless defined?(REXML::Document) doc = REXML::Document.new(data.read) if doc.root merge_element!({}, doc.root) else raise REXML::ParseException, "The document #{doc.to_s.inspect} does not have a valid root" end end end -
Simon Chiu
I wonder if this is one of those incompatibilities with Ruby 1.8 vs 1.9. I was using 1.8.7 when I came across this error, but the patch seemed to have fixed it. I will try and use 1.9-head tonight and see if I can duplicate the problem.
Just in case, can someone post an example XML which caused the error for them?
-
Si
Even something minimal like will do it.
If I use NokogiriSAX as my XmlMini backend, your patch works as hoped however.
-
Si
Ha! I should have used preview :)
Even something minimal like
<oops/>will do it.
-
Gaël Deest
Any update on this ? I'm seeing this bug too and it is pretty annoying.
-
Simon Chiu
Gael, are you also using Ruby 1.9.2-head?
-
Gaël Deest
Nope, I'm using Ruby Enterprise Edition 1.8.7 with rack 1.1.0 on the remote (ActiveResource) server, behind SSL and HTTP basic authentication. Switching the XmlMini backend from REXML to Nokogiri did not help.
If I'm understanding the issue correctly, the XML sent by the client can not be parsed because the XML parser expects the rack object to respond to unknown 'getc' and 'ungetc' methods. So this probably affects any XML controller and I would expect more people to complain. Perhaps there is something special in our setup (such as SSL) that triggers the problem ?
-
Simon Chiu
Gael,
I'm just curious what is preventing your set up from working.
Try putting this Gist in your initializer directory and see if it works: http://gist.github.com/373797
Simon
-
Gaël Deest
Your monkey patch seems to work. Thanks !
-
Simon Chiu
Okay, I will look at the patch and see if I messed up somewhere. Thanks Gael.
-
Gaël Deest
Oh, I had not applied your patch yet so it may be perfectly fine. Thanks to your for taking some time to address this issue !
-
Lawrence Pit
- Tag changed from active_resource, passenger, rack, xml_mini to actiondispatch, active_resource, passenger, rack, rails3, xml_mini
- Assigned user set to Jeremy Kemper
This shouldn't be solved by patching the xmlmini classes.
The issue only occurs in development mode. This is because Rack adds the middleware Rack::Lint when in development mode, which results in all input to Rails being wrapped into a Rack::Lint::InputWrapper. This is not an IO class, and therefor fails as input into all the XML parsers.
Attached is a patch to solve this issue.
Note: at this moment it's not possible to add a proper test for this, as rack's Rack::MockRequest always returns a StringIO stream for env['rack.input']. I'm currently working on a patch for Rack to remedy this, as I think tests should work with Rack::Lint::InputWrapper instances instead (which would then show the current xml tests failing without the attached patch): StringIO basically doesn't comply with the Rack specification.
-
Mat Schaffer
Just thought I'd mention that we've hit this running in production mode as well. Thanks for your work on this, looking forward to a fix.
-
Gaël Deest
I too met this bug in production.
-
Jeremy Kemper
- State changed from new to open
Sounds like our only option for streaming parsing is to provide an IO wrapper than treats
getcasread. Nasty.Patch + test welcome to read the full IO to a string first instead, reverting the streaming behavior.
-
Lawrence Pit
Mat and Gael, it /is/ possible that you get this issue in production as well, because any rack middleware that adds itself and wraps the input which strictly conforms to the Rack protocol will cause this issue.
-
Lawrence Pit
Jeremy, attached patch with test.
-
Mat Schaffer
Thanks for the clarification, Lawrence. If it helps, the app in question is using Rack::URLMap in config.ru (for switching between the main app and Resque::Server) as well as HoptoadNotifier::Rack in production.rb as middleware.
I'll try out some of these patches and let you know if I find anything. Thanks!
-
Mat Schaffer
That rackinput.diff patch seems to do the trick for my app. Good find, Lawrence!
I also did a test app without any middleware and was able to produce this under Passenger (development and production envs). Seems that the Rack environment in Passenger is a little more strict than others.
Thanks again.
-
Repository
- State changed from open to committed
(from [1e1d30715ee75312b41045d2af1c68492ea66a05]) Fix parsing xml input by ActionDispatch::ParamsParser
[#4437 [Patch] XML Mini Parser NoMethodError :getc when application running through ... state:committed]
Signed-off-by: Jeremy Kemper jeremy@bitsweat.net
http://github.com/rails/rails/commit/1e1d30715ee75312b41045d2af1c68...
