Code Safari: Almost Sinatra, Almost Readable
Sinatra is a minimal web framework for creating web applications in Ruby with minimal effort. Almost Sinatra is the same thing, but in only eight lines of code. Surely some trickery is afoot? Let’s have a look at those lines.
# almost-sinatra/almost_sinatra.rb
%w.rack tilt backports INT TERM..map{|l|trap(l){$r.stop}rescue require l}
$n=Sinatra=Module.new{extend Rack;a,D,S,$p,q,Application=Builder.new,Object.method(:define_method),/@@ *([^n]+)n(((?!@@)[^n]*n)*)/m,4567,a
%w[get post put delete].map{|m|D.(m){|u,&b|a.map(u){run->(e){[200,{"Content-Type"=>"text/html"},[a.instance_eval(&b)]]}}}}
Tilt.mappings.map{|k,v|D.(k){|n,*o|$t||=(h={};File.read(caller[0][/^[^:]+/]).scan(S){|a,b|h[a]=b};h);v.new(*o){n.to_s==n ?n:$t[n.to_s]}.render(a,o[0].try(:[],:locals)||{})}}
%w[set enable disable configure helpers use register].map{|m|D.(m){|*_,&b|b.try :[]}};END{Handler.get("webrick").run(a,Port:$p){|s|$r=s}}
%w[params session].map{|m|D.(m){q.send m}};a.use Session::Cookie;a.use Lock
D.(:before){|&b|a.use Rack::Config,&b};before{|e|q=Request.new e;q.params.dup.map{|k,v|params[k.to_sym]=v}}}
puts "== almost #$n/No Version has taken the stage on #$p for development with backup from Webrick"
That’s the lot of it. Sure is dense! There are some gems in here, so let’s start picking it apart, line by line. Reading obfuscated code is a great way to jump in the deep end and really get personal with a language’s syntax, and by the end of this article you’ll be ready to move in and leave dirty dishes on the couch.
Line One
I have taken the first line and reformatted it across multiple to make it easier to read. This is always my first step when dealing with obfuscated code. Often renaming variables to something meaningful can also be helpful too, though I haven’t done that in this article.
%w.rack tilt backports INT TERM..map{|l|
trap(l) {
$r.stop
} rescue require l
}
What is that initial syntax? It looks like a list given the #map
call trailing it, but it’s like no list I’ve seen. This type of code is hard to find information on, since googling for punctuation is rarely useful. Given it looks like an array, I took a punt and searched for ‘ruby array syntax’ which revealed the arrays section in the ruby programming wikibook:
%w is in essence shorthand for the String method split when the substrings are separated by whitespace only.
The example given uses '
as a delimiter, and using irb
we can confirm that we can use any punctuation after the %w
. The choice of which to use is solely a matter of style.
%w'rack tilt' # => ["rack", "tilt"]
%w.rack tilt. # => ["rack", "tilt"]
%w(rack tilt) # => ["rack", "tilt"]
%w!rack tilt! # => ["rack", "tilt"]
Now turn our attention to the contents of the list – it seems to contain both files to require and signals to rescue. Since rack
, tilt
, and backports
are all invalid signal names, the #trap
call will raise an exception. Normally in ruby exceptions are rescued explicitly:
begin
trap("bogus signal name") {}
rescue ArgumentError => e
puts "Invalid signal name"
end
Ruby also allows a trailing form though, in the same way that you can do with if
statements.
puts "Small enough" if line_count <= 10
trap("bogus") {} rescue puts ":("
This will rescue all exceptions though, which isn’t the sort of cowboy behaviour you want to spread liberally through your code base. Not to mention using exceptions for flow control, but when lines are at a premium everything is fair game.
Line Two
With the requires and other preamble out of the way, let’s dive into the framework proper.
$n = Sinatra = Module.new {
extend Rack;
a,D,S,$p,q,Application =
Builder.new,
Object.method(:define_method),
/@@ *([^n]+)n(((?!@@)[^n]*n)*)/m,
4567,
a
There are a few interesting techniques here. The first is dynamically defining a Module
. In ruby everything is an object, even modules and classes, so where you would normally use the module
keyword to define a module, you can do so on the fly by calling Module.new
. The only difference is that the keyword form will have an explicit name and constant defined, whereas the latter will be anonymous.
module Test
end
Test.name # => 'Test'
Module.new.name # => nil
Variable names prefixed with $
are not seen often, so they may be unfamiliar to you. Searching for ‘ruby variable types’ found an article with a handy table summarizing the different prefixes, and in this case we find that a variable beginning with $
is a global variable. That would be why you don’t see them so often…
There are two forms of variable assignment used here. The one used on the first line relies on the fact that everything in ruby implicitly returns a value. You can see this in irb
– every statement executed has a value shown after it, even it is often nil.
# puts returns the value 'nil'
irb> puts "hello"
hello
=> nil
Assignment returns the value being assigned, meaning that you can chain them together. In the snippet above, this means that $n
and Sinatra
will be assigned the same Module
.
irb> $n = Sinatara = Module.new {}
irb> $n == Sinatra
=> true
The other assignment trick being used is called multiple or parallel assignment, which allows you to assign different values to different variables all on the one line. What is interesting about this usage is that one of the variables on the left hand side a
is reused on the right hand side to assign to the Application constant. I was very confused by this for a while, but after playing around in irb
confirmed it is actually a bug in the code!
a,Application=1,a # => [1, nil]
a=1;Application=a
Line Three
This line sets up methods for the different HTTP verbs, and to comprehend it we would first need to first be familiar with the Rack::Builder
API, since an instance of this class is assigned to the D
variable. That’s a bit of a tangent, so I am going to leave that for a future article, and instead focus on the two interesting syntax features this snippet uses, both related to lambdas and introduced in ruby 1.9.
%w[get post put delete].map{|m|
D.(m){|u,&b|
a.map(u){
run->(e){
[200,{"Content-Type"=>"text/html"},[a.instance_eval(&b)]]
}
}
}
}
The first is a new way of calling lambas and procs, .()
, which is an alias for #call
. This brings the total number of ways to call a lambda in ruby to three:
add_two = lambda {|x| x + 2 }
add_two.call(1) # => 3
add_two.(1) # => 3
add_two[1] # => 3
There are subtle differences: .()
will always delegate to #call
whereas []
can be overridden separately, but for the most part they are equivalent.
The other interesting syntax is run->(e){}
. This is affectionately known as the “stabby” syntax, and is a new way of defining lambdas that was introduced to allow default argument values to be specified. This would be impossible for the ruby parser to deal with using the old run(lambda {|e| })
syntax (more details if you are keen).
add_two = lambda {|x| x + 2}
add_two = ->(x) { x + 2 } # The same!
double_or_add = ->(a,b=a|2) { a + b } # Just try that with the old syntax...
The old syntax is going to be around forever, but the new way gives you a less verbose, more flexible option.
And the rest
Told you it was dense! A whole article and we are only three lines in. On the other hand, it’s half way through a framework! We covered a lot of interesting syntax in a short amount of time:
%w
array syntax- Trailing
rescue
syntax - Anonymous modules using
Module.new
- Chaining assignment (
a = b = 1
) - Multiple assignment (
a,b = 1,2
) .()
syntax for calling code blocks->()
“stabby” syntax for writing lambdas
The remaining lines are mostly more of the same, but there a couple of curve balls. For practice, I recommend you continue to work through them. Other projects to sharpen your knife on:
- Camping, the 4k pocket full-of-gags web microframework. This is an old-school framework that has been around for years. It includes an unabridged version and as such is a relatively gentle introduction to obsfucated code.
- It’s old, but entries to the 2005 International Obfuscated Ruby Code Contest, helpfully mirrored in this blog post.
Let us know how you go in the comments. Tune in next week for more exciting adventures in the code jungle.