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
1412 def add_filter(type, path = /.*/, **options, &block)
1413   filters[type] << compile!(type, path, block, **options)
1414 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
1407 def after(path = /.*/, **options, &block)
1408   add_filter(:after, path, **options, &block)
1409 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
1400 def before(path = /.*/, **options, &block)
1401   add_filter(:before, path, **options, &block)
1402 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
1557 def build(app)
1558   builder = Rack::Builder.new
1559   setup_default_middleware builder
1560   setup_middleware builder
1561   builder.run app
1562   builder
1563 end
call(env) click to toggle source
     # File lib/sinatra/base.rb
1565 def call(env)
1566   synchronize { prototype.call(env) }
1567 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
1571 def caller_files
1572   cleaned_caller(1).flatten
1573 end
callers_to_ignore() click to toggle source
     # File lib/sinatra/base.rb
1225 def callers_to_ignore
1226   CALLERS_TO_IGNORE
1227 end
cleaned_caller(keep = 3) click to toggle source

Like Kernel#caller but excluding certain magic entries

     # File lib/sinatra/base.rb
1792 def cleaned_caller(keep = 3)
1793   caller(1)
1794     .map! { |line| line.split(/:(?=\d|in )/, 3)[0, keep] }
1795     .reject { |file, *_| callers_to_ignore.any? { |pattern| file =~ pattern } }
1796 end
compile(path, route_mustermann_opts = {}) click to toggle source
     # File lib/sinatra/base.rb
1702 def compile(path, route_mustermann_opts = {})
1703   Mustermann.new(path, **mustermann_opts.merge(route_mustermann_opts))
1704 end
compile!(verb, path, block, **options) click to toggle source
     # File lib/sinatra/base.rb
1682 def compile!(verb, path, block, **options)
1683   # Because of self.options.host
1684   host_name(options.delete(:host)) if options.key?(:host)
1685   # Pass Mustermann opts to compile()
1686   route_mustermann_opts = options.key?(:mustermann_opts) ? options.delete(:mustermann_opts) : {}.freeze
1687 
1688   options.each_pair { |option, args| send(option, *args) }
1689 
1690   pattern                 = compile(path, route_mustermann_opts)
1691   method_name             = "#{verb} #{path}"
1692   unbound_method          = generate_method(method_name, &block)
1693   conditions = @conditions
1694   @conditions = []
1695   wrapper = block.arity.zero? ?
1696     proc { |a, _p| unbound_method.bind(a).call } :
1697     proc { |a, p| unbound_method.bind(a).call(*p) }
1698 
1699   [pattern, conditions, wrapper]
1700 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
1418 def condition(name = "#{caller.first[/`.*'/]} condition", &block)
1419   @conditions << generate_method(name, &block)
1420 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
1485 def configure(*envs)
1486   yield self if envs.empty? || envs.include?(environment.to_sym)
1487 end
define_singleton(name, content = Proc.new) click to toggle source

Dynamically defines a method on settings.

     # File lib/sinatra/base.rb
