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 1412 def add_filter(type, path = /.*/, **options, &block) 1413 filters[type] << compile!(type, path, block, **options) 1414 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 1407 def after(path = /.*/, **options, &block) 1408 add_filter(:after, path, **options, &block) 1409 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 1400 def before(path = /.*/, **options, &block) 1401 add_filter(:before, path, **options, &block) 1402 end
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
# File lib/sinatra/base.rb 1565 def call(env) 1566 synchronize { prototype.call(env) } 1567 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 1571 def caller_files 1572 cleaned_caller(1).flatten 1573 end
# File lib/sinatra/base.rb 1225 def callers_to_ignore 1226 CALLERS_TO_IGNORE 1227 end
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
# File lib/sinatra/base.rb 1702 def compile(path, route_mustermann_opts = {}) 1703 Mustermann.new(path, **mustermann_opts.merge(route_mustermann_opts)) 1704 end
# 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
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
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
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
# File lib/sinatra/base.rb 1449 def delete(path, opts = {}, &block) route 'DELETE', path, opts, &block end
# File lib/sinatra/base.rb 1479 def development?; environment == :development end
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
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
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
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 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
# 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
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
# File lib/sinatra/base.rb 1451 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 1463 def helpers(*extensions, &block) 1464 class_eval(&block) if block_given? 1465 include(*extensions) if extensions.any? 1466 end
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
# 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
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
# 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
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
# File lib/sinatra/base.rb 1457 def link(path, opts = {}, &block) route 'LINK', path, opts, &block end
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
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
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
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
Sugar for ‘error(404) { … }`
# File lib/sinatra/base.rb 1329 def not_found(&block) 1330 error(404, &block) 1331 end
# File lib/sinatra/base.rb 1453 def options(path, opts = {}, &block) route 'OPTIONS', path, opts, &block end
# File lib/sinatra/base.rb 1455 def patch(path, opts = {}, &block) route 'PATCH', path, opts, &block end
# File lib/sinatra/base.rb 1447 def post(path, opts = {}, &block) route 'POST', path, opts, &block end
# File lib/sinatra/base.rb 1480 def production?; environment == :production end
The prototype instance used to process requests.
# File lib/sinatra/base.rb 1539 def prototype 1540 @prototype ||= new 1541 end
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
# 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
# File lib/sinatra/base.rb 1431 def public_dir 1432 public_folder 1433 end
# File lib/sinatra/base.rb 1427 def public_dir=(value) 1428 self.public_folder = value 1429 end
# File lib/sinatra/base.rb 1445 def put(path, opts = {}, &block) route 'PUT', path, opts, &block end
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
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
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
# 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 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
Check whether the self-hosted server is running or not.
# File lib/sinatra/base.rb 1534 def running? 1535 running_server? 1536 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 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
# File lib/sinatra/base.rb 1733 def setup_common_logger(builder) 1734 builder.use Sinatra::CommonLogger 1735 end
# 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
# 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
# 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
# File lib/sinatra/base.rb 1716 def setup_middleware(builder) 1717 middleware.each { |c, a, b| builder.use(c, *a, &b) } 1718 end
# File lib/sinatra/base.rb 1729 def setup_null_logger(builder) 1730 builder.use Rack::NullLogger 1731 end
# 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
# 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
# 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
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
# File lib/sinatra/base.rb 1597 def suppress_messages? 1598 handler_name =~ /cgi/i || quiet 1599 end
# File lib/sinatra/base.rb 1778 def synchronize(&block) 1779 if lock? 1780 @@mutex.synchronize(&block) 1781 else 1782 yield 1783 end 1784 end
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
# File lib/sinatra/base.rb 1481 def test?; environment == :test end
# File lib/sinatra/base.rb 1459 def unlink(path, opts = {}, &block) route 'UNLINK', path, opts, &block end
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
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
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
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 1814 def force_encoding(*args) 1815 settings.force_encoding(*args) 1816 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