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, **_kwargs) { |self| ... } click to toggle source
    # File lib/sinatra/base.rb
918 def initialize(app = nil, **_kwargs)
919   super()
920   @app = app
921   @template_cache = Tilt::Cache.new
922   @pinned_response = nil # whether a before! filter pinned the content-type
923   yield self if block_given?
924 end
Also aliased as: new!
settings() click to toggle source

Access settings defined with Base.set.

    # File lib/sinatra/base.rb
954 def self.settings
955   self
956 end

Private Class Methods

add_filter(type, path = /.*/, **options, &block) click to toggle source

add a filter

     # File lib/sinatra/base.rb
1407 def add_filter(type, path = /.*/, **options, &block)
1408   filters[type] << compile!(type, path, block, **options)
1409 end
after(path = /.*/, **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
1402 def after(path = /.*/, **options, &block)
1403   add_filter(:after, path, **options, &block)
1404 end
agent(pattern)
Alias for: user_agent
before(path = /.*/, **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
1395 def before(path = /.*/, **options, &block)
1396   add_filter(:before, path, **options, &block)
1397 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
1552 def build(app)
1553   builder = Rack::Builder.new
1554   setup_default_middleware builder
1555   setup_middleware builder
1556   builder.run app
1557   builder
1558 end
call(env) click to toggle source
     # File lib/sinatra/base.rb
1560 def call(env)
1561   synchronize { prototype.call(env) }
1562 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
1566 def caller_files
1567   cleaned_caller(1).flatten
1568 end
cleaned_caller(keep = 3) click to toggle source

Like Kernel#caller but excluding certain magic entries

     # File lib/sinatra/base.rb
1787 def cleaned_caller(keep = 3)
1788   caller(1)
1789     .map! { |line| line.split(/:(?=\d|in )/, 3)[0, keep] }
1790     .reject { |file, *_| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
1791 end
compile(path, route_mustermann_opts = {}) click to toggle source
     # File lib/sinatra/base.rb
1697 def compile(path, route_mustermann_opts = {})
1698   Mustermann.new(path, **mustermann_opts.merge(route_mustermann_opts))
1699 end
compile!(verb, path, block, **options) click to toggle source
     # File lib/sinatra/base.rb
1677 def compile!(verb, path, block, **options)
1678   # Because of self.options.host
1679   host_name(options.delete(:host)) if options.key?(:host)
1680   # Pass Mustermann opts to compile()
1681   route_mustermann_opts = options.key?(:mustermann_opts) ? options.delete(:mustermann_opts) : {}.freeze
1682 
1683   options.each_pair { |option, args| send(option, *args) }
1684 
1685   pattern                 = compile(path, route_mustermann_opts)
1686   method_name             = "#{verb} #{path}"
1687   unbound_method          = generate_method(method_name, &block)
1688   conditions = @conditions
1689   @conditions = []
1690   wrapper = block.arity.zero? ?
1691     proc { |a, _p| unbound_method.bind(a).call } :
1692     proc { |a, p| unbound_method.bind(a).call(*p) }
1693 
1694   [pattern, conditions, wrapper]
1695 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
1413 def condition(name = "#{caller.first[/`.*'/]} condition", &block)
1414   @conditions << generate_method(name, &block)
1415 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
1480 def configure(*envs)
1481   yield self if envs.empty? || envs.include?(environment.to_sym)
1482 end
define_singleton(name, content = Proc.new) click to toggle source

Dynamically defines a method on settings.

     # File lib/sinatra/base.rb
1612 def define_singleton(name, content = Proc.new)
1613   singleton_class.class_eval do
1614     undef_method(name) if method_defined? name
1615     String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content)
1616   end
1617 end
delete(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1444 def delete(path, opts = {}, &block)  route 'DELETE',  path, opts, &block end
development?() click to toggle source
     # File lib/sinatra/base.rb
1474 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
1308 def disable(*opts)
1309   opts.each { |key| set(key, false) }
1310 end
enable(*opts) click to toggle source

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

     # File lib/sinatra/base.rb
1303 def enable(*opts)
1304   opts.each { |key| set(key, true) }
1305 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
1315 def error(*codes, &block)
1316   args  = compile! 'ERROR', /.*/, block
1317   codes = codes.flat_map(&method(:Array))
1318   codes << Exception if codes.empty?
1319   codes << Sinatra::NotFound if codes.include?(404)
1320   codes.each { |c| (@errors[c] ||= []) << args }
1321 end
extensions() click to toggle source

Extension modules registered on this class and all superclasses.

     # File lib/sinatra/base.rb
1243 def extensions
1244   if superclass.respond_to?(:extensions)
1245     (@extensions + superclass.extensions).uniq
1246   else
1247     @extensions
1248   end
1249 end
force_encoding(data, encoding = default_encoding) click to toggle source

Force data to specified encoding. It defaults to settings.default_encoding which is UTF-8 by default

     # File lib/sinatra/base.rb
1796 def self.force_encoding(data, encoding = default_encoding)
1797   return if data == settings || data.is_a?(Tempfile)
1798 
1799   if data.respond_to? :force_encoding
1800     data.force_encoding(encoding).encode!
1801   elsif data.respond_to? :each_value
1802     data.each_value { |v| force_encoding(v, encoding) }
1803   elsif data.respond_to? :each
1804     data.each { |v| force_encoding(v, encoding) }
1805   end
1806   data
1807 end
generate_method(method_name, &block) click to toggle source
     # File lib/sinatra/base.rb
1670 def generate_method(method_name, &block)
1671   define_method(method_name, &block)
1672   method = instance_method method_name
1673   remove_method method_name
1674   method
1675 end
get(path, opts = {}, &block) click to toggle source

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

     # File lib/sinatra/base.rb
1432 def get(path, opts = {}, &block)
1433   conditions = @conditions.dup
1434   route('GET', path, opts, &block)
1435 
1436   @conditions = conditions
1437   route('HEAD', path, opts, &block)
1438 end
head(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1446 def head(path, opts = {}, &block)    route 'HEAD',    path, opts, &block 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
1458 def helpers(*extensions, &block)
1459   class_eval(&block)   if block_given?
1460   include(*extensions) if extensions.any?
1461 end
host_name(pattern) click to toggle source

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

     # File lib/sinatra/base.rb
1620 def host_name(pattern)
1621   condition { pattern === request.host }
1622 end
inherited(subclass) click to toggle source
Calls superclass method
     # File lib/sinatra/base.rb
1766 def inherited(subclass)
1767   subclass.reset!
1768   subclass.set :app_file, caller_files.first unless subclass.app_file?
1769   super
1770 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
1341 def inline_templates=(file = nil)
1342   file = (caller_files.first || File.expand_path($0)) if file.nil? || file == true
1343 
1344   begin
1345     io = ::IO.respond_to?(:binread) ? ::IO.binread(file) : ::IO.read(file)
1346     app, data = io.gsub("\r\n", "\n").split(/^__END__$/, 2)
1347   rescue Errno::ENOENT
1348     app, data = nil
1349   end
1350 
1351   return unless data
1352 
1353   encoding = if app && app =~ /([^\n]*\n)?#[^\n]*coding: *(\S+)/m
1354                $2
1355              else
1356                settings.default_encoding
1357              end
1358 
1359   lines = app.count("\n") + 1
1360   template = nil
1361   force_encoding data, encoding
1362   data.each_line do |line|
1363     lines += 1
1364     if line =~ /^@@\s*(.*\S)\s*$/
1365       template = force_encoding(String.new, encoding)
1366       templates[$1.to_sym] = [template, file, lines]
1367     elsif template
1368       template << line
1369     end
1370   end
1371 end
invoke_hook(name, *args) click to toggle source
     # File lib/sinatra/base.rb
1666 def invoke_hook(name, *args)
1667   extensions.each { |e| e.send(name, *args) if e.respond_to?(name) }
1668 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
1335 def layout(name = :layout, &block)
1336   template name, &block
1337 end
middleware() click to toggle source

Middleware used in this class and all superclasses.

     # File lib/sinatra/base.rb
1252 def middleware
1253   if superclass.respond_to?(:middleware)
1254     superclass.middleware + @middleware
1255   else
1256     @middleware
1257   end
1258 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
1374 def mime_type(type, value = nil)
1375   return type      if type.nil?
1376   return type.to_s if type.to_s.include?('/')
1377 
1378   type = ".#{type}" unless type.to_s[0] == '.'
1379   return Rack::Mime.mime_type(type, nil) unless value
1380 
1381   Rack::Mime::MIME_TYPES[type] = value
1382 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
1387 def mime_types(type)
1388   type = mime_type type
1389   type =~ %r{^application/(xml|javascript)$} ? [type, "text/#{$1}"] : [type]
1390 end
new(*args, &block) 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
1544 def new(*args, &block)
1545   instance = new!(*args, &block)
1546   Wrapper.new(build(instance).to_app, instance)
1547 end
new!(app = nil, **_kwargs)

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
1324 def not_found(&block)
1325   error(404, &block)
1326 end
options(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1448 def options(path, opts = {}, &block) route 'OPTIONS', path, opts, &block end
patch(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1450 def patch(path, opts = {}, &block)   route 'PATCH',   path, opts, &block end
post(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1442 def post(path, opts = {}, &block)    route 'POST',    path, opts, &block end
production?() click to toggle source
     # File lib/sinatra/base.rb
1475 def production?;  environment == :production  end
prototype() click to toggle source

The prototype instance used to process requests.

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

Condition for matching mimetypes. Accepts file extensions.

     # File lib/sinatra/base.rb
1639 def provides(*types)
1640   types.map! { |t| mime_types(t) }
1641   types.flatten!
1642   condition do
1643     response_content_type = response['Content-Type']
1644     preferred_type = request.preferred_type(types)
1645 
1646     if response_content_type
1647       types.include?(response_content_type) || types.include?(response_content_type[/^[^;]+/])
1648     elsif preferred_type
1649       params = (preferred_type.respond_to?(:params) ? preferred_type.params : {})
1650       content_type(preferred_type, params)
1651       true
1652     else
1653       false
1654     end
1655   end
1656 end
public=(value) click to toggle source
     # File lib/sinatra/base.rb
1417 def public=(value)
1418   warn_for_deprecation ':public is no longer used to avoid overloading Module#public, use :public_folder or :public_dir instead'
1419   set(:public_folder, value)
1420 end
public_dir() click to toggle source
     # File lib/sinatra/base.rb
1426 def public_dir
1427   public_folder
1428 end
public_dir=(value) click to toggle source
     # File lib/sinatra/base.rb
1422 def public_dir=(value)
1423   self.public_folder = value
1424 end
put(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1440 def put(path, opts = {}, &block)     route 'PUT',     path, opts, &block end
quit!() click to toggle source

Stop the self-hosted server if running.

     # File lib/sinatra/base.rb
1492 def quit!
1493   return unless running?
1494 
1495   # Use Thin's hard #stop! if available, otherwise just #stop.
1496   running_server.respond_to?(:stop!) ? running_server.stop! : running_server.stop
1497   warn '== Sinatra has ended his set (crowd applauds)' unless suppress_messages?
1498   set :running_server, nil
1499   set :handler_name, nil
1500 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
1465 def register(*extensions, &block)
1466   extensions << Module.new(&block) if block_given?
1467   @extensions += extensions
1468   extensions.each do |extension|
1469     extend extension
1470     extension.registered(self) if extension.respond_to?(:registered)
1471   end
1472 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
1226 def reset!
1227   @conditions     = []
1228   @routes         = {}
1229   @filters        = { before: [], after: [] }
1230   @errors         = {}
1231   @middleware     = []
1232   @prototype      = nil
1233   @extensions     = []
1234 
1235   @templates = if superclass.respond_to?(:templates)
1236                  Hash.new { |_hash, key| superclass.templates[key] }
1237                else
1238                  {}
1239                end
1240 end
route(verb, path, options = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1658 def route(verb, path, options = {}, &block)
1659   enable :empty_path_info if path == '' && empty_path_info.nil?
1660   signature = compile!(verb, path, block, **options)
1661   (@routes[verb] ||= []) << signature
1662   invoke_hook(:route_added, verb, path, block)
1663   signature
1664 end
run!(options = {}, &block) click to toggle source

Run the Sinatra app as a self-hosted server using Puma, Falcon, 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
1507 def run!(options = {}, &block)
1508   return if running?
1509 
1510   set options
1511   handler         = Rack::Handler.pick(server)
1512   handler_name    = handler.name.gsub(/.*::/, '')
1513   server_settings = settings.respond_to?(:server_settings) ? settings.server_settings : {}
1514   server_settings.merge!(Port: port, Host: bind)
1515 
1516   begin
1517     start_server(handler, server_settings, handler_name, &block)
1518   rescue Errno::EADDRINUSE
1519     warn "== Someone is already performing on port #{port}!"
1520     raise
1521   ensure
1522     quit!
1523   end
1524 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
1529 def running?
1530   running_server?
1531 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
1262 def set(option, value = (not_set = true), ignore_setter = false, &block)
1263   raise ArgumentError if block && !not_set
1264 
1265   if block
1266     value = block
1267     not_set = false
1268   end
1269 
1270   if not_set
1271     raise ArgumentError unless option.respond_to?(:each)
1272 
1273     option.each { |k, v| set(k, v) }
1274     return self
1275   end
1276 
1277   if respond_to?("#{option}=") && !ignore_setter
1278     return __send__("#{option}=", value)
1279   end
1280 
1281   setter = proc { |val| set option, val, true }
1282   getter = proc { value }
1283 
1284   case value
1285   when Proc
1286     getter = value
1287   when Symbol, Integer, FalseClass, TrueClass, NilClass
1288     getter = value.inspect
1289   when Hash
1290     setter = proc do |val|
1291       val = value.merge val if Hash === val
1292       set option, val, true
1293     end
1294   end
1295 
1296   define_singleton("#{option}=", setter)
1297   define_singleton(option, getter)
1298   define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
1299   self
1300 end
setup_common_logger(builder) click to toggle source
     # File lib/sinatra/base.rb
1728 def setup_common_logger(builder)
1729   builder.use Sinatra::CommonLogger
1730 end
setup_custom_logger(builder) click to toggle source
     # File lib/sinatra/base.rb
1732 def setup_custom_logger(builder)
1733   if logging.respond_to? :to_int
1734     builder.use Rack::Logger, logging
1735   else
1736     builder.use Rack::Logger
1737   end
1738 end
setup_default_middleware(builder) click to toggle source
     # File lib/sinatra/base.rb
1701 def setup_default_middleware(builder)
1702   builder.use ExtendedRack
1703   builder.use ShowExceptions       if show_exceptions?
1704   builder.use Rack::MethodOverride if method_override?
1705   builder.use Rack::Head
1706   setup_logging    builder
1707   setup_sessions   builder
1708   setup_protection builder
1709 end
setup_logging(builder) click to toggle source
     # File lib/sinatra/base.rb
1715 def setup_logging(builder)
1716   if logging?
1717     setup_common_logger(builder)
1718     setup_custom_logger(builder)
1719   elsif logging == false
1720     setup_null_logger(builder)
1721   end
1722 end
setup_middleware(builder) click to toggle source
     # File lib/sinatra/base.rb
1711 def setup_middleware(builder)
1712   middleware.each { |c, a, b| builder.use(c, *a, &b) }
1713 end
setup_null_logger(builder) click to toggle source
     # File lib/sinatra/base.rb
1724 def setup_null_logger(builder)
1725   builder.use Rack::NullLogger
1726 end
setup_protection(builder) click to toggle source
     # File lib/sinatra/base.rb
1740 def setup_protection(builder)
1741   return unless protection?
1742 
1743   options = Hash === protection ? protection.dup : {}
1744   options = {
1745     img_src: "'self' data:",
1746     font_src: "'self'"
1747   }.merge options
1748 
1749   protect_session = options.fetch(:session) { sessions? }
1750   options[:without_session] = !protect_session
1751 
1752   options[:reaction] ||= :drop_session
1753 
1754   builder.use Rack::Protection, options
1755 end
setup_sessions(builder) click to toggle source
     # File lib/sinatra/base.rb
1757 def setup_sessions(builder)
1758   return unless sessions?
1759 
1760   options = {}
1761   options[:secret] = session_secret if session_secret?
1762   options.merge! sessions.to_hash if sessions.respond_to? :to_hash
1763   builder.use session_store, options
1764 end
setup_traps() click to toggle source
     # File lib/sinatra/base.rb
1596 def setup_traps
1597   return unless traps?
1598 
1599   at_exit { quit! }
1600 
1601   %i[INT TERM].each do |signal|
1602     old_handler = trap(signal) do
1603       quit!
1604       old_handler.call if old_handler.respond_to?(:call)
1605     end
1606   end
1607 
1608   set :traps, false
1609 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
1573 def start_server(handler, server_settings, handler_name)
1574   # Ensure we initialize middleware before startup, to match standard Rack
1575   # behavior, by ensuring an instance exists:
1576   prototype
1577   # Run the instance we created:
1578   handler.run(self, **server_settings) do |server|
1579     unless suppress_messages?
1580       warn "== Sinatra (v#{Sinatra::VERSION}) has taken the stage on #{port} for #{environment} with backup from #{handler_name}"
1581     end
1582 
1583     setup_traps
1584     set :running_server, server
1585     set :handler_name,   handler_name
1586     server.threaded = settings.threaded if server.respond_to? :threaded=
1587 
1588     yield server if block_given?
1589   end
1590 end
stop!()
Alias for: quit!
suppress_messages?() click to toggle source
     # File lib/sinatra/base.rb
1592 def suppress_messages?
1593   handler_name =~ /cgi/i || quiet
1594 end
synchronize() { || ... } click to toggle source
     # File lib/sinatra/base.rb
1773 def synchronize(&block)
1774   if lock?
1775     @@mutex.synchronize(&block)
1776   else
1777     yield
1778   end
1779 end
template(name, &block) click to toggle source

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

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

Use the specified Rack middleware

     # File lib/sinatra/base.rb
1485 def use(middleware, *args, &block)
1486   @prototype = nil
1487   @middleware << [middleware, args, block]
1488 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
1626 def user_agent(pattern)
1627   condition do
1628     if request.user_agent.to_s =~ pattern
1629       @params[:agent] = $~[1..-1]
1630       true
1631     else
1632       false
1633     end
1634   end
1635 end
Also aliased as: agent
warn_for_deprecation(message) click to toggle source

used for deprecation warnings

     # File lib/sinatra/base.rb
1782 def warn_for_deprecation(message)
1783   warn message + "\n\tfrom #{cleaned_caller.first.join(':')}"
1784 end

Public Instance Methods

call(env) click to toggle source

Rack call interface.

    # File lib/sinatra/base.rb
927 def call(env)
928   dup.call!(env)
929 end
forward() click to toggle source

Forward the request to the downstream app – middleware only.

    # File lib/sinatra/base.rb
978 def forward
979   raise 'downstream app not set' unless @app.respond_to? :call
980 
981   status, headers, body = @app.call env
982   @response.status = status
983   @response.body = body
984   @response.headers.merge! headers
985   nil
986 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
965 def halt(*response)
966   response = response.first if response.length == 1
967   throw :halt, response
968 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
973 def pass(&block)
974   throw :pass, block
975 end
settings() click to toggle source

Access settings defined with Base.set.

    # File lib/sinatra/base.rb
959 def settings
960   self.class.settings
961 end

Private Instance Methods

dispatch!() click to toggle source

Dispatch a request with error handling.

     # File lib/sinatra/base.rb
1114 def dispatch!
1115   # Avoid passing frozen string in force_encoding
1116   @params.merge!(@request.params).each do |key, val|
1117     next unless val.respond_to?(:force_encoding)
1118 
1119     val = val.dup if val.frozen?
1120     @params[key] = force_encoding(val)
1121   end
1122 
1123   invoke do
1124     static! if settings.static? && (request.get? || request.head?)
1125     filter! :before do
1126       @pinned_response = !response['Content-Type'].nil?
1127     end
1128     route!
1129   end
1130 rescue ::Exception => e
1131   invoke { handle_exception!(e) }
1132 ensure
1133   begin
1134     filter! :after unless env['sinatra.static_file']
1135   rescue ::Exception => e
1136     invoke { handle_exception!(e) } unless @env['sinatra.error']
1137   end
1138 end
dump_errors!(boom) click to toggle source
     # File lib/sinatra/base.rb
1206 def dump_errors!(boom)
1207   msg = ["#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - #{boom.class} - #{boom.message}:", *boom.backtrace].join("\n\t")
1208   @env['rack.errors'].puts(msg)
1209 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
1187 def error_block!(key, *block_params)
1188   base = settings
1189   while base.respond_to?(:errors)
1190     args_array = base.errors[key]
1191 
1192     next base = base.superclass unless args_array
1193 
1194     args_array.reverse_each do |args|
1195       first = args == args_array.first
1196       args += [block_params]
1197       resp = process_route(*args)
1198       return resp unless resp.nil? && !first
1199     end
1200   end
1201   return false unless key.respond_to?(:superclass) && (key.superclass < Exception)
1202 
1203   error_block!(key.superclass, *block_params)
1204 end
filter!(type, base = settings, &block) click to toggle source

Run filters defined on the class and all superclasses. Accepts an optional block to call after each filter is applied.

    # File lib/sinatra/base.rb
992 def filter!(type, base = settings, &block)
993   filter!(type, base.superclass, &block) if base.superclass.respond_to?(:filters)
994   base.filters[type].each do |args|
995     result = process_route(*args)
996     block.call(result) if block_given?
997   end
998 end
force_encoding(*args) click to toggle source
     # File lib/sinatra/base.rb
1809 def force_encoding(*args)
1810   settings.force_encoding(*args)
1811 end
handle_exception!(boom) click to toggle source

Error handling during requests.

     # File lib/sinatra/base.rb
1141 def handle_exception!(boom)
1142   error_params = @env['sinatra.error.params']
1143 
1144   @params = @params.merge(error_params) if error_params
1145 
1146   @env['sinatra.error'] = boom
1147 
1148   http_status = if boom.is_a? Sinatra::Error
1149                   if boom.respond_to? :http_status
1150                     boom.http_status
1151                   elsif settings.use_code? && boom.respond_to?(:code)
1152                     boom.code
1153                   end
1154                 end
1155 
1156   http_status = 500 unless http_status&.between?(400, 599)
1157   status(http_status)
1158 
1159   if server_error?
1160     dump_errors! boom if settings.dump_errors?
1161     raise boom if settings.show_exceptions? && (settings.show_exceptions != :after_handler)
1162   elsif not_found?
1163     headers['X-Cascade'] = 'pass' if settings.x_cascade?
1164   end
1165 
1166   if (res = error_block!(boom.class, boom) || error_block!(status, boom))
1167     return res
1168   end
1169 
1170   if not_found? || bad_request?
1171     if boom.message && boom.message != boom.class.name
1172       body Rack::Utils.escape_html(boom.message)
1173     else
1174       content_type 'text/html'
1175       body "<h1>#{not_found? ? 'Not Found' : 'Bad Request'}</h1>"
1176     end
1177   end
1178 
1179   return unless server_error?
1180 
1181   raise boom if settings.raise_errors? || settings.show_exceptions?
1182 
1183   error_block! Exception, boom
1184 end
invoke(&block) click to toggle source

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

     # File lib/sinatra/base.rb
1098 def invoke(&block)
1099   res = catch(:halt, &block)
1100 
1101   res = [res] if (Integer === res) || (String === res)
1102   if (Array === res) && (Integer === res.first)
1103     res = res.dup
1104     status(res.shift)
1105     body(res.pop)
1106     headers(*res)
1107   elsif res.respond_to? :each
1108     body res
1109   end
1110   nil # avoid double setting the same response tuple twice
1111 end
process_route(pattern, 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
1035 def process_route(pattern, conditions, block = nil, values = [])
1036   route = @request.path_info
1037   route = '/' if route.empty? && !settings.empty_path_info?
1038   route = route[0..-2] if !settings.strict_paths? && route != '/' && route.end_with?('/')
1039 
1040   params = pattern.params(route)
1041   return unless params
1042 
1043   params.delete('ignore') # TODO: better params handling, maybe turn it into "smart" object or detect changes
1044   force_encoding(params)
1045   @params = @params.merge(params) { |_k, v1, v2| v2 || v1 } if params.any?
1046 
1047   regexp_exists = pattern.is_a?(Mustermann::Regular) || (pattern.respond_to?(:patterns) && pattern.patterns.any? { |subpattern| subpattern.is_a?(Mustermann::Regular) })
1048   if regexp_exists
1049     captures           = pattern.match(route).captures.map { |c| URI_INSTANCE.unescape(c) if c }
1050     values            += captures
1051     @params[:captures] = force_encoding(captures) unless captures.nil? || captures.empty?
1052   else
1053     values += params.values.flatten
1054   end
1055 
1056   catch(:pass) do
1057     conditions.each { |c| throw :pass if c.bind(self).call == false }
1058     block ? block[self, values] : yield(self, values)
1059   end
1060 rescue StandardError
1061   @env['sinatra.error.params'] = @params
1062   raise
1063 ensure
1064   params ||= {}
1065   params.each { |k, _| @params.delete(k) } unless @env['sinatra.error.params']
1066 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
1001 def route!(base = settings, pass_block = nil)
1002   routes = base.routes[@request.request_method]
1003 
1004   routes&.each do |pattern, conditions, block|
1005     response.delete_header('Content-Type') unless @pinned_response
1006 
1007     returned_pass_block = process_route(pattern, conditions) do |*args|
1008       env['sinatra.route'] = "#{@request.request_method} #{pattern}"
1009       route_eval { block[*args] }
1010     end
1011 
1012     # don't wipe out pass_block in superclass
1013     pass_block = returned_pass_block if returned_pass_block
1014   end
1015 
1016   # Run routes defined in superclass.
1017   if base.superclass.respond_to?(:routes)
1018     return route!(base.superclass, pass_block)
1019   end
1020 
1021   route_eval(&pass_block) if pass_block
1022   route_missing
1023 end
route_eval() { || ... } click to toggle source

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

     # File lib/sinatra/base.rb
1026 def route_eval
1027   throw :halt, yield
1028 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
1073 def route_missing
1074   raise NotFound unless @app
1075 
1076   forward
1077 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
1081 def static!(options = {})
1082   return if (public_dir = settings.public_folder).nil?
1083 
1084   path = "#{public_dir}#{URI_INSTANCE.unescape(request.path_info)}"
1085   return unless valid_path?(path)
1086 
1087   path = File.expand_path(path)
1088   return unless path.start_with?("#{File.expand_path(public_dir)}/")
1089 
1090   return unless File.file?(path)
1091 
1092   env['sinatra.static_file'] = path
1093   cache_control(*settings.static_cache_control) if settings.static_cache_control?
1094   send_file path, options.merge(disposition: nil)
1095 end