class Sinatra::Base

Base class for all Sinatra applications and middleware.

def before(&block)

request and response.
within the same context as route handlers and may access/modify the
Define a before filter. Filters are run before all requests
def before(&block)
  @filters << block
end

def call(env)

Rack call interface.
def call(env)
  dup.call!(env)
end

def call(env)

def call(env)
  synchronize { prototype.call(env) }
end

def call!(env)

def call!(env)
  @env      = env
  @request  = Request.new(env)
  @response = Response.new
  @params   = nil
  invoke { dispatch! }
  invoke { error_block!(response.status) }
  status, header, body = @response.finish
  # Never produce a body on HEAD requests. Do retain the Content-Length
  # unless it's "0", in which case we assume it was calculated erroneously
  # for a manual HEAD response and remove it entirely.
  if @env['REQUEST_METHOD'] == 'HEAD'
    body = []
    header.delete('Content-Length') if header['Content-Length'] == '0'
  end
  [status, header, body]
end

def caller_files

line / method information; the resulting array contains filenames only.
Like Kernel#caller but excluding certain magic entries and without
def caller_files
  caller_locations.
    map { |file,line| file }
end

def caller_locations

def caller_locations
  caller(1).
    map    { |line| line.split(/:(?=\d|in )/)[0,2] }.
    reject { |file,line| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
end

def clean_backtrace(trace)

def clean_backtrace(trace)
  return trace unless options.clean_trace?
  trace.reject { |line|
    line =~ /lib\/sinatra.*\.rb/ ||
      (defined?(Gem) && line.include?(Gem.dir))
  }.map! { |line| line.gsub(/^\.\//, '') }
end

def compile(path)

def compile(path)
  keys = []
  if path.respond_to? :to_str
    special_chars = %w{. + ( )}
    pattern =
      path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
        case match
        when "*"
          keys << 'splat'
          "(.*?)"
        when *special_chars
          Regexp.escape(match)
        else
          keys << $2[1..-1]
          "([^/?&#]+)"
        end
      end
    [/^#{pattern}$/, keys]
  elsif path.respond_to?(:keys) && path.respond_to?(:match)
    [path, path.keys]
  elsif path.respond_to? :match
    [path, keys]
  else
    raise TypeError, path
  end
end

def condition(&block)

block returns false.
Add a route condition. The route is considered non-matching when the
def condition(&block)
  @conditions << block
end

def configure(*envs, &block)

Allows scoping of settings for certain environments.
Set configuration options for Sinatra and/or the app.
def configure(*envs, &block)
  yield self if envs.empty? || envs.include?(environment.to_sym)
end

def delete(path, opts={}, &bk); route 'DELETE', path, opts, &bk end

def delete(path, opts={}, &bk); route 'DELETE', path, opts, &bk end

def detect_rack_handler

def detect_rack_handler
  servers = Array(self.server)
  servers.each do |server_name|
    begin
      return Rack::Handler.get(server_name.downcase)
    rescue LoadError
    rescue NameError
    end
  end
  fail "Server handler (#{servers.join(',')}) not found."
end

def development?; environment == :development end

def development?; environment == :development end

def disable(*opts)

Same as calling `set :option, false` for each of the given options.
def disable(*opts)
  opts.each { |key| set(key, false) }
end

def dispatch!

Dispatch a request with error handling.
def dispatch!
  route!
rescue NotFound => boom
  handle_not_found!(boom)
rescue ::Exception => boom
  handle_exception!(boom)
end

def dump_errors!(boom)

def dump_errors!(boom)
  backtrace = clean_backtrace(boom.backtrace)
  msg = ["#{boom.class} - #{boom.message}:",
    *backtrace].join("\n ")
  @env['rack.errors'].write(msg)
end

def dupe_routes

def dupe_routes
  routes.inject({}) do |hash,(request_method,routes)|
    hash[request_method] = routes.dup
    hash
  end
end

def enable(*opts)

Same as calling `set :option, true` for each of the given options.
def enable(*opts)
  opts.each { |key| set(key, true) }
end

def error(codes=Exception, &block)

handled.
class, or an HTTP status code to specify which errors should be
Define a custom error handler. Optionally takes either an Exception
def error(codes=Exception, &block)
  if codes.respond_to? :each
    codes.each { |err| error(err, &block) }
  else
    @errors[codes] = block
  end
end

def error_block!(*keys)

Find an custom error block for the key(s) specified.
def error_block!(*keys)
  errmap = self.class.errors
  keys.each do |key|
    if block = errmap[key]
      res = instance_eval(&block)
      return res
    end
  end
  nil
end

def extensions

def extensions
  (@extensions + (superclass.extensions rescue [])).uniq
end

def forward

Forward the request to the downstream app -- middleware only.
def forward
  fail "downstream app not set" unless @app.respond_to? :call
  status, headers, body = @app.call(@request.env)
  @response.status = status
  @response.body = body
  @response.headers.merge! headers
  nil
end

def get(path, opts={}, &block)

a `HEAD` handler.
Defining a `GET` handler also automatically defines
def get(path, opts={}, &block)
  conditions = @conditions.dup
  route('GET', path, opts, &block)
  @conditions = conditions
  route('HEAD', path, opts, &block)
end

def halt(*response)

of the request, and returns the specified response.
Exit the current block, halts any further processing
def halt(*response)
  response = response.first if response.length == 1
  throw :halt, response
end

def handle_exception!(boom)

def handle_exception!(boom)
  @env['sinatra.error'] = boom
  dump_errors!(boom) if options.dump_errors?
  raise boom         if options.raise_errors? || options.show_exceptions?
  @response.status = 500
  error_block! boom.class, Exception
end

def handle_not_found!(boom)

def handle_not_found!(boom)
  @env['sinatra.error'] = boom
  @response.status      = 404
  @response.body        = ['<h1>Not Found</h1>']
  error_block! boom.class, NotFound
end

def head(path, opts={}, &bk); route 'HEAD', path, opts, &bk end

def head(path, opts={}, &bk);   route 'HEAD',   path, opts, &bk end

def helpers(*extensions, &block)

in `extensions` available to the handlers and templates
Makes the methods defined in the block and in the Modules given
def helpers(*extensions, &block)
  class_eval(&block)  if block_given?
  include(*extensions) if extensions.any?
end

def host_name(pattern)

def host_name(pattern)
  condition { pattern === request.host }
end

def indifferent_hash

def indifferent_hash
  Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
end

def indifferent_params(params)

Enable string or symbol key access to the nested params hash.
def indifferent_params(params)
  params = indifferent_hash.merge(params)
  params.each do |key, value|
    next unless value.is_a?(Hash)
    params[key] = indifferent_params(value)
  end
end

def inherited(subclass)

def inherited(subclass)
  subclass.reset! self
  super
end

def initialize(app=nil)

def initialize(app=nil)
  @app = app
  yield self if block_given?
end

def inline_templates=(file=nil)

when no file is specified.
Load embeded templates from the file; uses the caller's __FILE__
def inline_templates=(file=nil)
  file = (file.nil? || file == true) ? caller_files.first : file
  begin
    app, data =
      ::IO.read(file).gsub("\r\n", "\n").split(/^__END__$/, 2)
  rescue Errno::ENOENT
    app, data = nil
  end
  if data
    lines = app.count("\n") + 1
    template = nil
    data.each_line do |line|
      lines += 1
      if line =~ /^@@\s*(.*)/
        template = ''
        templates[$1.to_sym] = { :filename => file, :line => lines, :template => template }
      elsif template
        template << line
      end
    end
  end
end

def invoke(&block)

Run the block with 'throw :halt' support and apply result to the response.
def invoke(&block)
  res = catch(:halt) { instance_eval(&block) }
  return if res.nil?
  case
  when res.respond_to?(:to_str)
    @response.body = [res]
  when res.respond_to?(:to_ary)
    res = res.to_ary
    if Fixnum === res.first
      if res.length == 3
        @response.status, headers, body = res
        @response.body = body if body
        headers.each { |k, v| @response.headers[k] = v } if headers
      elsif res.length == 2
        @response.status = res.first
        @response.body   = res.last
      else
        raise TypeError, "#{res.inspect} not supported"
      end
    else
      @response.body = res
    end
  when res.respond_to?(:each)
    @response.body = res
  when (100...599) === res
    @response.status = res
  end
  res
end

def invoke_hook(name, *args)

def invoke_hook(name, *args)
  extensions.each { |e| e.send(name, *args) if e.respond_to?(name) }
end

def layout(name=:layout, &block)

Define the layout template. The block must return the template source.
def layout(name=:layout, &block)
  template name, &block
end

def media_type(type, value=nil)

def media_type(type, value=nil)
  sinatra_warn "media_type is deprecated; use mime_type instead"
  mime_type(type, value)
end

def metadef(message, &block)

def metadef(message, &block)
  (class << self; self; end).
    send :define_method, message, &block
end

def mime_type(type, value=nil)

Lookup or register a mime type in Rack's mime registry.
def mime_type(type, value=nil)
  return type if type.nil? || type.to_s.include?('/')
  type = ".#{type}" unless type.to_s[0] == ?.
  return Rack::Mime.mime_type(type, nil) unless value
  Rack::Mime::MIME_TYPES[type] = value
end

def nested_params(params)

this once Rack 1.0 is required.
hash. Rack 1.0 has a built in implementation of this method - remove
Recursively replace the params hash with a nested indifferent
def nested_params(params)
  return indifferent_hash.merge(params) if !params.keys.join.include?('[')
  params.inject indifferent_hash do |res, (key,val)|
    if key.include?('[')
      head = key.split(/[\]\[]+/)
      last = head.pop
      head.inject(res){ |hash,k| hash[k] ||= indifferent_hash }[last] = val
    else
      res[key] = val
    end
    res
  end
end

def new(*args, &bk)

an instance of the class new was called on.
pipeline. The object is guaranteed to respond to #call but may not be
Create a new instance of the class fronted by its middleware
def new(*args, &bk)
  builder = Rack::Builder.new
  builder.use Rack::Session::Cookie if sessions? && !test?
  builder.use Rack::CommonLogger    if logging?
  builder.use Rack::MethodOverride  if method_override?
  builder.use ShowExceptions        if show_exceptions?
  @middleware.each { |c,a,b| builder.use(c, *a, &b) }
  builder.run super
  builder.to_app
end

def not_found(&block)

Sugar for `error(404) { ... }`
def not_found(&block)
  error 404, &block
end

def pass

return a 404 response.
If there are no more matching routes, Sinatra will
Pass control to the next matching route.
def pass
  throw :pass
end

def post(path, opts={}, &bk); route 'POST', path, opts, &bk end

def post(path, opts={}, &bk);   route 'POST',   path, opts, &bk end

def production?; environment == :production end

def production?;  environment == :production  end

def prototype

The prototype instance used to process requests.
def prototype
  @prototype ||= new
end

def provides(*types)

def provides(*types)
  types = [types] unless types.kind_of? Array
  types.map!{|t| mime_type(t)}
  condition {
    matching_types = (request.accept & types)
    unless matching_types.empty?
      response.headers['Content-Type'] = matching_types.first
      true
    else
      false
    end
  }
end

def put(path, opts={}, &bk); route 'PUT', path, opts, &bk end

def put(path, opts={}, &bk);    route 'PUT',    path, opts, &bk end

def register(*extensions, &block)

def register(*extensions, &block)
  extensions << Module.new(&block) if block_given?
  @extensions += extensions
  extensions.each do |extension|
    extend extension
    extension.registered(self) if extension.respond_to?(:registered)
  end
end

def reset!(base=superclass)

def reset!(base=superclass)
  @routes     = base.dupe_routes
  @templates  = base.templates.dup
  @conditions = []
  @filters    = base.filters.dup
  @errors     = base.errors.dup
  @middleware = base.middleware.dup
  @prototype  = nil
  @extensions = []
end

def route(verb, path, options={}, &block)

def route(verb, path, options={}, &block)
  # Because of self.options.host
  host_name(options.delete(:host)) if options.key?(:host)
  options.each {|option, args| send(option, *args)}
  pattern, keys = compile(path)
  conditions, @conditions = @conditions, []
  define_method "#{verb} #{path}", &block
  unbound_method = instance_method("#{verb} #{path}")
  block =
    if block.arity != 0
      lambda { unbound_method.bind(self).call(*@block_params) }
    else
      lambda { unbound_method.bind(self).call }
    end
  invoke_hook(:route_added, verb, path, block)
  (routes[verb] ||= []).
    push([pattern, keys, conditions, block]).last
end

def route!

Run before filters and then locate and run a matching route.
def route!
  # enable nested params in Rack < 1.0; allow indifferent access
  @params =
    if Rack::Utils.respond_to?(:parse_nested_query)
      indifferent_params(@request.params)
    else
      nested_params(@request.params)
    end
  # before filters
  self.class.filters.each { |block| instance_eval(&block) }
  # routes
  if routes = self.class.routes[@request.request_method]
    original_params = @params
    path            = unescape(@request.path_info)
    routes.each do |pattern, keys, conditions, block|
      if match = pattern.match(path)
        values = match.captures.to_a
        params =
          if keys.any?
            keys.zip(values).inject({}) do |hash,(k,v)|
              if k == 'splat'
                (hash[k] ||= []) << v
              else
                hash[k] = v
              end
              hash
            end
          elsif values.any?
            {'captures' => values}
          else
            {}
          end
        @params = original_params.merge(params)
        @block_params = values
        catch(:pass) do
          conditions.each { |cond|
            throw :pass if instance_eval(&cond) == false }
          route_eval(&block)
        end
      end
    end
  end
  route_missing
end

def route_eval(&block)

Run a route block and throw :halt with the result.
def route_eval(&block)
  throw :halt, instance_eval(&block)
end

def route_missing

custom route miss logic.
a NotFound exception. Subclasses can override this method to perform
as middleware (@app is non-nil); when no downstream app is set, raise
implementation is to forward the request downstream when running
No matching route was found or all routes passed. The default
def route_missing
  if @app
    forward
  else
    raise NotFound
  end
end

def run!(options={})

Thin, Mongrel or WEBrick (in that order)
Run the Sinatra app as a self-hosted server using
def run!(options={})
  set options
  handler      = detect_rack_handler
  handler_name = handler.name.gsub(/.*::/, '')
  puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
    "on #{port} for #{environment} with backup from #{handler_name}" unless handler_name =~/cgi/i
  handler.run self, :Host => host, :Port => port do |server|
    trap(:INT) do
      ## Use thins' hard #stop! if available, otherwise just #stop
      server.respond_to?(:stop!) ? server.stop! : server.stop
      puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i
    end
  end
rescue Errno::EADDRINUSE => e
  puts "== Someone is already performing on port #{port}!"
end

def set(option, value=self)

the proc will be called every time the option is accessed.
Sets an option to the given value. If the value is a proc,
def set(option, value=self)
  if value.kind_of?(Proc)
    metadef(option, &value)
    metadef("#{option}?") { !!__send__(option) }
    metadef("#{option}=") { |val| metadef(option, &Proc.new{val}) }
  elsif value == self && option.respond_to?(:to_hash)
    option.to_hash.each { |k,v| set(k, v) }
  elsif respond_to?("#{option}=")
    __send__ "#{option}=", value
  else
    set option, Proc.new{value}
  end
  self
end

def settings

Access settings defined with Base.set.
def settings
  self.class
end

def synchronize(&block)

def synchronize(&block)
  if lock?
    @@mutex.synchronize(&block)
  else
    yield
  end
end

def template(name, &block)

Define a named template. The block must return the template source.
def template(name, &block)
  filename, line = caller_locations.first
  templates[name] = { :filename => filename, :line => line, :template => block }
end

def test?; environment == :test end

def test?;        environment == :test        end

def use(middleware, *args, &block)

Use the specified Rack middleware
def use(middleware, *args, &block)
  @prototype = nil
  @middleware << [middleware, args, block]
end

def use_in_file_templates!(file=nil)

def use_in_file_templates!(file=nil)
  sinatra_warn "use_in_file_templates! is deprecated; " \
    "use enable :inline_templates instead"
  set :inline_templates, file
end

def user_agent(pattern)

def user_agent(pattern)
  condition {
    if request.user_agent =~ pattern
      @params[:agent] = $~[1..-1]
      true
    else
      false
    end
  }
end