1617 def define_singleton(name, content = Proc.new)
1618   singleton_class.class_eval do
1619     undef_method(name) if method_defined? name
1620     String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content)
1621   end
1622 end
delete(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1449 def delete(path, opts = {}, &block)  route 'DELETE',  path, opts, &block end
development?() click to toggle source
     # File lib/sinatra/base.rb
1479 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
1313 def disable(*opts)
1314   opts.each { |key| set(key, false) }
1315 end
enable(*opts) click to toggle source

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

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

Extension modules registered on this class and all superclasses.

     # File lib/sinatra/base.rb
1248 def extensions
1249   if superclass.respond_to?(:extensions)
1250     (@extensions + superclass.extensions).uniq
1251   else
1252     @extensions
1253   end
1254 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
1801 def self.force_encoding(data, encoding = default_encoding)
1802   return if data == settings || data.is_a?(Tempfile)
1803 
1804   if data.respond_to? :force_encoding
1805     data.force_encoding(encoding).encode!
1806   elsif data.respond_to? :each_value
1807     data.each_value { |v| force_encoding(v, encoding) }
1808   elsif data.respond_to? :each
1809     data.each { |v| force_encoding(v, encoding) }
1810   end
1811   data
1812 end
generate_method(method_name, &block) click to toggle source
     # File lib/sinatra/base.rb
1675 def generate_method(method_name, &block)
1676   define_method(method_name, &block)
1677   method = instance_method method_name
1678   remove_method method_name
1679   method
1680 end
get(path, opts = {}, &block) click to toggle source

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

     # File lib/sinatra/base.rb
1437 def get(path, opts = {}, &block)
1438   conditions = @conditions.dup
1439   route('GET', path, opts, &block)
1440 
1441   @conditions = conditions
1442   route('HEAD', path, opts, &block)
1443 end
head(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1451 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
1463 def helpers(*extensions, &block)
1464   class_eval(&block)   if block_given?
1465   include(*extensions) if extensions.any?
1466 end
host_name(pattern) click to toggle source

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

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

Middleware used in this class and all superclasses.

     # File lib/sinatra/base.rb
1257 def middleware
1258   if superclass.respond_to?(:middleware)
1259     superclass.middleware + @middleware
1260   else
1261     @middleware
1262   end
1263 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
1379 def mime_type(type, value = nil)
1380   return type      if type.nil?
1381   return type.to_s if type.to_s.include?('/')
1382 
1383   type = ".#{type}" unless type.to_s[0] == '.'
1384   return Rack::Mime.mime_type(type, nil) unless value
1385 
1386   Rack::Mime::MIME_TYPES[type] = value
1387 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
1392 def mime_types(type)
1393   type = mime_type type
1394   type =~ %r{^application/(xml|javascript)$} ? [type, "text/#{$1}"] : [type]
1395 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
1549 def new(*args, &block)
1550   instance = new!(*args, &block)
1551   Wrapper.new(build(instance).to_app, instance)
1552 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
1329 def not_found(&block)
1330   error(404, &block)
1331 end
options(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1453 def options(path, opts = {}, &block) route 'OPTIONS', path, opts, &block end
patch(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1455 def patch(path, opts = {}, &block)   route 'PATCH',   path, opts, &block end
post(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1447 def post(path, opts = {}, &block)    route 'POST',    path, opts, &block end
production?() click to toggle source
     # File lib/sinatra/base.rb
1480 def production?;  environment == :production  end
prototype() click to toggle source

The prototype instance used to process requests.

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

Condition for matching mimetypes. Accepts file extensions.

     # File lib/sinatra/base.rb
1644 def provides(*types)
1645   types.map! { |t| mime_types(t) }
1646   types.flatten!
1647   condition do
1648     response_content_type = response['Content-Type']
1649     preferred_type = request.preferred_type(types)
1650 
1651     if response_content_type
1652       types.include?(response_content_type) || types.include?(response_content_type[/^[^;]+/])
1653     elsif preferred_type
1654       params = (preferred_type.respond_to?(:params) ? preferred_type.params : {})
1655       content_type(preferred_type, params)
1656       true
1657     else
1658       false
1659     end
1660   end
1661 end
public=(value) click to toggle source
     # File lib/sinatra/base.rb
1422 def public=(value)
1423   warn_for_deprecation ':public is no longer used to avoid overloading Module#public, use :public_folder or :public_dir instead'
1424   set(:public_folder, value)
1425 end
public_dir() click to toggle source
     # File lib/sinatra/base.rb
1431 def public_dir
1432   public_folder
1433 end
public_dir=(value) click to toggle source
     # File lib/sinatra/base.rb
1427 def public_dir=(value)
1428   self.public_folder = value
1429 end
put(path, opts = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1445 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
1497 def quit!
1498   return unless running?
1499 
1500   # Use Thin's hard #stop! if available, otherwise just #stop.
1501   running_server.respond_to?(:stop!) ? running_server.stop! : running_server.stop
1502   warn '== Sinatra has ended his set (crowd applauds)' unless suppress_messages?
1503   set :running_server, nil
1504   set :handler_name, nil
1505 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
1470 def register(*extensions, &block)
1471   extensions << Module.new(&block) if block_given?
1472   @extensions += extensions
1473   extensions.each do |extension|
1474     extend extension
1475     extension.registered(self) if extension.respond_to?(:registered)
1476   end
1477 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
1231 def reset!
1232   @conditions     = []
1233   @routes         = {}
1234   @filters        = { before: [], after: [] }
1235   @errors         = {}
1236   @middleware     = []
1237   @prototype      = nil
1238   @extensions     = []
1239 
1240   @templates = if superclass.respond_to?(:templates)
1241                  Hash.new { |_hash, key| superclass.templates[key] }
1242                else
1243                  {}
1244                end
1245 end
route(verb, path, options = {}, &block) click to toggle source
     # File lib/sinatra/base.rb
1663 def route(verb, path, options = {}, &block)
1664   enable :empty_path_info if path == '' && empty_path_info.nil?
1665   signature = compile!(verb, path, block, **options)
1666   (@routes[verb] ||= []) << signature
1667   invoke_hook(:route_added, verb, path, block)
1668   signature
1669 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
1512 def run!(options = {}, &block)
1513   return if running?
1514 
1515   set options
1516   handler         = Rack::Handler.pick(server)
1517   handler_name    = handler.name.gsub(/.*::/, '')
1518   server_settings = settings.respond_to?(:server_settings) ? settings.server_settings : {}
1519   server_settings.merge!(Port: port, Host: bind)
1520 
1521   begin
1522     start_server(handler, server_settings, handler_name, &block)
1523   rescue Errno::EADDRINUSE
1524     warn "== Someone is already performing on port #{port}!"
1525     raise
1526   ensure
1527     quit!
1528   end
1529 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
1534 def running?
1535   running_server?
1536 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
1267 def set(option, value = (not_set = true), ignore_setter = false, &block)
1268   raise ArgumentError if block && !not_set
1269 
1270   if block
1271     value = block
1272     not_set = false
1273   end
1274 
1275   if not_set
1276     raise ArgumentError unless option.respond_to?(:each)
1277 
1278     option.each { |k, v| set(k, v) }
1279     return self
1280   end
1281 
1282   if respond_to?("#{option}=") && !ignore_setter
1283     return __send__("#{option}=", value)
1284   end
1285 
1286   setter = proc { |val| set option, val, true }
1287   getter = proc { value }
1288 
1289   case value
1290   when Proc
1291     getter = value
1292   when Symbol, Integer, FalseClass, TrueClass, NilClass
1293     getter = value.inspect
1294   when Hash
1295     setter = proc do |val|
1296       val = value.merge val if Hash === val
1297       set option, val, true
1298     end
1299   end
1300 
1301   define_singleton("#{option}=", setter)
1302   define_singleton(option, getter)
1303   define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
1304   self
1305 end
setup_common_logger(builder) click to toggle source
     # File lib/sinatra/base.rb
1733 def setup_common_logger(builder)
1734   builder.use Sinatra::CommonLogger
1735 end
setup_custom_logger(builder) click to toggle source
     # File lib/sinatra/base.rb
1737 def setup_custom_logger(builder)
1738   if logging.respond_to? :to_int
1739     builder.use Rack::Logger, logging
1740   else
1741     builder.use Rack::Logger
1742   end
1743 end
setup_default_middleware(builder) click to toggle source
     # File lib/sinatra/base.rb
1706 def setup_default_middleware(builder)
1707   builder.use ExtendedRack
1708   builder.use ShowExceptions       if show_exceptions?
1709   builder.use Rack::MethodOverride if method_override?
1710   builder.use Rack::Head
1711   setup_logging    builder
1712   setup_sessions   builder
1713   setup_protection builder
1714 end
setup_logging(builder) click to toggle source
     # File lib/sinatra/base.rb
1720 def setup_logging(builder)
1721   if logging?
1722     setup_common_logger(builder)
1723     setup_custom_logger(builder)
1724   elsif logging == false
1725     setup_null_logger(builder)
1726   end
1727 end
setup_middleware(builder) click to toggle source
     # File lib/sinatra/base.rb
1716 def setup_middleware(builder)
1717   middleware.each { |c, a, b| builder.use(c, *a, &b) }
1718 end
setup_null_logger(builder) click to toggle source
     # File lib/sinatra/base.rb
1729 def setup_null_logger(builder)
1730   builder.use Rack::NullLogger
1731 end
setup_protection(builder) click to toggle source
     # File lib/sinatra/base.rb
1745 def setup_protection(builder)
1746   return unless protection?
1747 
1748   options = Hash === protection ? protection.dup : {}
1749   options = {
1750     img_src: "'self' data:",
1751     font_src: "'self'"
1752   }.merge options
1753 
1754   protect_session = options.fetch(:session) { sessions? }
1755   options[:without_session] = !protect_session
1756 
1757   options[:reaction] ||= :drop_session
1758 
1759   builder.use Rack::Protection, options
1760 end
setup_sessions(builder) click to toggle source
     # File lib/sinatra/base.rb
1762 def setup_sessions(builder)
1763   return unless sessions?
1764 
1765   options = {}
1766   options[:secret] = session_secret if session_secret?
1767   options.merge! sessions.to_hash if sessions.respond_to? :to_hash
1768   builder.use session_store, options
1769 end
setup_traps() click to toggle source
     # File lib/sinatra/base.rb
1601 def setup_traps
1602   return unless traps?
1603 
1604   at_exit { quit! }
1605 
1606   %i[INT TERM].each do |signal|
1607     old_handler = trap(signal) do
1608       quit!
1609       old_handler.call if old_handler.respond_to?(:call)
1610     end
1611   end
1612 
1613   set :traps, false
1614 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
1578 def start_server(handler, server_settings, handler_name)
1579   # Ensure we initialize middleware before startup, to match standard Rack
1580   # behavior, by ensuring an instance exists:
1581   prototype
1582   # Run the instance we created:
1583   handler.run(self, **server_settings) do |server|
1584     unless suppress_messages?
1585       warn "== Sinatra (v#{Sinatra::VERSION}) has taken the stage on #{port} for #{environment} with backup from #{handler_name}"
1586     end
1587 
1588     setup_traps
1589     set :running_server, server
1590     set :handler_name,   handler_name
1591     server.threaded = settings.threaded if server.respond_to? :threaded=
1592 
1593     yield server if block_given?
1594   end
1595 end
stop!()
Alias for: quit!
suppress_messages?() click to toggle source
     # File lib/sinatra/base.rb
1597 def suppress_messages?
1598   handler_name =~ /cgi/i || quiet
1599 end
synchronize() { || ... } click to toggle source
     # File lib/sinatra/base.rb
1778 def synchronize(&block)
1779   if lock?
1780     @@mutex.synchronize(&block)
1781   else
1782     yield
1783   end
1784 end
template(name, &block) click to toggle source

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

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

Use the specified Rack middleware

     # File lib/sinatra/base.rb
1490 def use(middleware, *args, &block)
1491   @prototype = nil
1492   @middleware << [middleware, args, block]
1493 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
1631 def user_agent(pattern)
1632   condition do
1633     if request.user_agent.to_s =~ pattern
1634       @params[:agent] = $~[1..-1]
1635       true
1636     else
1637       false
1638     end
1639   end
1640 end
Also aliased as: agent
warn_for_deprecation(message) click to toggle source

used for deprecation warnings

     # File lib/sinatra/base.rb
1787 def warn_for_deprecation(message)
1788   warn message + "\n\tfrom #{cleaned_caller.first.join(':')}"
1789 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
1814 def force_encoding(*args)
1815   settings.force_encoding(*args)
1816 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