Question

Sinatra allows the return values of route blocks to take many different forms.

How does Sinatra know how to extract status, headers, and body from each type of return value?

Particularly, I'm looking for the source code (logic) that does this, because I'd like to do something similar.

I've searched the Sinatra & Rack sources to no avail.

Was it helpful?

Solution

The code you’re looking for is in the invoke method:

def invoke
  res = catch(:halt) { yield }
  res = [res] if Fixnum === res or String === res
  if Array === res and Fixnum === res.first
    res = res.dup
    status(res.shift)
    body(res.pop)
    headers(*res)
  elsif res.respond_to? :each
    body res
  end
  nil # avoid double setting the same response tuple twice
end

There are a couple of quirks to look out for. For example if you return a hash Sinatra will see that it responds to each and treat it as the body, but since it doesn’t yield strings this can cause an error or unexpected results when the webserver tries to send the content. Also the rack spec says this about the status: “When parsed as integer (to_i), it must be greater than or equal to 100” and so you should be able to pass a string like "200" that will be converted with to_i, but Sinatra only looks for Fixnums, which goes against its claim of “You can return any object that would either be a valid Rack response”.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top