Friday, May 18, 2007

RoR: unexpected nil when trying to parse a query string

While sending a HTTP post message that contains a substring '&&' in the body to a ruby on rails application, there is a error reported:

==================================================
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.include?
/public/../config/../vendor/rails/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb:49:in `parse_request_parameters'
/public/../config/../vendor/rails/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb:47:in `parse_request_parameters'
/public/../config/../vendor/rails/actionpack/lib/action_controller/cgi_process.rb:71:in `request_parameters'
/public/../config/../vendor/rails/actionpack/lib/action_controller/request.rb:13:in `parameters'
/public/../config/../vendor/rails/actionpack/lib/action_controller/session_management.rb:122:in `set_session_options_without_components'
/public/../config/../vendor/rails/actionpack/lib/action_controller/components.rb:178:in `set_session_options'
/public/../config/../vendor/rails/actionpack/lib/action_controller/session_management.rb:116:in `process'
/public/../config/../vendor/rails/railties/lib/dispatcher.rb:38:in `dispatch'
/public/../config/../vendor/rails/railties/lib/fcgi_handler.rb:150:in `process_request'
/public/../config/../vendor/rails/railties/lib/fcgi_handler.rb:54:in `process!'
/usr/lib/ruby/site_ruby/1.8/fcgi.rb:612:in `each_cgi'
/usr/lib/ruby/site_ruby/1.8/fcgi.rb:609:in `each_cgi'
/public/../config/../vendor/rails/railties/lib/fcgi_handler.rb:53:in `process!'
/public/../config/../vendor/rails/railties/lib/fcgi_handler.rb:23:in `process!'
/public/dispatch.fcgi:24
==================================================

The error occurred because '&' is the separator of different name/value pair in a message body, such as "name1=value1&name2=value2", and rails framework doesn't handle the string "&&" properly. According to a bug report and its patch in rubyonrails.org (http://dev.rubyonrails.org/ticket/5714), we need to change "/vendor/rails/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb" line 47 from

==================================================
for key, value in params
value = [value] if key =~ /.*\[\]$/
unless key.include?('[')
# much faster to test for the most common case first (GET)
# and avoid the call to build_deep_hash
parsed_params[key] = get_typed_value(value[0])
else
build_deep_hash(get_typed_value(value[0]), parsed_params, get_levels(key))
end
end
==================================================

to

==================================================
for key, value in params
if (not key.nil?)
value = [value] if key =~ /.*\[\]$/
unless key.include?('[')
# much faster to test for the most common case first (GET)
# and avoid the call to build_deep_hash
parsed_params[key] = get_typed_value(value[0])
else
build_deep_hash(get_typed_value(value[0]), parsed_params, get_levels(key))
end
end
end
==================================================