JSON-P Rack Handler 1

Posted by acts_as_flinn Tue, 17 Jun 2008 01:58:00 GMT

Updated 2008-06-19 – better support Halcyon

JSON-P Rack Handler

Juicing Ruby

I’ve been trying to find ways to squeeze all the juice out of Ruby lately. So many blog posts talk about how Rails doesn’t scale, Ruby is slow, blah blah. I had a convo with another developer at work today that went something like this:

Me: if we’re willing to do anything for performance we’d we just switch to Java

Jared: Yeah let’s not do that.

Switching to Java would be a big trade off in performance but also in development time. That’s a big trade off that none of us around here think is worth. That’s where this Rack handler comes in.

JSON-P Caching

I’ve posted before about how to use JSON-P in Rails and how to cache JSON-P in Rails with fairly decent results (500+ reqs/sec) but I felt like I could do better. Action caching always seemed like the best way to cache the full JSON output of a request but the fact that jQuery uses a dynamic callback takes action caching out of the equation.

Speeding up JSON-P

500+ reqs/sec is good and all but I felt like if I could action cache then somehow pad that cached JSON result with the callback I’d get better performance. I thought I’d see what Merb could offer on the JSON-P front. In my quest to juice Ruby my test setup looks like this: Merb, Datamapper, Memcached (the c gem), Memcached (the server) and Ebb. I’m really impressed with Merb and Datamapper in terms of development and I’m equally impressed with Rack and Ebb for performance.

I read recently it’s possible to use Rack to filter results to gzip output, which got me thinking. Why not try to do the same to pad my action cached JSON. Well it is possible and I’m squeezing out JSON-P at ~1200 reqs/sec with the JSON-P Rack Handler with my test stack.

JSON-P Rack Handler


# config/jsonp.rb
class JsonP
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, response = @app.call(env)
    request = Rack::Request.new(env)
    response = pad(request.params.delete('callback'), response) if request.params.include?('callback')
    [status, headers, response]
  end

  def pad(callback, response, body = "")
    response.each{ |s| body << s }
    "#{callback}(#{body})" 
  end
end

Config


# config/rack.rb
require 'config/jsonp'
use JsonP
run Merb::Rack::Application.new

In Halcyon


# runner.ru
...
require 'config/jsonp.halcyon'
use JsonP
run Halcyon::Runner.new

Rails Support Soon

One last thing… whenever Rails starts using Rack, you’ll be able to use this in your Rails app.

About Me: I’m a developer with Sports Technologies, a Rails firm specializing in community focused web applications aimed at sports and entertainment. We’re always looking for Rails talent, if you’re looking to work on rewarding high profile projects with a seasoned team of professionals give us a shout.

Trackbacks

Use the following link to trackback from your own site:
http://www.actsasflinn.com/trackbacks?article_id=json-p-rack-handler&day=16&month=06&year=2008

Comments

Leave a response

  1. Avatar
    Matt Todd 3 days later:
    Hey Flinn, I've integrated your JSON-P middleware into Halcyon. When Halcyon 0.5.1 is officially released, you will simply need to update your runner.ru file to: use Rack::JSONP and it will behave exactly as above. Thanks for the excellent contribution. Hopefully it will make it into the Rack codebase and I can remove it from Halcyon, but for now, that's where it will live. Matt
Comments


ss_blog_claim=746d258dc975cb7923cc57154dbf1d71