Archive | January 2011

Rails Session ArgumentError: key too long [SOLVED]

Problem

I am migrating an app from one version of Ruby to another. In my rollout I decided to first launch one server using the new version of Ruby 1.9.2 and adjust the load balancer to only move over about 10% of the traffic to it. I noticed in newrelic that within 10 minutes there were tons of exceptions like:

ArgumentError: key too long "rt:BAh7Czozg3OWY4MWRkMjAyYjlkNzljNmUwNWYwZDRhMDQ6F
GFiaW5nb19pZGVudGl0eUkiDzEyMTc2ODUyNzIGOgZFRjoKcnRfYWJJIgZiBjsHRjodY2xpY2tfdHJh
Y2tpbmdfZmlyc3RfdXJsSSJAaHR0cDovL3JlYWx0cmF2ZWwuY29tL2ItMjM1MTM4LWxvbmRvbl9ib
G9nLWxvbmRvbjpfYV90b196ZWQGOwdGOihjbGlja190cmFja2luZ19vcmlnaW5hbF9yZWZlcmV
yX3VybCJgaHR0cDovL3d3dy5nb29nbGUuY29tL3NlYXJjaD9zb3VyY2U9aWcmaGw9ZW4mc
mx6PTFHMUdHTFFfRU5VUzQwMCZxPWxvbmRvbithK3RvK3plZCZhcT1mJm9xPToMcmVm
ZXJlckAK--65814e8bacff8432ac09e15520afb13117d0e5cd"
Stack trace (hide Rails)
/path/shared/bundle/ruby/1.8/gems/memcache-client-1.8.5/lib/memcache.rb:703:in `get_server_for_key'
/path/shared/bundle/ruby/1.8/gems/memcache-client-1.8.5/lib/memcache.rb:920:in `request_setup'
/path/shared/bundle/ruby/1.8/gems/memcache-client-1.8.5/lib/memcache.rb:885:in `with_server'
/path/shared/bundle/ruby/1.8/gems/memcache-client-1.8.5/lib/memcache.rb:246:in `get_MemCache_read'
/path/shared/bundle/ruby/1.8/gems/actionpack-2.3.8/lib/action_controller/session/mem_cache_store.rb:31:in `get_session'

The interesting thing was that none of these errors were coming from the new server, but something on the new ruby server was breaking the other, so here is what I found was the problem.

Solution

The new server was configured to use the cookie store and the others were using memcached store. It sounds stupid and it is, but it wasn’t so easy to figure out at first. When I googled for the error I noticed that none of the issues had solutions, so thats why I decided to write this post.

In short, the session[:session_id] with the default cookie store passes both the session data and the session key into the cookie, and the memcached/db store’s only put the session_id from the cookie as session[:session_id].

May your session keys be truly keys!

Advertisements

Ruby 1.9.2, Encoding UTF-8 and Rails: invalid byte sequence in US-ASCII

Ruby 1.9.2, Encoding UTF-8 and Rails: invalid byte sequence in US-ASCII

written by Paul on January 20th, 2011 @ 12:05 AM

While working on a migration from ruby 1.8.7 to 1.9.2, I ran into some issues with encoding. Fortunately, we are using PostgreSQL and the database drivers are pretty good for UTF-8 support and encoding tagging, but there were still some snags in a few areas of my code.

My company, has pretty custom urls structures. Because of the concern of having multiple urls go to the same content and appearing to Google to be doing something bad, we have come code that ensures that the url that was requested is the same url that we would have generated and if it wasn’t we would redirect.

In this code, we generate a url and compare it to the value ofrequest.request_uri to see if we should redirect or not. On issue that came up is that Nginx and Passenger encode the unicode characters and Rack turns it into Binary, which is ASCII-8bit, but its really just means that no encoding is assigned.

In the browser a url might look like this:

/h-336461-amboise_hotel-château_de_noizay

But when my code genrated the url it looked like this:

/h-336461-amboise_hotel-ch%C3%A2teau_de_noizay

The above could easily be fixed with this:

URI.unescape(canonical_url)

Then I had issued where I had a URL (request.request_uri) like:

/h-336461-amboise_hotel-ch\xC3\xA2teau_de_noizay

It was ASCII-8bit which is really a way of saying that its binary or in other words that no encoding is set. The solution was pretty easy, I just assigned it the encoding that I knew it should be:

/h-336461-amboise_hotel-ch\xC3\xA2teau_de_noizay".force_encoding('UTF-8')
  # => "/h-336461-amboise_hotel-château_de_noizay"

Then I had an issue where templates/views were breaking due to some data in a haml view thinking that the test was ASCII: The test was supposed to look like this “Details for Château de Noizay,” but haml raised an exception “ActionView::TemplateError (invalid byte sequence in US-ASCII).”

After digging around a bit I was able to configure Apache (on my mac) by adding the following to the /etc/profile.

export LANG=en_US.UTF-8

Then after restarting Apache on my mac, I refreshed, and when I did, the text that was supposed to look like “Details for Château de Noizay” ended up looking like “Details for Ch 도teau de Noizay”.

I was about to write my own hybrid asian/latin based languages but instead added the following to my environment.rb and everything seemed to come together like I had hoped it would.

Encoding.default_internal = 'UTF-8'

Now that my app was able to run without encoding errors, I said “yeah!”

Hope this scribble scrabble helps some poorly encoded soul.

Thanks to a few articles I was not only reminded of some of the basics of encoding but learned to embrace the new changes within Ruby 1.9.2. We’ll see how tomorrow goes. 😉

 

Changing File Encoding Using Ruby 1.9.2

Changing File Encoding Using Ruby 1.9.2

written by Paul on January 3rd, 2011 @ 06:22 AM

Currently, I am in the process of upgrading an application from Ruby 1.8.7 to Ruby 1.9.2. One of the big differences between 1.8 and 1.9 is the multi-byte character support.

The Problem

We have thousands of static html files that were generated in Ruby 1.8 and when Ruby 1.9 reads them it fails. As usual, before I start to dig in to solving the problem I do a quick search and see what other people have been doing to solve the problem. My search yielded a bunch of multi-lined scripts and techniques… most of which were from the Ruby 1.8 days.

The Solution

In short I wrote a simple 4 lined script in irb and it completed my task quickly. One thing that I am really happy about it how Ruby 1.9.2 strings have a method called escape that provides great utility when performing these kinds of tasks.

So here is the code:


`find . -name '*.html'`.split("\n").each do |filename|
  puts filename
  handle = File.open(filename,"w+")
  handle.write(handle.read.encode('UTF-8'))
  handle.close
end; nil

If you are interested in the options with the encode method, go check them out.