16 December, 2010

A compact idiom for some case-expression usages.

Motivation

At some point every Ruby programmer has written this pattern:

result = case item
when String
  string = item
  "item is a string: #{string}"
when Fixnum, Float
  num = item
  "item is a num: #{num}"
end

I could use directly the item variable in each when block, but this would make the code harder to read. Wouldn't it be nice if we had the item in a variable with a meaningful name plus and with no boilerplate?

Metaprogramming
We'll take advantage of Ruby's powerful metaprogramming capabilities to design a pattern that describes exactly what we want. This is the best I've come up with:

result = item.is do
  a String do |string|
    "item is a string: #{string}"
  end
  a Fixnum, Float do |number|
    "item is a number: #{number}"
  end
end

Implementation
This is how I would write it:

class IsArray < Array
  def a(*categories, &block)
    self.push({:categories => categories, :block => block})
  end    
end

class Object
  def is(&block)
    IsArray.new.instance_eval(&block).detect do |hash|
      if hash[:categories].any? { |category| category === self }
        break hash[:block] ? hash[:block].call(self) : nil
      end 
    end
  end
end

06 December, 2010

Intercepting HTTP traffic with a proxy

Motivation
You are debugging a webpage's Javascript (using Firebug or whatever) and you stumble over an undebuggable minified one-line script. Now what? indeed, there are some solutions for this specific problem, but I'd prefer a more generic approach; wouldn't be nice to fake URL? tweak images?

Javascript beautifier
First, we'll need a command-line Javascript beautifier. The one I chose was js-beautify, which needs rhino (an enormous and ugly Java beast), but other than that it works just fine. Surprisingly it was not yet packaged for ArchLinux, so i took the time to upload it to the AUR user's repository.

A man in the middle
The first idea that comes to mind is using an existing HTTP Proxy that intercepts operations and allow modifying requests and responses. I found some projects, but they all were too much complicated, so I ended up writing with my own custom code with Webrick (using this post as inspiration). I wrote then the blueprint, the configuration file (YAML format) I'd like to have:

port: 8080

urlmapping:
  - from: "^http://apple.com/"
    to: "http://freebsd.org/"
  
filters:
  - conditions: {content_type: "javascript"}
    command: "js-beautify"
  - conditions: {content_type: "image/jpeg"}
    command: "examples/change_image.sh"

YAML makes a good configuration format because it's a standardized and concise format with a direct translation to standard objects (hashes, lists, strings, ...), so the code can easily be used as a library (for Ruby programmers) and as a command-line executable (for everybody).

Show me the code

$ svn checkout http://tokland.googlecode.com/svn/trunk/proxy proxy
$ cd proxy
$ ruby proxynt.rb example/config.yaml

Browse source code

Webrick certainly has some drawbacks (for example, responses are not streamed, the whole body is given as a block), but it's ok for debugging purposes.

As a demo, check what the result of second filter in the YAML example (using change_image) on a website: