class Sinatra::Helpers::Stream::Base

Base class for all Sinatra applications and middleware.

Constants

URI_INSTANCE

Attributes

errors[R]
filters[R]
routes[R]
templates[R]
app[RW]
env[RW]
params[RW]
request[RW]
response[RW]
template_cache[R]

Public Class Methods

new(app = nil) { |self| ... } click to toggle source
Calls superclass method Sinatra::Helpers::Stream::Templates.new
# File lib/sinatra/base.rb, line 886
def initialize(app = nil)
  super()
  @app = app
  @template_cache = Tilt::Cache.new
  yield self if block_given?
end
Also aliased as: new!
settings() click to toggle source

Access settings defined with ::set.

# File lib/sinatra/base.rb, line 922
def self.settings
  self
end

Private Class Methods

add_filter(type, path = nil, options = {}, &block) click to toggle source

add a filter

# File lib/sinatra/base.rb, line 1343
def add_filter(type, path = nil, options = {}, &block)
  path, options = //, path if path.respond_to?(:each_pair)
  filters[type] << compile!(type, path || //, block, options)
end
after(path = nil, options = {}, &block) click to toggle source

Define an after filter; runs after all requests within the same context as route handlers and may access/modify the request and response.

# File lib/sinatra/base.rb, line 1338
def after(path = nil, options = {}, &block)
  add_filter(:after, path, options, &block)
end
agent(pattern)
Alias for: user_agent
before(path = nil, options = {}, &block) click to toggle source

Define a before filter; runs before all requests within the same context as route handlers and may access/modify the request and response.

# File lib/sinatra/base.rb, line 1331
def before(path = nil, options = {}, &block)
  add_filter(:before, path, options, &block)
end
build(app) click to toggle source

Creates a Rack::Builder instance with all the middleware set up and the given app as end point.

# File lib/sinatra/base.rb, line 1478
def build(app)
  builder = Rack::Builder.new
  setup_default_middleware builder
  setup_middleware builder
  builder.run app
  builder
end
call(env) click to toggle source
# File lib/sinatra/base.rb, line 1486
def call(env)
  synchronize { prototype.call(env) }
end
caller_files() click to toggle source

Like Kernel#caller but excluding certain magic entries and without line / method information; the resulting array contains filenames only.

# File lib/sinatra/base.rb, line 1492
def caller_files
  cleaned_caller(1).flatten
end
caller_locations() click to toggle source

Like ::caller_files, but containing Arrays rather than strings with the first element being the file, and the second being the line.

# File lib/sinatra/base.rb, line 1498
def caller_locations
  cleaned_caller 2
end
cleaned_caller(keep = 3) click to toggle source

Like Kernel#caller but excluding certain magic entries

# File lib/sinatra/base.rb, line 1797
def cleaned_caller(keep = 3)
  caller(1).
    map!    { |line| line.split(/:(?=\d|in )/, 3)[0,keep] }.
    reject { |file, *_| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
end
compile(path) click to toggle source
# File lib/sinatra/base.rb, line 1617
def compile(path)
  if path.respond_to? :to_str
    keys = []

    # Split the path into pieces in between forward slashes.
    # A negative number is given as the second argument of path.split
    # because with this number, the method does not ignore / at the end
    # and appends an empty string at the end of the return value.
    #
    segments = path.split('/', -1).map! do |segment|
      ignore = []

      # Special character handling.
      #
      pattern = segment.to_str.gsub(/[^\?\%\\/\:\*\w]|:(?!\w)/) do |c|
        ignore << escaped(c).join if c.match(/[\.@]/)
        patt = encoded(c)
        patt.gsub(/%[\da-fA-F]{2}/) do |match|
          match.split(//).map! { |char| char == char.downcase ? char : "[#{char}#{char.downcase}]" }.join
        end
      end

      ignore = ignore.uniq.join

      # Key handling.
      #
      pattern.gsub(/((:\w+)|\*)/) do |match|
        if match == "*"
          keys << 'splat'
          "(.*?)"
        else
          keys << $2[1..-1]
          ignore_pattern = safe_ignore(ignore)

          ignore_pattern
        end
      end
    end

    # Special case handling.
    #
    if last_segment = segments[-1] and last_segment.match(/\[\^\\./)
      parts = last_segment.rpartition(/\[\^\\./)
      parts[1] = '[^'
      segments[-1] = parts.join
    end
    [/\A#{segments.join('/')}\z/, keys]
  elsif path.respond_to?(:keys) && path.respond_to?(:match)
    [path, path.keys]
  elsif path.respond_to?(:names) && path.respond_to?(:match)
    [path, path.names]
  elsif path.respond_to? :match
    [path, []]
  else
    raise TypeError, path
  end
end
compile!(verb, path, block, options = {}) click to toggle source
# File lib/sinatra/base.rb, line 1602
def compile!(verb, path, block, options = {})
  options.each_pair { |option, args| send(option, *args) }
  method_name             = "#{verb} #{path}"
  unbound_method          = generate_method(method_name, &block)
  pattern, keys           = compile path
  conditions, @conditions = @conditions, []

  wrapper                 = block.arity != 0 ?
    proc { |a,p| unbound_method.bind(a).call(*p) } :
    proc { |a,p| unbound_method.bind(a).call }
  wrapper.instance_variable_set(:@route_name, method_name)

  [ pattern, keys, conditions, wrapper ]
end
condition(name = " click to toggle source

Add a route condition. The route is considered non-matching when the block returns false.

# File lib/sinatra/base.rb, line 1350
def condition(name = "#{caller.first[/`.*'/]} condition", &block)
  @conditions << generate_method(name, &block)
end
configure(*envs) { |self| ... } click to toggle source

Set configuration options for Sinatra and/or the app. Allows scoping of settings for certain environments.

# File lib/sinatra/base.rb, line 1410
def configure(*envs)
  yield self if envs.empty? || envs.include?(environment.to_sym)
end
define_singleton(name, content = Proc.new) click to toggle source

Dynamically defines a method on settings.

# File lib/sinatra/base.rb, line 1536
def define_singleton(name, content = Proc.new)
  # replace with call to singleton_class once we're 1.9 only
  (class << self; self; end).class_eval do
    undef_method(name) if method_defined? name
    String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content)
  end
end
delete(path, opts = {}, &bk) click to toggle source
# File lib/sinatra/base.rb, line 1379
def delete(path, opts = {}, &bk)  route 'DELETE',  path, opts, &bk end
detect_rack_handler() click to toggle source
# File lib/sinatra/base.rb, line 1763
def detect_rack_handler
  servers = Array(server)
  servers.each do |server_name|
    begin
      return Rack::Handler.get(server_name.to_s)
    rescue LoadError, NameError
    rescue ArgumentError
      Sinatra::Ext.get_handler(server_name.to_s)
    end
  end
  fail "Server handler (#{servers.join(',')}) not found."
end
development?() click to toggle source
# File lib/sinatra/base.rb, line 1404
def development?; environment == :development end
disable(*opts) click to toggle source

Same as calling `set :option, false` for each of the given options.

# File lib/sinatra/base.rb, line 1247
def disable(*opts)
  opts.each { |key| set(key, false) }
end
enable(*opts) click to toggle source

Same as calling `set :option, true` for each of the given options.

# File lib/sinatra/base.rb, line 1242
def enable(*opts)
  opts.each { |key| set(key, true) }
end
encoded(char) click to toggle source
# File lib/sinatra/base.rb, line 1675
def encoded(char)
  enc = URI_INSTANCE.escape(char)
  enc = "(?:#{escaped(char, enc).join('|')})" if enc == char
  enc = "(?:#{enc}|#{encoded('+')})" if char == " "
  enc
end
error(*codes, &block) click to toggle source

Define a custom error handler. Optionally takes either an Exception class, or an HTTP status code to specify which errors should be handled.

# File lib/sinatra/base.rb, line 1254
def error(*codes, &block)
  args  = compile! "ERROR", //, block
  codes = codes.map { |c| Array(c) }.flatten
  codes << Exception if codes.empty?
  codes.each { |c| (@errors[c] ||= []) << args }
end
escaped(char, enc = URI_INSTANCE.escape(char)) click to toggle source
# File lib/sinatra/base.rb, line 1682
def escaped(char, enc = URI_INSTANCE.escape(char))
  [Regexp.escape(enc), URI_INSTANCE.escape(char, /./)]
end
extensions() click to toggle source

Extension modules registered on this class and all superclasses.

# File lib/sinatra/base.rb, line 1187
def extensions
  if superclass.respond_to?(:extensions)
    (@extensions + superclass.extensions).uniq
  else
    @extensions
  end
end
force_encoding(data, encoding = default_encoding) click to toggle source
# File lib/sinatra/base.rb, line 1812
def self.force_encoding(data, encoding = default_encoding)
  return if data == settings || data.is_a?(Tempfile)
  if data.respond_to? :force_encoding
    data.force_encoding(encoding).encode!
  elsif data.respond_to? :each_value
    data.each_value { |v| force_encoding(v, encoding) }
  elsif data.respond_to? :each
    data.each { |v| force_encoding(v, encoding) }
  end
  data
end
generate_method(method_name, &block) click to toggle source
# File lib/sinatra/base.rb, line 1594
def generate_method(method_name, &block)
  method_name = method_name.to_sym
  define_method(method_name, &block)
  method = instance_method method_name
  remove_method method_name
  method
end
get(path, opts = {}, &block) click to toggle source

Defining a `GET` handler also automatically defines a `HEAD` handler.

# File lib/sinatra/base.rb, line 1369
def get(path, opts = {}, &block)
  conditions = @conditions.dup
  route('GET', path, opts, &block)

  @conditions = conditions
  route('HEAD', path, opts, &block)
end
head(path, opts = {}, &bk) click to toggle source
# File lib/sinatra/base.rb, line 1380
def head(path, opts = {}, &bk)    route 'HEAD',    path, opts, &bk end
helpers(*extensions, &block) click to toggle source

Makes the methods defined in the block and in the Modules given in `extensions` available to the handlers and templates

# File lib/sinatra/base.rb, line 1388
def helpers(*extensions, &block)
  class_eval(&block)   if block_given?
  include(*extensions) if extensions.any?
end
host_name(pattern) click to toggle source

Condition for matching host name. Parameter might be String or Regexp.

# File lib/sinatra/base.rb, line 1545
def host_name(pattern)
  condition { pattern === request.host }
end
inherited(subclass) click to toggle source
Calls superclass method
# File lib/sinatra/base.rb, line 1776
def inherited(subclass)
  subclass.reset!
  subclass.set :app_file, caller_files.first unless subclass.app_file?
  super
end
inline_templates=(file = nil) click to toggle source

Load embedded templates from the file; uses the caller's __FILE__ when no file is specified.

# File lib/sinatra/base.rb, line 1280
def inline_templates=(file = nil)
  file = (file.nil? || file == true) ? (caller_files.first || File.expand_path($0)) : file

  begin
    io = ::IO.respond_to?(:binread) ? ::IO.binread(file) : ::IO.read(file)
    app, data = io.gsub("\r\n", "\n").split(/^__END__$/, 2)
  rescue Errno::ENOENT
    app, data = nil
  end

  if data
    if app and app =~ /([^\n]*\n)?#[^\n]*coding: *(\S+)/
      encoding = $2
    else
      encoding = settings.default_encoding
    end
    lines = app.count("\n") + 1
    template = nil
    force_encoding data, encoding
    data.each_line do |line|
      lines += 1
      if line =~ /^@@\s*(.*\S)\s*$/
        template = force_encoding('', encoding)
        templates[$1.to_sym] = [template, file, lines]
      elsif template
        template << line
      end
    end
  end
end
invoke_hook(name, *args) click to toggle source
# File lib/sinatra/base.rb, line 1590
def invoke_hook(name, *args)
  extensions.each { |e| e.send(name, *args) if e.respond_to?(name) }
end
layout(name = :layout, &block) click to toggle source

Define the layout template. The block must return the template source.

# File lib/sinatra/base.rb, line 1274
def layout(name = :layout, &block)
  template name, &block
end
middleware() click to toggle source

Middleware used in this class and all superclasses.

# File lib/sinatra/base.rb, line 1196
def middleware
  if superclass.respond_to?(:middleware)
    superclass.middleware + @middleware
  else
    @middleware
  end
end
mime_type(type, value = nil) click to toggle source

Lookup or register a mime type in Rack's mime registry.

# File lib/sinatra/base.rb, line 1312
def mime_type(type, value = nil)
  return type      if type.nil?
  return type.to_s if 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
mime_types(type) click to toggle source

provides all mime types matching type, including deprecated types:

mime_types :html # => ['text/html']
mime_types :js   # => ['application/javascript', 'text/javascript']
# File lib/sinatra/base.rb, line 1323
def mime_types(type)
  type = mime_type type
  type =~ /^application\/(xml|javascript)$/ ? [type, "text/#$1"] : [type]
end
new(*args, &bk) click to toggle source

Create a new instance of the class fronted by its middleware pipeline. The object is guaranteed to respond to call but may not be an instance of the class new was called on.

# File lib/sinatra/base.rb, line 1471
def new(*args, &bk)
  instance = new!(*args, &bk)
  Wrapper.new(build(instance).to_app, instance)
end
new!(app = nil)

Create a new instance without middleware in front of it.

Alias for: new
not_found(&block) click to toggle source

Sugar for `error(404) { … }`

# File lib/sinatra/base.rb, line 1262
def not_found(&block)
  error(404, &block)
  error(Sinatra::NotFound, &block)
end
options(path, opts = {}, &bk) click to toggle source
# File lib/sinatra/base.rb, line 1381
def options(path, opts = {}, &bk) route 'OPTIONS', path, opts, &bk end
patch(path, opts = {}, &bk) click to toggle source
# File lib/sinatra/base.rb, line 1382
def patch(path, opts = {}, &bk)   route 'PATCH',   path, opts, &bk end
post(path, opts = {}, &bk) click to toggle source
# File lib/sinatra/base.rb, line 1378
def post(path, opts = {}, &bk)    route 'POST',    path, opts, &bk end
production?() click to toggle source
# File lib/sinatra/base.rb, line 1405
def production?;  environment == :production  end
prototype() click to toggle source

The prototype instance used to process requests.

# File lib/sinatra/base.rb, line 1461
def prototype
  @prototype ||= new
end
provides(*types) click to toggle source

Condition for matching mimetypes. Accepts file extensions.

# File lib/sinatra/base.rb, line 1564
def provides(*types)
  types.map! { |t| mime_types(t) }
  types.flatten!
  condition do
    if type = response['Content-Type']
      types.include? type or types.include? type[/^[^;]+/]
    elsif type = request.preferred_type(types)
      params = (type.respond_to?(:params) ? type.params : {})
      content_type(type, params)
      true
    else
      false
    end
  end
end
public=(value) click to toggle source
# File lib/sinatra/base.rb, line 1354
def public=(value)
  warn ":public is no longer used to avoid overloading Module#public, use :public_folder or :public_dir instead"
  set(:public_folder, value)
end
public_dir() click to toggle source
# File lib/sinatra/base.rb, line 1363
def public_dir
  public_folder
end
public_dir=(value) click to toggle source
# File lib/sinatra/base.rb, line 1359
def public_dir=(value)
  self.public_folder = value
end
put(path, opts = {}, &bk) click to toggle source
# File lib/sinatra/base.rb, line 1377
def put(path, opts = {}, &bk)     route 'PUT',     path, opts, &bk end
quit!() click to toggle source

Stop the self-hosted server if running.

# File lib/sinatra/base.rb, line 1421
def quit!
  return unless running?
  # Use Thin's hard #stop! if available, otherwise just #stop.
  running_server.respond_to?(:stop!) ? running_server.stop! : running_server.stop
  $stderr.puts "== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/
  set :running_server, nil
  set :handler_name, nil
end
Also aliased as: stop!
register(*extensions, &block) click to toggle source

Register an extension. Alternatively take a block from which an extension will be created and registered on the fly.

# File lib/sinatra/base.rb, line 1395
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
reset!() click to toggle source

Removes all routes, filters, middleware and extension hooks from the current class (not routes/filters/… defined by its superclass).

# File lib/sinatra/base.rb, line 1170
def reset!
  @conditions     = []
  @routes         = {}
  @filters        = {:before => [], :after => []}
  @errors         = {}
  @middleware     = []
  @prototype      = nil
  @extensions     = []

  if superclass.respond_to?(:templates)
    @templates = Hash.new { |hash,key| superclass.templates[key] }
  else
    @templates = {}
  end
end
route(verb, path, options = {}, &block) click to toggle source
# File lib/sinatra/base.rb, line 1580
def route(verb, path, options = {}, &block)
  # Because of self.options.host
  host_name(options.delete(:host)) if options.key?(:host)
  enable :empty_path_info if path == "" and empty_path_info.nil?
  signature = compile!(verb, path, block, options)
  (@routes[verb] ||= []) << signature
  invoke_hook(:route_added, verb, path, block)
  signature
end
run!(options = {}, &block) click to toggle source

Run the Sinatra app as a self-hosted server using Thin, Puma, Mongrel, or WEBrick (in that order). If given a block, will call with the constructed handler once we have taken the stage.

# File lib/sinatra/base.rb, line 1435
def run!(options = {}, &block)
  return if running?
  set options
  handler         = detect_rack_handler
  handler_name    = handler.name.gsub(/.*::/, '')
  server_settings = settings.respond_to?(:server_settings) ? settings.server_settings : {}
  server_settings.merge!(:Port => port, :Host => bind)

  begin
    start_server(handler, server_settings, handler_name, &block)
  rescue Errno::EADDRINUSE
    $stderr.puts "== Someone is already performing on port #{port}!"
    raise
  ensure
    quit!
  end
end
Also aliased as: start!
running?() click to toggle source

Check whether the self-hosted server is running or not.

# File lib/sinatra/base.rb, line 1456
def running?
  running_server?
end
safe_ignore(ignore) click to toggle source
# File lib/sinatra/base.rb, line 1686
def safe_ignore(ignore)
  unsafe_ignore = []
  ignore = ignore.gsub(/%[\da-fA-F]{2}/) do |hex|
    unsafe_ignore << hex[1..2]
    ''
  end
  unsafe_patterns = unsafe_ignore.map! do |unsafe|
    chars = unsafe.split(//).map! do |char|
      char == char.downcase ? char : char + char.downcase
    end

    "|(?:%[^#{chars[0]}].|%[#{chars[0]}][^#{chars[1]}])"
  end
  if unsafe_patterns.length > 0
    "((?:[^#{ignore}/?#%]#{unsafe_patterns.join()})+)"
  else
    "([^#{ignore}/?#]+)"
  end
end
set(option, value = (not_set = true), ignore_setter = false, &block) click to toggle source

Sets an option to the given value. If the value is a proc, the proc will be called every time the option is accessed.

# File lib/sinatra/base.rb, line 1206
def set(option, value = (not_set = true), ignore_setter = false, &block)
  raise ArgumentError if block and !not_set
  value, not_set = block, false if block

  if not_set
    raise ArgumentError unless option.respond_to?(:each)
    option.each { |k,v| set(k, v) }
    return self
  end

  if respond_to?("#{option}=") and not ignore_setter
    return __send__("#{option}=", value)
  end

  setter = proc { |val| set option, val, true }
  getter = proc { value }

  case value
  when Proc
    getter = value
  when Symbol, Fixnum, FalseClass, TrueClass, NilClass
    getter = value.inspect
  when Hash
    setter = proc do |val|
      val = value.merge val if Hash === val
      set option, val, true
    end
  end

  define_singleton("#{option}=", setter) if setter
  define_singleton(option, getter) if getter
  define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
  self
end
setup_common_logger(builder) click to toggle source
# File lib/sinatra/base.rb, line 1733
def setup_common_logger(builder)
  builder.use Sinatra::CommonLogger
end
setup_custom_logger(builder) click to toggle source
# File lib/sinatra/base.rb, line 1737
def setup_custom_logger(builder)
  if logging.respond_to? :to_int
    builder.use Rack::Logger, logging
  else
    builder.use Rack::Logger
  end
end
setup_default_middleware(builder) click to toggle source
# File lib/sinatra/base.rb, line 1706
def setup_default_middleware(builder)
  builder.use ExtendedRack
  builder.use ShowExceptions       if show_exceptions?
  builder.use Rack::MethodOverride if method_override?
  builder.use Rack::Head
  setup_logging    builder
  setup_sessions   builder
  setup_protection builder
end
setup_logging(builder) click to toggle source
# File lib/sinatra/base.rb, line 1720
def setup_logging(builder)
  if logging?
    setup_common_logger(builder)
    setup_custom_logger(builder)
  elsif logging == false
    setup_null_logger(builder)
  end
end
setup_middleware(builder) click to toggle source
# File lib/sinatra/base.rb, line 1716
def setup_middleware(builder)
  middleware.each { |c,a,b| builder.use(c, *a, &b) }
end
setup_null_logger(builder) click to toggle source
# File lib/sinatra/base.rb, line 1729
def setup_null_logger(builder)
  builder.use Rack::NullLogger
end
setup_protection(builder) click to toggle source
# File lib/sinatra/base.rb, line 1745
def setup_protection(builder)
  return unless protection?
  options = Hash === protection ? protection.dup : {}
  protect_session  = options.fetch(:session) { sessions? }
  options[:except] = Array options[:except]
  options[:except] += [:session_hijacking, :remote_token] unless protect_session
  options[:reaction] ||= :drop_session
  builder.use Rack::Protection, options
end
setup_sessions(builder) click to toggle source
# File lib/sinatra/base.rb, line 1755
def setup_sessions(builder)
  return unless sessions?
  options = {}
  options[:secret] = session_secret if session_secret?
  options.merge! sessions.to_hash if sessions.respond_to? :to_hash
  builder.use Rack::Session::Cookie, options
end
setup_traps() click to toggle source
# File lib/sinatra/base.rb, line 1520
def setup_traps
  if traps?
    at_exit { quit! }

    [:INT, :TERM].each do |signal|
      old_handler = trap(signal) do
        quit!
        old_handler.call if old_handler.respond_to?(:call)
      end
    end

    set :traps, false
  end
end
start!(options = {}, &block)
Alias for: run!
start_server(handler, server_settings, handler_name) { |server| ... } click to toggle source

Starts the server by running the Rack Handler.

# File lib/sinatra/base.rb, line 1505
def start_server(handler, server_settings, handler_name)
  handler.run(self, server_settings) do |server|
    unless handler_name =~ /cgi/
      $stderr.puts "== Sinatra (v#{Sinatra::VERSION}) has taken the stage on #{port} for #{environment} with backup from #{handler_name}"
    end

    setup_traps
    set :running_server, server
    set :handler_name,   handler_name
    server.threaded = settings.threaded if server.respond_to? :threaded=

    yield server if block_given?
  end
end
stop!()
Alias for: quit!
synchronize() { || ... } click to toggle source
# File lib/sinatra/base.rb, line 1783
def synchronize(&block)
  if lock?
    @@mutex.synchronize(&block)
  else
    yield
  end
end
template(name, &block) click to toggle source

Define a named template. The block must return the template source.

# File lib/sinatra/base.rb, line 1268
def template(name, &block)
  filename, line = caller_locations.first
  templates[name] = [block, filename, line.to_i]
end
test?() click to toggle source
# File lib/sinatra/base.rb, line 1406
def test?;        environment == :test        end
use(middleware, *args, &block) click to toggle source

Use the specified Rack middleware

# File lib/sinatra/base.rb, line 1415
def use(middleware, *args, &block)
  @prototype = nil
  @middleware << [middleware, args, block]
end
user_agent(pattern) click to toggle source

Condition for matching user agent. Parameter should be Regexp. Will set params.

# File lib/sinatra/base.rb, line 1551
def user_agent(pattern)
  condition do
    if request.user_agent.to_s =~ pattern
      @params[:agent] = $~[1..-1]
      true
    else
      false
    end
  end
end
Also aliased as: agent
warn(message) click to toggle source

used for deprecation warnings

Calls superclass method
# File lib/sinatra/base.rb, line 1792
def warn(message)
  super message + "\n\tfrom #{cleaned_caller.first.join(':')}"
end

Public Instance Methods

call(env) click to toggle source

Rack call interface.

# File lib/sinatra/base.rb, line 894
def call(env)
  dup.call!(env)
end
forward() click to toggle source

Forward the request to the downstream app – middleware only.

# File lib/sinatra/base.rb, line 952
def forward
  fail "downstream app not set" unless @app.respond_to? :call
  status, headers, body = @app.call env
  @response.status = status
  @response.body = body
  @response.headers.merge! headers
  nil
end
halt(*response) click to toggle source

Exit the current block, halts any further processing of the request, and returns the specified response.

# File lib/sinatra/base.rb, line 939
def halt(*response)
  response = response.first if response.length == 1
  throw :halt, response
end
options() click to toggle source
# File lib/sinatra/base.rb, line 931
def options
  warn "Sinatra::Base#options is deprecated and will be removed, "          "use #settings instead."
  settings
end
pass(&block) click to toggle source

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

# File lib/sinatra/base.rb, line 947
def pass(&block)
  throw :pass, block
end
settings() click to toggle source

Access settings defined with ::set.

# File lib/sinatra/base.rb, line 927
def settings
  self.class.settings
end

Private Instance Methods

dispatch!() click to toggle source

Dispatch a request with error handling.

# File lib/sinatra/base.rb, line 1081
def dispatch!
  invoke do
    static! if settings.static? && (request.get? || request.head?)
    filter! :before
    route!
  end
rescue ::Exception => boom
  invoke { handle_exception!(boom) }
ensure
  begin
    filter! :after unless env['sinatra.static_file']
  rescue ::Exception => boom
    invoke { handle_exception!(boom) } unless @env['sinatra.error']
  end
end
dump_errors!(boom) click to toggle source
# File lib/sinatra/base.rb, line 1143
def dump_errors!(boom)
  msg = ["#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} - #{boom.class} - #{boom.message}:", *boom.backtrace].join("\n\t")
  @env['rack.errors'].puts(msg)
end
error_block!(key, *block_params) click to toggle source

Find an custom error block for the key(s) specified.

# File lib/sinatra/base.rb, line 1128
def error_block!(key, *block_params)
  base = settings
  while base.respond_to?(:errors)
    next base = base.superclass unless args_array = base.errors[key]
    args_array.reverse_each do |args|
      first = args == args_array.first
      args += [block_params]
      resp = process_route(*args)
      return resp unless resp.nil? && !first
    end
  end
  return false unless key.respond_to? :superclass and key.superclass < Exception
  error_block!(key.superclass, *block_params)
end
filter!(type, base = settings) click to toggle source

Run filters defined on the class and all superclasses.

# File lib/sinatra/base.rb, line 964
def filter!(type, base = settings)
  filter! type, base.superclass if base.superclass.respond_to?(:filters)
  base.filters[type].each { |args| process_route(*args) }
end
force_encoding(*args) click to toggle source

Fixes encoding issues by

  • defaulting to UTF-8

  • casting params to Encoding.default_external

The latter might not be necessary if Rack handles it one day. Keep an eye on Rack's LH #100.

# File lib/sinatra/base.rb, line 1810
def force_encoding(*args) settings.force_encoding(*args) end
handle_exception!(boom) click to toggle source

Error handling during requests.

# File lib/sinatra/base.rb, line 1098
def handle_exception!(boom)
  @env['sinatra.error'] = boom

  if boom.respond_to? :http_status
    status(boom.http_status)
  elsif settings.use_code? and boom.respond_to? :code and boom.code.between? 400, 599
    status(boom.code)
  else
    status(500)
  end

  status(500) unless status.between? 400, 599

  if server_error?
    dump_errors! boom if settings.dump_errors?
    raise boom if settings.show_exceptions? and settings.show_exceptions != :after_handler
  end

  if not_found?
    headers['X-Cascade'] = 'pass' if settings.x_cascade?
    body '<h1>Not Found</h1>'
  end

  res = error_block!(boom.class, boom) || error_block!(status, boom)
  return res if res or not server_error?
  raise boom if settings.raise_errors? or settings.show_exceptions?
  error_block! Exception, boom
end
indifferent_hash() click to toggle source

Creates a Hash with indifferent access.

# File lib/sinatra/base.rb, line 1061
def indifferent_hash
  Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
end
indifferent_params(object) click to toggle source

Enable string or symbol key access to the nested params hash.

# File lib/sinatra/base.rb, line 1047
def indifferent_params(object)
  case object
  when Hash
    new_hash = indifferent_hash
    object.each { |key, value| new_hash[key] = indifferent_params(value) }
    new_hash
  when Array
    object.map { |item| indifferent_params(item) }
  else
    object
  end
end
invoke() { || ... } click to toggle source

Run the block with 'throw :halt' support and apply result to the response.

# File lib/sinatra/base.rb, line 1066
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
process_route(pattern, keys, conditions, block = nil, values = []) { |self, values| ... } click to toggle source

If the current request matches pattern and conditions, fill params with keys and call the given block. Revert params afterwards.

Returns pass block.

# File lib/sinatra/base.rb, line 1002
def process_route(pattern, keys, conditions, block = nil, values = [])
  route = @request.path_info
  route = '/' if route.empty? and not settings.empty_path_info?
  return unless match = pattern.match(route)
  values += match.captures.map! { |v| force_encoding URI_INSTANCE.unescape(v) if v }

  if values.any?
    original, @params = params, params.merge('splat' => [], 'captures' => values)
    keys.zip(values) { |k,v| Array === @params[k] ? @params[k] << v : @params[k] = v if v }
  end

  catch(:pass) do
    conditions.each { |c| throw :pass if c.bind(self).call == false }
    block ? block[self, values] : yield(self, values)
  end
ensure
  @params = original if original
end
route!(base = settings, pass_block = nil) click to toggle source

Run routes defined on the class and all superclasses.

# File lib/sinatra/base.rb, line 970
def route!(base = settings, pass_block = nil)
  if routes = base.routes[@request.request_method]
    routes.each do |pattern, keys, conditions, block|
      returned_pass_block = process_route(pattern, keys, conditions) do |*args|
        env['sinatra.route'] = block.instance_variable_get(:@route_name)
        route_eval { block[*args] }
      end

      # don't wipe out pass_block in superclass
      pass_block = returned_pass_block if returned_pass_block
    end
  end

  # Run routes defined in superclass.
  if base.superclass.respond_to?(:routes)
    return route!(base.superclass, pass_block)
  end

  route_eval(&pass_block) if pass_block
  route_missing
end
route_eval() { || ... } click to toggle source

Run a route block and throw :halt with the result.

# File lib/sinatra/base.rb, line 993
def route_eval
  throw :halt, yield
end
route_missing() click to toggle source

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

# File lib/sinatra/base.rb, line 1026
def route_missing
  if @app
    forward
  else
    raise NotFound
  end
end
static!(options = {}) click to toggle source

Attempt to serve static files from public directory. Throws :halt when a matching file is found, returns nil otherwise.

# File lib/sinatra/base.rb, line 1036
def static!(options = {})
  return if (public_dir = settings.public_folder).nil?
  path = File.expand_path("#{public_dir}#{URI_INSTANCE.unescape(request.path_info)}" )
  return unless File.file?(path)

  env['sinatra.static_file'] = path
  cache_control(*settings.static_cache_control) if settings.static_cache_control?
  send_file path, options.merge(:disposition => nil)
end