class Sinatra::Helpers::Stream::Base
Constants
- URI_INSTANCE
Attributes
Public Class Methods
Sinatra::Helpers::Stream::Templates::new
# File lib/sinatra/base.rb 877 def initialize(app = nil) 878 super() 879 @app = app 880 @template_cache = Tilt::Cache.new 881 yield self if block_given? 882 end
Access settings defined with Base.set
.
# File lib/sinatra/base.rb 913 def self.settings 914 self 915 end
Private Class Methods
add a filter
# File lib/sinatra/base.rb 1334 def add_filter(type, path = nil, options = {}, &block) 1335 path, options = //, path if path.respond_to?(:each_pair) 1336 filters[type] << compile!(type, path || //, block, options) 1337 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 1329 def after(path = nil, options = {}, &block) 1330 add_filter(:after, path, options, &block) 1331 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 1322 def before(path = nil, options = {}, &block) 1323 add_filter(:before, path, options, &block) 1324 end
Creates a Rack::Builder
instance with all the middleware set up and the given app
as end point.
# File lib/sinatra/base.rb 1469 def build(app) 1470 builder = Rack::Builder.new 1471 setup_default_middleware builder 1472 setup_middleware builder 1473 builder.run app 1474 builder 1475 end
# File lib/sinatra/base.rb 1477 def call(env) 1478 synchronize { prototype.call(env) } 1479 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 1483 def caller_files 1484 cleaned_caller(1).flatten 1485 end
Like caller_files
, but containing Arrays rather than strings with the first element being the file, and the second being the line.
# File lib/sinatra/base.rb 1489 def caller_locations 1490 cleaned_caller 2 1491 end
Like Kernel#caller but excluding certain magic entries
# File lib/sinatra/base.rb 1798 def cleaned_caller(keep = 3) 1799 caller(1). 1800 map! { |line| line.split(/:(?=\d|in )/, 3)[0,keep] }. 1801 reject { |file, *_| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } } 1802 end
# File lib/sinatra/base.rb 1609 def compile(path) 1610 if path.respond_to? :to_str 1611 keys = [] 1612 1613 # We append a / at the end if there was one. 1614 # Reason: Splitting does not split off an empty 1615 # string at the end if the split separator 1616 # is at the end. 1617 # 1618 postfix = '/' if path =~ /\/\z/ 1619 1620 # Split the path into pieces in between forward slashes. 1621 # 1622 segments = path.split('/').map! do |segment| 1623 ignore = [] 1624 1625 # Special character handling. 1626 # 1627 pattern = segment.to_str.gsub(/[^\?\%\\\/\:\*\w]/) do |c| 1628 ignore << escaped(c).join if c.match(/[\.@]/) 1629 patt = encoded(c) 1630 patt.gsub(/%[\da-fA-F]{2}/) do |match| 1631 match.split(//).map! {|char| char =~ /[A-Z]/ ? "[#{char}#{char.tr('A-Z', 'a-z')}]" : char}.join 1632 end 1633 end 1634 1635 ignore = ignore.uniq.join 1636 1637 # Key handling. 1638 # 1639 pattern.gsub(/((:\w+)|\*)/) do |match| 1640 if match == "*" 1641 keys << 'splat' 1642 "(.*?)" 1643 else 1644 keys << $2[1..-1] 1645 ignore_pattern = safe_ignore(ignore) 1646 1647 ignore_pattern 1648 end 1649 end 1650 end 1651 1652 # Special case handling. 1653 # 1654 if segment = segments.pop 1655 if segment.match(/\[\^\\\./) 1656 parts = segment.rpartition(/\[\^\\\./) 1657 parts[1] = '[^' 1658 segments << parts.join 1659 else 1660 segments << segment 1661 end 1662 end 1663 [/\A#{segments.join('/')}#{postfix}\z/, keys] 1664 elsif path.respond_to?(:keys) && path.respond_to?(:match) 1665 [path, path.keys] 1666 elsif path.respond_to?(:names) && path.respond_to?(:match) 1667 [path, path.names] 1668 elsif path.respond_to? :match 1669 [path, []] 1670 else 1671 raise TypeError, path 1672 end 1673 end
# File lib/sinatra/base.rb 1594 def compile!(verb, path, block, options = {}) 1595 options.each_pair { |option, args| send(option, *args) } 1596 method_name = "#{verb} #{path}" 1597 unbound_method = generate_method(method_name, &block) 1598 pattern, keys = compile path 1599 conditions, @conditions = @conditions, [] 1600 1601 wrapper = block.arity != 0 ? 1602 proc { |a,p| unbound_method.bind(a).call(*p) } : 1603 proc { |a,p| unbound_method.bind(a).call } 1604 wrapper.instance_variable_set(:@route_name, method_name) 1605 1606 [ pattern, keys, conditions, wrapper ] 1607 end
Add a route condition. The route is considered non-matching when the block returns false.
# File lib/sinatra/base.rb 1341 def condition(name = "#{caller.first[/`.*'/]} condition", &block) 1342 @conditions << generate_method(name, &block) 1343 end
Set configuration options for Sinatra
and/or the app. Allows scoping of settings for certain environments.
# File lib/sinatra/base.rb 1401 def configure(*envs) 1402 yield self if envs.empty? || envs.include?(environment.to_sym) 1403 end
Dynamically defines a method on settings.
# File lib/sinatra/base.rb 1528 def define_singleton(name, content = Proc.new) 1529 # replace with call to singleton_class once we're 1.9 only 1530 (class << self; self; end).class_eval do 1531 undef_method(name) if method_defined? name 1532 String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content) 1533 end 1534 end
# File lib/sinatra/base.rb 1370 def delete(path, opts = {}, &bk) route 'DELETE', path, opts, &bk end
# File lib/sinatra/base.rb 1766 def detect_rack_handler 1767 servers = Array(server) 1768 servers.each do |server_name| 1769 begin 1770 return Rack::Handler.get(server_name.to_s) 1771 rescue LoadError, NameError 1772 end 1773 end 1774 fail "Server handler (#{servers.join(',')}) not found." 1775 end
# File lib/sinatra/base.rb 1395 def development?; environment == :development end
Same as calling ‘set :option, false` for each of the given options.
# File lib/sinatra/base.rb 1238 def disable(*opts) 1239 opts.each { |key| set(key, false) } 1240 end
Same as calling ‘set :option, true` for each of the given options.
# File lib/sinatra/base.rb 1233 def enable(*opts) 1234 opts.each { |key| set(key, true) } 1235 end
# File lib/sinatra/base.rb 1675 def encoded(char) 1676 enc = URI_INSTANCE.escape(char) 1677 enc = "(?:#{escaped(char, enc).join('|')})" if enc == char 1678 enc = "(?:#{enc}|#{encoded('+')})" if char == " " 1679 enc 1680 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 1245 def error(*codes, &block) 1246 args = compile! "ERROR", //, block 1247 codes = codes.map { |c| Array(c) }.flatten 1248 codes << Exception if codes.empty? 1249 codes.each { |c| (@errors[c] ||= []) << args } 1250 end
# File lib/sinatra/base.rb 1682 def escaped(char, enc = URI_INSTANCE.escape(char)) 1683 [Regexp.escape(enc), URI_INSTANCE.escape(char, /./)] 1684 end
Extension modules registered on this class and all superclasses.
# File lib/sinatra/base.rb 1178 def extensions 1179 if superclass.respond_to?(:extensions) 1180 (@extensions + superclass.extensions).uniq 1181 else 1182 @extensions 1183 end 1184 end
# File lib/sinatra/base.rb 1813 def self.force_encoding(data, encoding = default_encoding) 1814 return if data == settings || data.is_a?(Tempfile) 1815 if data.respond_to? :force_encoding 1816 data.force_encoding(encoding).encode! 1817 elsif data.respond_to? :each_value 1818 data.each_value { |v| force_encoding(v, encoding) } 1819 elsif data.respond_to? :each 1820 data.each { |v| force_encoding(v, encoding) } 1821 end 1822 data 1823 end
# File lib/sinatra/base.rb 1586 def generate_method(method_name, &block) 1587 method_name = method_name.to_sym 1588 define_method(method_name, &block) 1589 method = instance_method method_name 1590 remove_method method_name 1591 method 1592 end
Defining a ‘GET` handler also automatically defines a `HEAD` handler.
# File lib/sinatra/base.rb 1360 def get(path, opts = {}, &block) 1361 conditions = @conditions.dup 1362 route('GET', path, opts, &block) 1363 1364 @conditions = conditions 1365 route('HEAD', path, opts, &block) 1366 end
# File lib/sinatra/base.rb 1371 def head(path, opts = {}, &bk) route 'HEAD', path, opts, &bk 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 1379 def helpers(*extensions, &block) 1380 class_eval(&block) if block_given? 1381 include(*extensions) if extensions.any? 1382 end
Condition for matching host name. Parameter might be String or Regexp.
# File lib/sinatra/base.rb 1537 def host_name(pattern) 1538 condition { pattern === request.host } 1539 end
# File lib/sinatra/base.rb 1777 def inherited(subclass) 1778 subclass.reset! 1779 subclass.set :app_file, caller_files.first unless subclass.app_file? 1780 super 1781 end
Load embedded templates from the file; uses the caller’s __FILE__ when no file is specified.
# File lib/sinatra/base.rb 1271 def inline_templates=(file = nil) 1272 file = (file.nil? || file == true) ? (caller_files.first || File.expand_path($0)) : file 1273 1274 begin 1275 io = ::IO.respond_to?(:binread) ? ::IO.binread(file) : ::IO.read(file) 1276 app, data = io.gsub("\r\n", "\n").split(/^__END__$/, 2) 1277 rescue Errno::ENOENT 1278 app, data = nil 1279 end 1280 1281 if data 1282 if app and app =~ /([^\n]*\n)?#[^\n]*coding: *(\S+)/m 1283 encoding = $2 1284 else 1285 encoding = settings.default_encoding 1286 end 1287 lines = app.count("\n") + 1 1288 template = nil 1289 force_encoding data, encoding 1290 data.each_line do |line| 1291 lines += 1 1292 if line =~ /^@@\s*(.*\S)\s*$/ 1293 template = force_encoding('', encoding) 1294 templates[$1.to_sym] = [template, file, lines] 1295 elsif template 1296 template << line 1297 end 1298 end 1299 end 1300 end
# File lib/sinatra/base.rb 1582 def invoke_hook(name, *args) 1583 extensions.each { |e| e.send(name, *args) if e.respond_to?(name) } 1584 end
Define the layout template. The block must return the template source.
# File lib/sinatra/base.rb 1265 def layout(name = :layout, &block) 1266 template name, &block 1267 end
# File lib/sinatra/base.rb 1374 def link(path, opts = {}, &bk) route 'LINK', path, opts, &bk end
Middleware used in this class and all superclasses.
# File lib/sinatra/base.rb 1187 def middleware 1188 if superclass.respond_to?(:middleware) 1189 superclass.middleware + @middleware 1190 else 1191 @middleware 1192 end 1193 end
Lookup or register a mime type in Rack’s mime registry.
# File lib/sinatra/base.rb 1303 def mime_type(type, value = nil) 1304 return type if type.nil? 1305 return type.to_s if type.to_s.include?('/') 1306 type = ".#{type}" unless type.to_s[0] == ?. 1307 return Rack::Mime.mime_type(type, nil) unless value 1308 Rack::Mime::MIME_TYPES[type] = value 1309 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 1314 def mime_types(type) 1315 type = mime_type type 1316 type =~ /^application\/(xml|javascript)$/ ? [type, "text/#$1"] : [type] 1317 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 1462 def new(*args, &bk) 1463 instance = new!(*args, &bk) 1464 Wrapper.new(build(instance).to_app, instance) 1465 end
Sugar for ‘error(404) { … }`
# File lib/sinatra/base.rb 1253 def not_found(&block) 1254 error(404, &block) 1255 error(Sinatra::NotFound, &block) 1256 end
# File lib/sinatra/base.rb 1372 def options(path, opts = {}, &bk) route 'OPTIONS', path, opts, &bk end
# File lib/sinatra/base.rb 1373 def patch(path, opts = {}, &bk) route 'PATCH', path, opts, &bk end
# File lib/sinatra/base.rb 1369 def post(path, opts = {}, &bk) route 'POST', path, opts, &bk end
# File lib/sinatra/base.rb 1396 def production?; environment == :production end
The prototype instance used to process requests.
# File lib/sinatra/base.rb 1452 def prototype 1453 @prototype ||= new 1454 end
Condition for matching mimetypes. Accepts file extensions.
# File lib/sinatra/base.rb 1556 def provides(*types) 1557 types.map! { |t| mime_types(t) } 1558 types.flatten! 1559 condition do 1560 if type = response['Content-Type'] 1561 types.include? type or types.include? type[/^[^;]+/] 1562 elsif type = request.preferred_type(types) 1563 params = (type.respond_to?(:params) ? type.params : {}) 1564 content_type(type, params) 1565 true 1566 else 1567 false 1568 end 1569 end 1570 end
# File lib/sinatra/base.rb 1345 def public=(value) 1346 warn ":public is no longer used to avoid overloading Module#public, use :public_folder or :public_dir instead" 1347 set(:public_folder, value) 1348 end
# File lib/sinatra/base.rb 1354 def public_dir 1355 public_folder 1356 end
# File lib/sinatra/base.rb 1350 def public_dir=(value) 1351 self.public_folder = value 1352 end
# File lib/sinatra/base.rb 1368 def put(path, opts = {}, &bk) route 'PUT', path, opts, &bk end
Stop the self-hosted server if running.
# File lib/sinatra/base.rb 1412 def quit! 1413 return unless running? 1414 # Use Thin's hard #stop! if available, otherwise just #stop. 1415 running_server.respond_to?(:stop!) ? running_server.stop! : running_server.stop 1416 $stderr.puts "== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i 1417 set :running_server, nil 1418 set :handler_name, nil 1419 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 1386 def register(*extensions, &block) 1387 extensions << Module.new(&block) if block_given? 1388 @extensions += extensions 1389 extensions.each do |extension| 1390 extend extension 1391 extension.registered(self) if extension.respond_to?(:registered) 1392 end 1393 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 1161 def reset! 1162 @conditions = [] 1163 @routes = {} 1164 @filters = {:before => [], :after => []} 1165 @errors = {} 1166 @middleware = [] 1167 @prototype = nil 1168 @extensions = [] 1169 1170 if superclass.respond_to?(:templates) 1171 @templates = Hash.new { |hash,key| superclass.templates[key] } 1172 else 1173 @templates = {} 1174 end 1175 end
# File lib/sinatra/base.rb 1572 def route(verb, path, options = {}, &block) 1573 # Because of self.options.host 1574 host_name(options.delete(:host)) if options.key?(:host) 1575 enable :empty_path_info if path == "" and empty_path_info.nil? 1576 signature = compile!(verb, path, block, options) 1577 (@routes[verb] ||= []) << signature 1578 invoke_hook(:route_added, verb, path, block) 1579 signature 1580 end
Run the Sinatra
app as a self-hosted server using Thin, Puma, Mongrel, or WEBrick (in that order). If given a block, will call with the constructed handler once we have taken the stage.
# File lib/sinatra/base.rb 1426 def run!(options = {}, &block) 1427 return if running? 1428 set options 1429 handler = detect_rack_handler 1430 handler_name = handler.name.gsub(/.*::/, '') 1431 server_settings = settings.respond_to?(:server_settings) ? settings.server_settings : {} 1432 server_settings.merge!(:Port => port, :Host => bind) 1433 1434 begin 1435 start_server(handler, server_settings, handler_name, &block) 1436 rescue Errno::EADDRINUSE 1437 $stderr.puts "== Someone is already performing on port #{port}!" 1438 raise 1439 ensure 1440 quit! 1441 end 1442 end
Check whether the self-hosted server is running or not.
# File lib/sinatra/base.rb 1447 def running? 1448 running_server? 1449 end
# File lib/sinatra/base.rb 1686 def safe_ignore(ignore) 1687 unsafe_ignore = [] 1688 ignore = ignore.gsub(/%[\da-fA-F]{2}/) do |hex| 1689 unsafe_ignore << hex[1..2] 1690 '' 1691 end 1692 unsafe_patterns = unsafe_ignore.map! do |unsafe| 1693 chars = unsafe.split(//).map! do |char| 1694 if char =~ /[A-Z]/ 1695 char <<= char.tr('A-Z', 'a-z') 1696 end 1697 char 1698 end 1699 1700 "|(?:%[^#{chars[0]}].|%[#{chars[0]}][^#{chars[1]}])" 1701 end 1702 if unsafe_patterns.length > 0 1703 "((?:[^#{ignore}/?#%]#{unsafe_patterns.join()})+)" 1704 else 1705 "([^#{ignore}/?#]+)" 1706 end 1707 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 1197 def set(option, value = (not_set = true), ignore_setter = false, &block) 1198 raise ArgumentError if block and !not_set 1199 value, not_set = block, false if block 1200 1201 if not_set 1202 raise ArgumentError unless option.respond_to?(:each) 1203 option.each { |k,v| set(k, v) } 1204 return self 1205 end 1206 1207 if respond_to?("#{option}=") and not ignore_setter 1208 return __send__("#{option}=", value) 1209 end 1210 1211 setter = proc { |val| set option, val, true } 1212 getter = proc { value } 1213 1214 case value 1215 when Proc 1216 getter = value 1217 when Symbol, Fixnum, FalseClass, TrueClass, NilClass 1218 getter = value.inspect 1219 when Hash 1220 setter = proc do |val| 1221 val = value.merge val if Hash === val 1222 set option, val, true 1223 end 1224 end 1225 1226 define_singleton("#{option}=", setter) if setter 1227 define_singleton(option, getter) if getter 1228 define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?" 1229 self 1230 end
# File lib/sinatra/base.rb 1736 def setup_common_logger(builder) 1737 builder.use Sinatra::CommonLogger 1738 end
# File lib/sinatra/base.rb 1740 def setup_custom_logger(builder) 1741 if logging.respond_to? :to_int 1742 builder.use Rack::Logger, logging 1743 else 1744 builder.use Rack::Logger 1745 end 1746 end
# File lib/sinatra/base.rb 1709 def setup_default_middleware(builder) 1710 builder.use ExtendedRack 1711 builder.use ShowExceptions if show_exceptions? 1712 builder.use Rack::MethodOverride if method_override? 1713 builder.use Rack::Head 1714 setup_logging builder 1715 setup_sessions builder 1716 setup_protection builder 1717 end
# File lib/sinatra/base.rb 1723 def setup_logging(builder) 1724 if logging? 1725 setup_common_logger(builder) 1726 setup_custom_logger(builder) 1727 elsif logging == false 1728 setup_null_logger(builder) 1729 end 1730 end
# File lib/sinatra/base.rb 1719 def setup_middleware(builder) 1720 middleware.each { |c,a,b| builder.use(c, *a, &b) } 1721 end
# File lib/sinatra/base.rb 1732 def setup_null_logger(builder) 1733 builder.use Rack::NullLogger 1734 end
# File lib/sinatra/base.rb 1748 def setup_protection(builder) 1749 return unless protection? 1750 options = Hash === protection ? protection.dup : {} 1751 protect_session = options.fetch(:session) { sessions? } 1752 options[:except] = Array options[:except] 1753 options[:except] += [:session_hijacking, :remote_token] unless protect_session 1754 options[:reaction] ||= :drop_session 1755 builder.use Rack::Protection, options 1756 end
# File lib/sinatra/base.rb 1758 def setup_sessions(builder) 1759 return unless sessions? 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 Rack::Session::Cookie, options 1764 end
# File lib/sinatra/base.rb 1512 def setup_traps 1513 if traps? 1514 at_exit { quit! } 1515 1516 [:INT, :TERM].each do |signal| 1517 old_handler = trap(signal) do 1518 quit! 1519 old_handler.call if old_handler.respond_to?(:call) 1520 end 1521 end 1522 1523 set :traps, false 1524 end 1525 end
Starts the server by running the Rack
Handler.
# File lib/sinatra/base.rb 1496 def start_server(handler, server_settings, handler_name) 1497 handler.run(self, server_settings) do |server| 1498 unless handler_name =~ /cgi/i 1499 $stderr.puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " + 1500 "on #{port} for #{environment} with backup from #{handler_name}" 1501 end 1502 1503 setup_traps 1504 set :running_server, server 1505 set :handler_name, handler_name 1506 server.threaded = settings.threaded if server.respond_to? :threaded= 1507 1508 yield server if block_given? 1509 end 1510 end
# File lib/sinatra/base.rb 1784 def synchronize(&block) 1785 if lock? 1786 @@mutex.synchronize(&block) 1787 else 1788 yield 1789 end 1790 end
Define a named template. The block must return the template source.
# File lib/sinatra/base.rb 1259 def template(name, &block) 1260 filename, line = caller_locations.first 1261 templates[name] = [block, filename, line.to_i] 1262 end
# File lib/sinatra/base.rb 1397 def test?; environment == :test end
# File lib/sinatra/base.rb 1375 def unlink(path, opts = {}, &bk) route 'UNLINK', path, opts, &bk end
Use the specified Rack
middleware
# File lib/sinatra/base.rb 1406 def use(middleware, *args, &block) 1407 @prototype = nil 1408 @middleware << [middleware, args, block] 1409 end
Condition for matching user agent. Parameter should be Regexp. Will set params.
# File lib/sinatra/base.rb 1543 def user_agent(pattern) 1544 condition do 1545 if request.user_agent.to_s =~ pattern 1546 @params[:agent] = $~[1..-1] 1547 true 1548 else 1549 false 1550 end 1551 end 1552 end
used for deprecation warnings
# File lib/sinatra/base.rb 1793 def warn(message) 1794 super message + "\n\tfrom #{cleaned_caller.first.join(':')}" 1795 end
Public Instance Methods
Rack
call interface.
# File lib/sinatra/base.rb 885 def call(env) 886 dup.call!(env) 887 end
Forward the request to the downstream app – middleware only.
# File lib/sinatra/base.rb 943 def forward 944 fail "downstream app not set" unless @app.respond_to? :call 945 status, headers, body = @app.call env 946 @response.status = status 947 @response.body = body 948 @response.headers.merge! headers 949 nil 950 end
Exit the current block, halts any further processing of the request, and returns the specified response.
# File lib/sinatra/base.rb 930 def halt(*response) 931 response = response.first if response.length == 1 932 throw :halt, response 933 end
# File lib/sinatra/base.rb 922 def options 923 warn "Sinatra::Base#options is deprecated and will be removed, " \ 924 "use #settings instead." 925 settings 926 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 938 def pass(&block) 939 throw :pass, block 940 end
Access settings defined with Base.set
.
# File lib/sinatra/base.rb 918 def settings 919 self.class.settings 920 end
Private Instance Methods
Dispatch a request with error handling.
# File lib/sinatra/base.rb 1072 def dispatch! 1073 invoke do 1074 static! if settings.static? && (request.get? || request.head?) 1075 filter! :before 1076 route! 1077 end 1078 rescue ::Exception => boom 1079 invoke { handle_exception!(boom) } 1080 ensure 1081 begin 1082 filter! :after unless env['sinatra.static_file'] 1083 rescue ::Exception => boom 1084 invoke { handle_exception!(boom) } unless @env['sinatra.error'] 1085 end 1086 end
# File lib/sinatra/base.rb 1134 def dump_errors!(boom) 1135 msg = ["#{boom.class} - #{boom.message}:", *boom.backtrace].join("\n\t") 1136 @env['rack.errors'].puts(msg) 1137 end
Find an custom error block for the key(s) specified.
# File lib/sinatra/base.rb 1119 def error_block!(key, *block_params) 1120 base = settings 1121 while base.respond_to?(:errors) 1122 next base = base.superclass unless args_array = base.errors[key] 1123 args_array.reverse_each do |args| 1124 first = args == args_array.first 1125 args += [block_params] 1126 resp = process_route(*args) 1127 return resp unless resp.nil? && !first 1128 end 1129 end 1130 return false unless key.respond_to? :superclass and key.superclass < Exception 1131 error_block!(key.superclass, *block_params) 1132 end
Run filters defined on the class and all superclasses.
# File lib/sinatra/base.rb 955 def filter!(type, base = settings) 956 filter! type, base.superclass if base.superclass.respond_to?(:filters) 957 base.filters[type].each { |args| process_route(*args) } 958 end
Fixes encoding issues by
-
defaulting to UTF-8
-
casting params to Encoding.default_external
The latter might not be necessary if Rack
handles it one day. Keep an eye on Rack’s LH #100.
# File lib/sinatra/base.rb 1811 def force_encoding(*args) settings.force_encoding(*args) end
Error handling during requests.
# File lib/sinatra/base.rb 1089 def handle_exception!(boom) 1090 @env['sinatra.error'] = boom 1091 1092 if boom.respond_to? :http_status 1093 status(boom.http_status) 1094 elsif settings.use_code? and boom.respond_to? :code and boom.code.between? 400, 599 1095 status(boom.code) 1096 else 1097 status(500) 1098 end 1099 1100 status(500) unless status.between? 400, 599 1101 1102 if server_error? 1103 dump_errors! boom if settings.dump_errors? 1104 raise boom if settings.show_exceptions? and settings.show_exceptions != :after_handler 1105 end 1106 1107 if not_found? 1108 headers['X-Cascade'] = 'pass' if settings.x_cascade? 1109 body '<h1>Not Found</h1>' 1110 end 1111 1112 res = error_block!(boom.class, boom) || error_block!(status, boom) 1113 return res if res or not server_error? 1114 raise boom if settings.raise_errors? or settings.show_exceptions? 1115 error_block! Exception, boom 1116 end
Creates a Hash with indifferent access.
# File lib/sinatra/base.rb 1052 def indifferent_hash 1053 Hash.new {|hash,key| hash[key.to_s] if Symbol === key } 1054 end
Enable string or symbol key access to the nested params hash.
# File lib/sinatra/base.rb 1038 def indifferent_params(object) 1039 case object 1040 when Hash 1041 new_hash = indifferent_hash 1042 object.each { |key, value| new_hash[key] = indifferent_params(value) } 1043 new_hash 1044 when Array 1045 object.map { |item| indifferent_params(item) } 1046 else 1047 object 1048 end 1049 end
Run the block with ‘throw :halt’ support and apply result to the response.
# File lib/sinatra/base.rb 1057 def invoke 1058 res = catch(:halt) { yield } 1059 res = [res] if Fixnum === res or String === res 1060 if Array === res and Fixnum === res.first 1061 res = res.dup 1062 status(res.shift) 1063 body(res.pop) 1064 headers(*res) 1065 elsif res.respond_to? :each 1066 body res 1067 end 1068 nil # avoid double setting the same response tuple twice 1069 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 993 def process_route(pattern, keys, conditions, block = nil, values = []) 994 route = @request.path_info 995 route = '/' if route.empty? and not settings.empty_path_info? 996 return unless match = pattern.match(route) 997 values += match.captures.map! { |v| force_encoding URI_INSTANCE.unescape(v) if v } 998 999 if values.any? 1000 original, @params = params, params.merge('splat' => [], 'captures' => values) 1001 keys.zip(values) { |k,v| Array === @params[k] ? @params[k] << v : @params[k] = v if v } 1002 end 1003 1004 catch(:pass) do 1005 conditions.each { |c| throw :pass if c.bind(self).call == false } 1006 block ? block[self, values] : yield(self, values) 1007 end 1008 ensure 1009 @params = original if original 1010 end
Run routes defined on the class and all superclasses.
# File lib/sinatra/base.rb 961 def route!(base = settings, pass_block = nil) 962 if routes = base.routes[@request.request_method] 963 routes.each do |pattern, keys, conditions, block| 964 returned_pass_block = process_route(pattern, keys, conditions) do |*args| 965 env['sinatra.route'] = block.instance_variable_get(:@route_name) 966 route_eval { block[*args] } 967 end 968 969 # don't wipe out pass_block in superclass 970 pass_block = returned_pass_block if returned_pass_block 971 end 972 end 973 974 # Run routes defined in superclass. 975 if base.superclass.respond_to?(:routes) 976 return route!(base.superclass, pass_block) 977 end 978 979 route_eval(&pass_block) if pass_block 980 route_missing 981 end
Run a route block and throw :halt with the result.
# File lib/sinatra/base.rb 984 def route_eval 985 throw :halt, yield 986 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 1017 def route_missing 1018 if @app 1019 forward 1020 else 1021 raise NotFound 1022 end 1023 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 1027 def static!(options = {}) 1028 return if (public_dir = settings.public_folder).nil? 1029 path = File.expand_path("#{public_dir}#{unescape(request.path_info)}" ) 1030 return unless File.file?(path) 1031 1032 env['sinatra.static_file'] = path 1033 cache_control(*settings.static_cache_control) if settings.static_cache_control? 1034 send_file path, options.merge(:disposition => nil) 1035 end