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:

No comments:

Post a Comment