class Sinatra::Helpers::Stream::Base
Constants
- URI_INSTANCE
Attributes
Public Class Methods
Sinatra::Helpers::Stream::Templates::new
# 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
Access settings defined with Base.set.
# File lib/sinatra/base.rb 954 def self.settings 955 self 956 end
Private Class Methods
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
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
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
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
# File lib/sinatra/base.rb 1560 def call(env) 1561 synchronize { prototype.call(env) } 1562 end
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
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
# File lib/sinatra/base.rb 1697 def compile(path, route_mustermann_opts = {}) 1698 Mustermann.new(path, **mustermann_opts.merge(route_mustermann_opts)) 1699 end
# 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
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
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
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
# File lib/sinatra/base.rb 1444 def delete(path, opts = {}, &block) route 'DELETE', path, opts, &block end
# File lib/sinatra/base.rb 1474 def development?; environment == :development end
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
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
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
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 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
# 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
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
# File lib/sinatra/base.rb 1446 def head(path, opts = {}, &block) route 'HEAD', path, opts, &block end
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
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
# 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
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
# 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
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
# File lib/sinatra/base.rb 1452 def link(path, opts = {}, &block) route 'LINK', path, opts, &block end
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
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
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
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
Sugar for ‘error(404) { … }`
# File lib/sinatra/base.rb 1324 def not_found(&block) 1325 error(404, &block) 1326 end
# File lib/sinatra/base.rb 1448 def options(path, opts = {}, &block) route 'OPTIONS', path, opts, &block end
# File lib/sinatra/base.rb 1450 def patch(path, opts = {}, &block) route 'PATCH', path, opts, &block end
# File lib/sinatra/base.rb 1442 def post(path, opts = {}, &block) route 'POST', path, opts, &block end
# File lib/sinatra/base.rb 1475 def production?; environment == :production end
The prototype instance used to process requests.
# File lib/sinatra/base.rb 1534 def prototype 1535 @prototype ||= new 1536 end
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
# 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
# File lib/sinatra/base.rb 1426 def public_dir 1427 public_folder 1428 end
# File lib/sinatra/base.rb 1422 def public_dir=(value) 1423 self.public_folder = value 1424 end
# File lib/sinatra/base.rb 1440 def put(path, opts = {}, &block) route 'PUT', path, opts, &block end
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
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
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
# 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 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
Check whether the self-hosted server is running or not.
# File lib/sinatra/base.rb 1529 def running? 1530 running_server? 1531 end
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
# File lib/sinatra/base.rb 1728 def setup_common_logger(builder) 1729 builder.use Sinatra::CommonLogger 1730 end
# 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
# 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
# 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
# File lib/sinatra/base.rb 1711 def setup_middleware(builder) 1712 middleware.each { |c, a, b| builder.use(c, *a, &b) } 1713 end
# File lib/sinatra/base.rb 1724 def setup_null_logger(builder) 1725 builder.use Rack::NullLogger 1726 end
# 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
# 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
# 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
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
# File lib/sinatra/base.rb 1592 def suppress_messages? 1593 handler_name =~ /cgi/i || quiet 1594 end
# File lib/sinatra/base.rb 1773 def synchronize(&block) 1774 if lock? 1775 @@mutex.synchronize(&block) 1776 else 1777 yield 1778 end 1779 end
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
# File lib/sinatra/base.rb 1476 def test?; environment == :test end
# File lib/sinatra/base.rb 1454 def unlink(path, opts = {}, &block) route 'UNLINK', path, opts, &block end
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
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
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
Rack call interface.
# File lib/sinatra/base.rb 927 def call(env) 928 dup.call!(env) 929 end
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
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 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
Access settings defined with Base.set.
# File lib/sinatra/base.rb 959 def settings 960 self.class.settings 961 end
Private Instance Methods
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
# 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
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
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
# File lib/sinatra/base.rb 1809 def force_encoding(*args) 1810 settings.force_encoding(*args) 1811 end
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
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
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
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
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
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
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