views:

143

answers:

1

I'm working with a Ruby on Rails application that makes a client side API call to a 3rd party service. It then takes strings from the 3rd party API and generates URIs with them.

Unfortunately, Rails fails to parse some of the URIs due to encoding errors. I have tried running the strings through encodeURIComponent, but this does not resolve the issue.

Here is the error I get:

Processing ApplicationController#index (for 67.101.113.66 at 2010-08-12 23:24:55) [GET]
  Parameters: {"name"=>"Camilo Andr\xE9s \xD1ustes", "recipient_id"=>"279"}

ArgumentError (invalid byte sequence in US-ASCII):
  <internal:prelude>:8:in `synchronize'
  /home/heroku_rack/lib/static_assets.rb:9:in `call'
  /home/heroku_rack/lib/last_access.rb:25:in `call'
  /home/heroku_rack/lib/date_header.rb:14:in `call'
  thin (1.2.6) lib/thin/connection.rb:76:in `block in pre_process'
  thin (1.2.6) lib/thin/connection.rb:74:in `catch'
  thin (1.2.6) lib/thin/connection.rb:74:in `pre_process'
  thin (1.2.6) lib/thin/connection.rb:57:in `process'
  thin (1.2.6) lib/thin/connection.rb:42:in `receive_data'
  eventmachine (0.12.10) lib/eventmachine.rb:256:in `run_machine'
  eventmachine (0.12.10) lib/eventmachine.rb:256:in `run'
  thin (1.2.6) lib/thin/backends/base.rb:57:in `start'
  thin (1.2.6) lib/thin/server.rb:156:in `start'
  thin (1.2.6) lib/thin/controllers/controller.rb:80:in `start'
  thin (1.2.6) lib/thin/runner.rb:177:in `run_command'
  thin (1.2.6) lib/thin/runner.rb:143:in `run!'
  thin (1.2.6) bin/thin:6:in `<top (required)>'
  /usr/ruby1.9.1/bin/thin:19:in `load'

  /usr/ruby1.9.1/bin/thin:19:in `<main>'

How do I properly handle these strings as input for my application?

A: 

This works for me: <%= u name -%>

I use this technique everytime i have to pass on auth token around in my views: <%= u form_authenticity_token %>

Since the above is for views, if you want ruby specific:

require 'uri'
foo = "http://google.com?query=hello"

bad = URI.escape(foo)
good = URI.escape(foo, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))

bad_uri = "http://mysite.com?service=#{bad}&amp;bar=blah"
good_uri = "http://mysite.com?service=#{good}&amp;bar=blah"

puts bad_uri
# outputs "http://mysite.com?service=http://google.com?query=hello&amp;bar=blah"

puts good_uri
# outputs "http://mysite.com?service=http%3A%2F%2Fgoogle.com%3Fquery%3Dhello&amp;bar=blah"

Hope this helps.

Shripad K
Thanks. If this is the solution, however, I need to do it in javascript.The name comes from a jsonp api call, and then is appended to the url.My solution for now was to switch the application to use Ruby 1.8 instead of 1.9.
Gdeglin
Even if it comes from a jsonp api call i am guessing you are receiving it in the controller's action as `params[:name]`, `params[:recepient_id]` right? Why not just do `URI.escape(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))`? I see from the log output that you are receiving the parameters.. Just escape it before storing/manipulating the data. If you could provide a skinny version of your controller's action it would be more easier to provide a solution.
Shripad K
It's a jsonp api call that's all done client side. The data is then sent to a rails controller. It fails inside of Rack before it even hits the controller action.
Gdeglin