As of Curb 0.3.7, Curb comes with slightly better cookie support that makes it more “curl-like”.

It probably sounds like shameless self-promotion that I’m blogging about these changes since I’d contributed them. Well, yeah that’s true, but I’m also doing so because I doubt these changes will ever be made known since Curb doesn’t publicize any updates or changelogs.

Curb is my current number 1 HTTP client for Ruby so the more love it gets, the better.

Passing cookies as a string in Curb requests

Curl veterans will probably know how to do this with the curl binary:

curl -b "auth=abcdef; ASP.NET_SessionId=lotsatext;" example.com

This sends a request to example.com with 2 cookies named “auth” and “ASP.NET_SessionId” (I hate those big-ass ASP.NET cookies btw). There wasn’t a way to set this in Curb, so I looked up the libcurl C API docs and replicated the same option in Curb (commit on Github). An example:

curl = Curl::Easy.new('http://example.com/')
curl.cookies = 'auth=abcdef; ASP.NET_SessionId=big-wall-of-text;'
curl.perform

Of course, the cookies will more often be retrieved/constructed rather than a literal like in the example above. In my case, I was proxying cookies while trying to wrap an API around a site that doesn’t have one.

Passing cookies as a file via the “cookiefile” option

The second change is the new cookiefile option. This replicates curl commands like these:

curl -b cookies-to-send.txt www.example.com

with something like this in ruby:

curl = Curl::Easy.new('http://example.com/')
curl.cookiefile = '/path/to/cookies-to-send.txt'
curl.perform

The cookies file looks like this (you can get a sample with the --cookie-jar option to curl, e.g. curl --cookie-jar cookies.txt www.wego.com):

www.wego.com	FALSE	/	FALSE	0	lang
www.wego.com	FALSE	/	FALSE	0	user_country_code	SG

Check out the commit on Github if you’re interested.

Why would I use these?

Now you might be wondering how these 2 changes are useful – well, they are totally irrelevant to you if you’re not expecting any cookie support in Curb. However, if you’re accessing or scraping a site that uses cookie-based authentication, these changes allow you to keep your Curb client authenticated across sessions, even when doing HTTP POSTs (Curb doesn’t send cookies properly in POST requests even if curl.enable_cookies is set).

I’ve found these changes to Curb particularly useful since I vastly prefer Curb to most HTTP clients for its speed and lightweight implementation, and heavier scraper-type HTTP clients like Mechanize are a last resort.

Rails Metal has been available on Rails since version 2.3 – it’s old news. But if you haven’t used it or heard about it, you can find out more about Rails Metal on the RoR weblog and on Jesse Newland’s blog.

So anyway, I am one of those laggards and only wrote a Rails Metal piece not too long ago for a Rails app on Wego.com in an effort to optimize some high volume requests. It looked something like this:

class Adamantine
  def self.call(env)
    if env['PATH_INFO'] =~ ROUTE_REGEX
      location = Location.find(1) # Use ActiveRecord.

      [200, { 'Content-Type' => 'text/html' }, [location.to_json]]
    else
      # Leave it to Rails to deal with the request.
      [404, { 'Content-Type' => 'text/html' }, ['Not Found']]
    end
  end
end

Notice the use of an ActiveRecord model. It ran for quite awhile, almost 30 minutes, in production until I started getting notification emails about “Too many open database connections” to the MySQL server! The change was promptly rolled back and there was no cheezburger for me.

dam it!

As it turns out, Rails doesn’t take care of certain things in Rails Metal pieces, including the releasing of connections back to the database connection pool. A bit of googling turned up this bug in Rails’ bug tracker (see Josh Peek’s comment about ActiveRecord::Base.clear_active_connections!).

I rewrote the Rails Metal piece to always ensure it clears any active database connections with ActiveRecord::Base.clear_active_connections!:

class Adamantine
  def self.call(env)
    if env['PATH_INFO'] =~ ROUTE_REGEX
      location = Location.find(1)

      [200, { 'Content-Type' => 'text/html' }, [location.to_json]]
    else
      # Leave it to Rails to deal with the request.
      [404, { 'Content-Type' => 'text/html' }, ['Not Found']]
    end
  ensure
    # Release the connections back to the pool.
    ActiveRecord::Base.clear_active_connections!
  end
end

Moral of the story: Don’t forget to release your database connections if you’re using ActiveRecord in your Rails Metal. Or even better, don’t use ActiveRecord in Rails Metal – you’re aiming for raw speed anyway right?

Wow, it seems like I haven’t posted anything this year. Don’t worry, you aren’t rid of me yet. I’m still alive and posting updates to FriendFeed and (less often) to Twitter.

If you belong to what I imagine must be now the microscopic population of loyal readers of my blog, please do hook up with me on FriendFeed or Twitter. I’ll follow you back if you’re a reader!

Completely by accident, I discovered that you can now drag a tab out from its current window to a new window in a recent Firefox nightly. A short video 24-second better explains what I’m talking about:

This tab tearing capability is a pretty neat feature – I know you can already do this in Safari, Opera and Galeon. It’s really well done in Safari, which I think is what Firefox is emulating. Nice to see Firefox follow suit!

If you can’t wait for Firefox 3.1, try it out in a recent Firefox nighty build (remember to use a new profile unless you are willing to risk corrupting your daily profile).

I’m a heavy tabbed browsing user – I have around 30 tabs open in my day-to-day Firefox profile all the time. Since the day Firefox 3 was released, I’ve noticed Firefox progressively getting slower with this particular Firefox profile (I use a different profile for web development). When it got to the point where changing tabs took a noticeable pause of 1-2 seconds, I tweaked some of Firefox’s session store and history preferences and now things are blazing fast again.

Here’s what you can do:

  1. Go to about:config in Firefox.
  2. Type in “session” in the “Filter” box.
  3. Edit browser.sessionhistory.max_entries – this is the number of pages stored in the history of your browsing session. Basically these are pages that can be reached using your Back and Forward buttons. The default is 50 – I reduced it to 20.
  4. Edit browser.sessionhistory.max_total_viewers – this is the number of pages that are stored in RAM so that they aren’t re-processed by Firefox’s rendering engine. This is what allows you to go Back to a page in Firefox and have it load almost instantaneously. The number of pages stored actually depends on the amount of RAM on your machine (see this). I reduced this to 4 (I have 2GB RAM).
  5. Edit browser.sessionstore.max_tabs_undo – the number of tabs you can restore after closing them (you can do this with Ctrl/Cmd-Shift-T). The default of 10 is more than I really need, so I reduced it to 3 tabs.
  6. Edit browser.sessionstore.interval – Firefox saves your session after every 10 seconds by default. I changed this to a more conservative 30000 milliseconds.

You can read more about these preferences and more at the MozillaZine Knowledge Base. If you’ve any tips on how to improve Firefox’s performance, be sure to share!