Class: Sinatra::Base
Relationships & Source Files | |
Extension / Inclusion / Inheritance Descendants | |
Subclasses:
|
|
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
|
|
Inherits: | Object |
Defined in: | lib/sinatra/base.rb |
Overview
Base
class for all ::Sinatra
applications and middleware.
Constant Summary
-
CALLERS_TO_IGNORE =
Internal use only
# File 'lib/sinatra/base.rb', line 1289[ # :nodoc: %r{/sinatra(/(base|main|show_exceptions))?\.rb$}, # all sinatra code %r{lib/tilt.*\.rb$}, # all tilt code /^\(.*\)$/, # generated code /\/bundled_gems.rb$/, # ruby >= 3.3 with bundler >= 2.5 %r{rubygems/(custom|core_ext/kernel)_require\.rb$}, # rubygems require hacks /active_support/, # active_support require hacks %r{bundler(/(?:runtime|inline))?\.rb}, # bundler require hacks /<internal:/, # internal in ruby >= 1.9.2 %r{zeitwerk/(core_ext/)?kernel\.rb} # Zeitwerk kernel#require decorator ].freeze
-
URI_INSTANCE =
# File 'lib/sinatra/base.rb', line 978defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::RFC2396_Parser.new
Helpers
- Included
Class Attribute Summary
- .development? ⇒ Boolean readonly
- .errors readonly
- .filters readonly
- .on_start_callback readonly
- .on_stop_callback readonly
- .production? ⇒ Boolean readonly
- .public=(value) writeonly
- .public_dir rw
- .public_dir=(value) rw
- .routes readonly
-
.running? ⇒ Boolean
readonly
Check whether the self-hosted server is running or not.
- .templates readonly
- .test? ⇒ Boolean readonly
- .suppress_messages? ⇒ Boolean readonly private
Class Method Summary
-
.add_filter(type, path = /.*/, **options, &block)
add a filter.
-
.after(path = /.*/, **options, &block)
Define an after filter; runs after all requests within the same context as route handlers and may access/modify the request and response.
-
.before(path = /.*/, **options, &block)
Define a before filter; runs before all requests within the same context as route handlers and may access/modify the request and response.
-
.build(app)
Creates a
::Rack::Builder
instance with all the middleware set up and the given #app as end point. - .call(env)
-
.caller_files
Like Kernel#caller but excluding certain magic entries and without line / method information; the resulting array contains filenames only.
- .callers_to_ignore
-
.condition(name = "#{caller.first[/`.*'/]} condition", &block)
Add a route condition.
-
.configure(*envs) {|_self| ... }
Set configuration options for
::Sinatra
and/or the app. - .delete(path, opts = {}, &block)
-
.disable(*opts)
Same as calling
set <code>:option</code>, false
for each of the given options. -
.enable(*opts)
Same as calling
set <code>:option</code>, true
for each of the given options. -
.error(*codes, &block)
Define a custom error handler.
-
.extensions
Extension
modules registered on this class and all superclasses. -
.get(path, opts = {}, &block)
Defining a
GET
handler also automatically defines aHEAD
handler. - .head(path, opts = {}, &block)
-
.helpers(*extensions, &block)
Makes the methods defined in the block and in the Modules given in .extensions available to the handlers and templates.
-
.inline_templates=(file = nil)
Load embedded templates from the file; uses the caller's FILE when no file is specified.
-
.layout(name = :layout, &block)
Define the layout template.
- .link(path, opts = {}, &block)
- .methodoverride=
- .methodoverride?
-
.middleware
Middleware
used in this class and all superclasses. -
.mime_type(type, value = nil)
Lookup or register a mime type in Rack's mime registry.
-
.mime_types(type)
provides all mime types matching type, including deprecated types:
-
.new(*args, &block) ⇒ Base
(also: .new!, .new!)
constructor
Create a new instance of the class fronted by its middleware pipeline.
-
.new!(app = nil, **_kwargs)
Alias for .new.
-
.not_found(&block)
Sugar for `error(404) { ...
- .on_start(&on_start_callback)
- .on_stop(&on_stop_callback)
- .options(path, opts = {}, &block)
- .patch(path, opts = {}, &block)
- .post(path, opts = {}, &block)
-
.prototype
The prototype instance used to process requests.
- .put(path, opts = {}, &block)
-
.quit!
(also: .stop!)
Stop the self-hosted server if running.
-
.register(*extensions, &block)
Register an extension.
-
.reset!
Removes all routes, filters, middleware and extension hooks from the current class (not routes/filters/...
-
.run!(options = {}, &block)
(also: .start!)
Run the
::Sinatra
app as a self-hosted server using Puma, Falcon (in that order). -
.set(option, value = (not_set = true), ignore_setter = false, &block)
Sets an option to the given value.
-
.settings
Access settings defined with
Base
.set. -
.start!(options = {}, &block)
Alias for .run!.
-
.stop!
Alias for .quit!.
-
.template(name, &block)
Define a named template.
- .unlink(path, opts = {}, &block)
-
.use(middleware, *args, &block)
Use the specified
::Rack
middleware. -
.agent(pattern)
private
Alias for .user_agent.
-
.cleaned_caller(keep = 3)
private
Like Kernel#caller but excluding certain magic entries.
- .compile(path, route_mustermann_opts = {}) private
- .compile!(verb, path, block, **options) private
-
.define_singleton(name, content = Proc.new)
private
Dynamically defines a method on settings.
-
.force_encoding(data, encoding = default_encoding)
private
Force data to specified encoding.
- .generate_method(method_name, &block) private
-
.host_name(pattern)
private
Condition for matching host name.
- .inherited(subclass) private
- .invoke_hook(name, *args) private
-
.provides(*types)
private
Condition for matching mimetypes.
- .route(verb, path, options = {}, &block) private
- .setup_common_logger(builder) private
- .setup_custom_logger(builder) private
- .setup_default_middleware(builder) private
- .setup_host_authorization(builder) private
- .setup_logging(builder) private
- .setup_middleware(builder) private
- .setup_null_logger(builder) private
- .setup_protection(builder) private
- .setup_sessions(builder) private
- .setup_traps private
-
.start_server(handler, server_settings, handler_name)
private
Starts the server by running the
::Rack
Handler. - .synchronize(&block) private
-
.user_agent(pattern)
(also: .agent)
private
Condition for matching user agent.
-
.warn_for_deprecation(message)
private
used for deprecation warnings.
Instance Attribute Summary
Helpers
- Included
#bad_request? | whether or not the status is set to 400. |
#client_error? | whether or not the status is set to 4xx. |
#informational? | whether or not the status is set to 1xx. |
#not_found? | whether or not the status is set to 404. |
#redirect? | whether or not the status is set to 3xx. |
#server_error? | whether or not the status is set to 5xx. |
#success? | whether or not the status is set to 2xx. |
Instance Method Summary
-
#call(env)
::Rack
call interface. - #call!(env) Internal use only
-
#forward
Forward the request to the downstream app -- middleware only.
-
#halt(*response)
Exit the current block, halts any further processing of the request, and returns the specified response.
-
#pass(&block)
Pass control to the next matching route.
-
#settings
Access settings defined with
Base
.set. -
#dispatch!
private
Dispatch a request with error handling.
- #dump_errors!(boom) private
-
#error_block!(key, *block_params)
private
Find an custom error block for the key(s) specified.
-
#filter!(type, base = settings, &block)
private
Run filters defined on the class and all superclasses.
- #force_encoding(*args) private
-
#handle_exception!(boom)
private
Error
handling during requests. -
#invoke(&block)
private
Run the block with 'throw :halt' support and apply result to the response.
-
#process_route(pattern, conditions, block = nil, values = [])
private
If the current request matches pattern and conditions, fill params with keys and call the given block.
-
#route!(base = settings, pass_block = nil)
private
Run routes defined on the class and all superclasses.
-
#route_eval
private
Run a route block and throw
:halt
with the result. -
#route_missing
private
No matching route was found or all routes passed.
-
#static!(options = {})
private
Attempt to serve static files from public directory.
Templates
- Included
#asciidoc, #builder, #erb, | |
#find_template | Calls the given block for every possible template file in views, named name.ext, where ext is registered on engine. |
#haml, #initialize, #liquid, #markaby, #markdown, #nokogiri, #rabl, #rdoc, #sass, #scss, #slim, #yajl, #compile_block_template, #compile_template, #render, | |
#render_ruby | logic shared between builder and nokogiri. |
Helpers
- Included
#attachment | Set the Content-Disposition to "attachment" with the specified filename, instructing the user agents to prompt to save. |
#back | Sugar for redirect (example: redirect back). |
#body | Set or retrieve the response body. |
#cache_control | Specify response freshness policy for HTTP caches (Cache-Control header). |
#content_type | Set the content-type of the response body given a media type or file extension. |
#error | Halt processing and return the error status provided. |
#etag | Set the response entity tag (HTTP 'ETag' header) and halt if conditional GET matches. |
#expires | Set the Expires header and Cache-Control/max-age directive. |
#headers | Set multiple response headers with Hash. |
#last_modified | Set the last modified time of the resource (HTTP 'Last-Modified' header) and halt if conditional GET matches. |
#logger | Access shared logger object. |
#mime_type | Look up a media type by file extension in Rack's mime registry. |
#not_found | Halt processing and return a 404 Not Found. |
#redirect | Halt processing and redirect to the URI provided. |
#send_file | Use the contents of the file at |
#session | Access the underlying |
#status | Set or retrieve the response status code. |
#stream | Allows to start sending data to the client even though later parts of the response body have not yet been generated. |
#time_for | Generates a Time object from the given value. |
#to | Alias for Helpers#uri. |
#uri | Generates the absolute URI for a given path in the app. |
#url | Alias for Helpers#uri. |
#etag_matches? | Helper method checking if a ETag value list includes the current ETag. |
#with_params |
Constructor Details
.new(*args, &block) ⇒ Base
Also known as: .new!, .new!
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', line 1660
def initialize(app = nil, **_kwargs) super() @app = app @template_cache = TemplateCache.new @pinned_response = nil # whether a before! filter pinned the content-type yield self if block_given? end
Class Attribute Details
.development? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'lib/sinatra/base.rb', line 1571
def development?; environment == :development end
.errors (readonly)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1301
attr_reader :routes, :filters, :templates, :errors, :on_start_callback, :on_stop_callback
.filters (readonly)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1301
attr_reader :routes, :filters, :templates, :errors, :on_start_callback, :on_stop_callback
.on_start_callback (readonly)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1301
attr_reader :routes, :filters, :templates, :errors, :on_start_callback, :on_stop_callback
.on_stop_callback (readonly)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1301
attr_reader :routes, :filters, :templates, :errors, :on_start_callback, :on_stop_callback
.production? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'lib/sinatra/base.rb', line 1572
def production?; environment == :production end
.public=(value) (writeonly)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1514
def public=(value) warn_for_deprecation ':public is no longer used to avoid overloading Module#public, use :public_folder or :public_dir instead' set(:public_folder, value) end
.public_dir (rw)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1523
def public_dir public_folder end
.public_dir=(value) (rw)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1519
def public_dir=(value) self.public_folder = value end
.routes (readonly)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1301
attr_reader :routes, :filters, :templates, :errors, :on_start_callback, :on_stop_callback
.running? ⇒ Boolean
(readonly)
Check whether the self-hosted server is running or not.
# File 'lib/sinatra/base.rb', line 1645
def running? running_server? end
.suppress_messages? ⇒ Boolean
(readonly, private)
[ GitHub ]
# File 'lib/sinatra/base.rb', line 1708
def handler_name =~ /cgi/i || quiet end
.templates (readonly)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1301
attr_reader :routes, :filters, :templates, :errors, :on_start_callback, :on_stop_callback
.test? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'lib/sinatra/base.rb', line 1573
def test?; environment == :test end
Class Method Details
.add_filter(type, path = /.*/, **options, &block)
add a filter
.after(path = /.*/, **options, &block)
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', line 1491
def after(path = /.*/, **, &block) add_filter(:after, path, **, &block) end
.agent(pattern) (private)
Alias for .user_agent.
# File 'lib/sinatra/base.rb', line 1752
alias agent user_agent
.before(path = /.*/, **options, &block)
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', line 1484
def before(path = /.*/, **, &block) add_filter(:before, path, **, &block) end
.build(app)
Creates a ::Rack::Builder
instance with all the middleware set up and
the given #app as end point.
# File 'lib/sinatra/base.rb', line 1668
def build(app) builder = Rack::Builder.new setup_default_middleware builder setup_middleware builder builder.run app builder end
.call(env)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1676
def call(env) synchronize { prototype.call(env) } end
.caller_files
Like Kernel#caller but excluding certain magic entries and without line / method information; the resulting array contains filenames only.
# File 'lib/sinatra/base.rb', line 1682
def caller_files cleaned_caller(1).flatten end
.callers_to_ignore
[ GitHub ]# File 'lib/sinatra/base.rb', line 1303
def callers_to_ignore CALLERS_TO_IGNORE end
.cleaned_caller(keep = 3) (private)
Like Kernel#caller but excluding certain magic entries
# File 'lib/sinatra/base.rb', line 1908
def cleaned_caller(keep = 3) caller(1) .map! { |line| line.split(/:(?=\d|in )/, 3)[0, keep] } .reject { |file, *_| callers_to_ignore.any? { |pattern| file =~ pattern } } end
.compile(path, route_mustermann_opts = {}) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1813
def compile(path, route_mustermann_opts = {}) Mustermann.new(path, **mustermann_opts.merge(route_mustermann_opts)) end
.compile!(verb, path, block, **options) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1793
def compile!(verb, path, block, ** ) # Because of self.options.host host_name( .delete(:host)) if .key?(:host) # Pass Mustermann opts to compile() route_mustermann_opts = .key?(:mustermann_opts) ? .delete(:mustermann_opts) : {}.freeze .each_pair { |option, args| send(option, *args) } pattern = compile(path, route_mustermann_opts) method_name = "#{verb} #{path}" unbound_method = generate_method(method_name, &block) conditions = @conditions @conditions = [] wrapper = block.arity.zero? ? proc { |a, _p| unbound_method.bind(a).call } : proc { |a, p| unbound_method.bind(a).call(*p) } [pattern, conditions, wrapper] end
.condition(name = "#{caller.first[/`.*'/]} condition", &block)
Add a route condition. The route is considered non-matching when the block returns false.
# File 'lib/sinatra/base.rb', line 1510
def condition(name = "#{caller.first[/`.*'/]} condition", &block) @conditions << generate_method(name, &block) end
.configure(*envs) {|_self| ... }
Set configuration options for ::Sinatra
and/or the app.
Allows scoping of settings for certain environments.
# File 'lib/sinatra/base.rb', line 1577
def configure(*envs) yield self if envs.empty? || envs.include?(environment.to_sym) end
.define_singleton(name, content = Proc.new) (private)
Dynamically defines a method on settings.
# File 'lib/sinatra/base.rb', line 1728
def define_singleton(name, content = Proc.new) singleton_class.class_eval do undef_method(name) if method_defined? name String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content) end end
.delete(path, opts = {}, &block)
[ GitHub ].disable(*opts)
Same as calling set <code>:option</code>, false
for each of the given options.
.enable(*opts)
Same as calling set <code>:option</code>, true
for each of the given options.
.error(*codes, &block)
Define a custom error handler. Optionally takes either an Exception class, or an HTTP status code to specify which errors should be handled.
.extensions
Extension
modules registered on this class and all superclasses.
# File 'lib/sinatra/base.rb', line 1326
def extensions if superclass.respond_to?(:extensions) (@extensions + superclass.extensions).uniq else @extensions end end
.force_encoding(data, encoding = default_encoding) (private)
Force data to specified encoding. It defaults to settings.default_encoding which is UTF-8 by default
# File 'lib/sinatra/base.rb', line 1917
def self.force_encoding(data, encoding = default_encoding) return if data == settings || data.is_a?(Tempfile) if data.respond_to? :force_encoding data.force_encoding(encoding).encode! elsif data.respond_to? :each_value data.each_value { |v| force_encoding(v, encoding) } elsif data.respond_to? :each data.each { |v| force_encoding(v, encoding) } end data end
.generate_method(method_name, &block) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1786
def generate_method(method_name, &block) define_method(method_name, &block) method = instance_method method_name remove_method method_name method end
.get(path, opts = {}, &block)
Defining a GET
handler also automatically defines
a HEAD
handler.
.head(path, opts = {}, &block)
[ GitHub ].helpers(*extensions, &block)
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', line 1555
def helpers(*extensions, &block) class_eval(&block) if block_given? include(*extensions) if extensions.any? end
.host_name(pattern) (private)
Condition for matching host name. Parameter might be String or Regexp.
.inherited(subclass) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1887
def inherited(subclass) subclass.reset! subclass.set :app_file, caller_files.first unless subclass.app_file? super end
.inline_templates=(file = nil)
Load embedded templates from the file; uses the caller's FILE when no file is specified.
# File 'lib/sinatra/base.rb', line 1424
def inline_templates=(file = nil) file = (caller_files.first || File. ($0)) if file.nil? || file == true begin io = ::IO.respond_to?(:binread) ? ::IO.binread(file) : ::IO.read(file) app, data = io.gsub("\r\n", "\n").split(/^__END__$/, 2) rescue Errno::ENOENT app, data = nil end return unless data encoding = if app && app =~ /([^\n]*\n)?#[^\n]*coding: *(\S+)/m $2 else settings.default_encoding end lines = app.count("\n") + 1 template = nil force_encoding data, encoding data.each_line do |line| lines += 1 if line =~ /^@@\s*(.*\S)\s*$/ template = force_encoding(String.new, encoding) templates[$1.to_sym] = [template, file, lines] elsif template template << line end end end
.invoke_hook(name, *args) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1782
def invoke_hook(name, *args) extensions.each { |e| e.send(name, *args) if e.respond_to?(name) } end
.layout(name = :layout, &block)
Define the layout template. The block must return the template source.
.link(path, opts = {}, &block)
[ GitHub ].methodoverride=
[ GitHub ]# File 'lib/sinatra/base.rb', line 1965
alias methodoverride= method_override=
.methodoverride?
[ GitHub ]# File 'lib/sinatra/base.rb', line 1964
alias methodoverride? method_override?
.middleware
Middleware
used in this class and all superclasses.
# File 'lib/sinatra/base.rb', line 1335
def middleware if superclass.respond_to?(:middleware) superclass.middleware + @middleware else @middleware end end
.mime_type(type, value = nil)
Lookup or register a mime type in Rack's mime registry.
.mime_types(type)
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', line 1470
def mime_types(type) type = mime_type type if type =~ %r{^application/(xml|javascript)$} [type, "text/#{$1}"] elsif type =~ %r{^text/(xml|javascript)$} [type, "application/#{$1}"] else [type] end end
.new!(app = nil, **_kwargs)
Alias for .new.
# File 'lib/sinatra/base.rb', line 1655
alias new! new unless method_defined? :new!
.not_found(&block)
Sugar for error(404) { ... }
.on_start(&on_start_callback)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1500
def on_start(&on_start_callback) @on_start_callback = on_start_callback end
.on_stop(&on_stop_callback)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1504
def on_stop(&on_stop_callback) @on_stop_callback = on_stop_callback end
.options(path, opts = {}, &block)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1545
def (path, opts = {}, &block) route 'OPTIONS', path, opts, &block end
.patch(path, opts = {}, &block)
[ GitHub ].post(path, opts = {}, &block)
[ GitHub ].prototype
The prototype instance used to process requests.
# File 'lib/sinatra/base.rb', line 1650
def prototype @prototype ||= new end
.provides(*types) (private)
Condition for matching mimetypes. Accepts file extensions.
# File 'lib/sinatra/base.rb', line 1755
def provides(*types) types.map! { |t| mime_types(t) } types.flatten! condition do response_content_type = response['content-type'] preferred_type = request.preferred_type(types) if response_content_type types.include?(response_content_type) || types.include?(response_content_type[/^[^;]+/]) elsif preferred_type params = (preferred_type.respond_to?(:params) ? preferred_type.params : {}) content_type(preferred_type, params) true else false end end end
.put(path, opts = {}, &block)
[ GitHub ].quit! Also known as: .stop!
Stop the self-hosted server if running.
# File 'lib/sinatra/base.rb', line 1589
def quit! return unless running? # Use Thin's hard #stop! if available, otherwise just #stop. running_server.respond_to?(:stop!) ? running_server.stop! : running_server.stop warn '== Sinatra has ended his set (crowd applauds)' unless set :running_server, nil set :handler_name, nil on_stop_callback.call unless on_stop_callback.nil? end
.register(*extensions, &block)
Register an extension. Alternatively take a block from which an extension will be created and registered on the fly.
# File 'lib/sinatra/base.rb', line 1562
def register(*extensions, &block) extensions << Module.new(&block) if block_given? @extensions += extensions extensions.each do |extension| extend extension extension.registered(self) if extension.respond_to?(:registered) end end
.reset!
Removes all routes, filters, middleware and extension hooks from the current class (not routes/filters/... defined by its superclass).
# File 'lib/sinatra/base.rb', line 1309
def reset! @conditions = [] @routes = {} @filters = { before: [], after: [] } @errors = {} @middleware = [] @prototype = nil @extensions = [] @templates = if superclass.respond_to?(:templates) Hash.new { |_hash, key| superclass.templates[key] } else {} end end
.route(verb, path, options = {}, &block) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1774
def route(verb, path, = {}, &block) enable :empty_path_info if path == '' && empty_path_info.nil? signature = compile!(verb, path, block, ** ) (@routes[verb] ||= []) << signature invoke_hook(:route_added, verb, path, block) signature end
.run!(options = {}, &block) Also known as: .start!
Run the ::Sinatra
app as a self-hosted server using
Puma, Falcon (in that order). If given a block, will call
with the constructed handler once we have taken the stage.
# File 'lib/sinatra/base.rb', line 1606
def run!( = {}, &block) unless defined?(Rackup::Handler) rackup_warning = <<~MISSING_RACKUP Sinatra could not start, the required gems weren't found! Add them to your bundle with: bundle add rackup puma or install them with: gem install rackup puma MISSING_RACKUP warn rackup_warning exit 1 end return if running? set handler = Rackup::Handler.pick(server) handler_name = handler.name.gsub(/.*::/, '') server_settings = settings.respond_to?(:server_settings) ? settings.server_settings : {} server_settings.merge!(Port: port, Host: bind) begin start_server(handler, server_settings, handler_name, &block) rescue Errno::EADDRINUSE warn "== Someone is already performing on port #{port}!" raise ensure quit! end end
.set(option, value = (not_set = true), ignore_setter = false, &block)
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', line 1345
def set(option, value = (not_set = true), ignore_setter = false, &block) raise ArgumentError if block && !not_set if block value = block not_set = false end if not_set raise ArgumentError unless option.respond_to?(:each) option.each { |k, v| set(k, v) } return self end if respond_to?("#{option}=") && !ignore_setter return __send__("#{option}=", value) end setter = proc { |val| set option, val, true } getter = proc { value } case value when Proc getter = value when Symbol, Integer, FalseClass, TrueClass, NilClass getter = value.inspect when Hash setter = proc do |val| val = value.merge val if Hash === val set option, val, true end end define_singleton("#{option}=", setter) define_singleton(option, getter) define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?" self end
.settings
Access settings defined with Base
.set.
# File 'lib/sinatra/base.rb', line 1019
def self.settings self end
.setup_common_logger(builder) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1845
def setup_common_logger(builder) builder.use Sinatra::CommonLogger end
.setup_custom_logger(builder) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1849
def setup_custom_logger(builder) if logging.respond_to? :to_int builder.use Sinatra::Middleware::Logger, logging else builder.use Sinatra::Middleware::Logger end end
.setup_default_middleware(builder) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1817
def setup_default_middleware(builder) builder.use ExtendedRack builder.use ShowExceptions if show_exceptions? builder.use Rack::MethodOverride if method_override? builder.use Rack::Head setup_logging builder setup_sessions builder setup_protection builder builder end
.setup_host_authorization(builder) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1874
def (builder) builder.use Rack::Protection::HostAuthorization, end
.setup_logging(builder) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1832
def setup_logging(builder) if logging? setup_common_logger(builder) setup_custom_logger(builder) elsif logging == false setup_null_logger(builder) end end
.setup_middleware(builder) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1828
def setup_middleware(builder) middleware.each { |c, a, b| builder.use(c, *a, &b) } end
.setup_null_logger(builder) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1841
def setup_null_logger(builder) builder.use Sinatra::Middleware::Logger, ::Logger::FATAL end
.setup_protection(builder) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1857
def setup_protection(builder) return unless protection? = Hash === protection ? protection.dup : {} = { img_src: "'self' data:", font_src: "'self'" }.merge protect_session = .fetch(:session) { sessions? } [:without_session] = !protect_session [:reaction] ||= :drop_session builder.use Rack::Protection, end
.setup_sessions(builder) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1878
def setup_sessions(builder) return unless sessions? = {} [:secret] = session_secret if session_secret? .merge! sessions.to_hash if sessions.respond_to? :to_hash builder.use session_store, end
.setup_traps (private)
[ GitHub ].start!(options = {}, &block)
Alias for .run!.
# File 'lib/sinatra/base.rb', line 1642
alias start! run!
.start_server(handler, server_settings, handler_name) (private)
Starts the server by running the ::Rack
Handler.
# File 'lib/sinatra/base.rb', line 1689
def start_server(handler, server_settings, handler_name) # Ensure we initialize middleware before startup, to match standard Rack # behavior, by ensuring an instance exists: prototype # Run the instance we created: handler.run(self, **server_settings) do |server| unless warn "== Sinatra (v#{Sinatra::VERSION}) has taken the stage on #{port} for #{environment} with backup from #{handler_name}" end setup_traps set :running_server, server set :handler_name, handler_name server.threaded = settings.threaded if server.respond_to? :threaded= on_start_callback.call unless on_start_callback.nil? yield server if block_given? end end
.stop!
Alias for .quit!.
# File 'lib/sinatra/base.rb', line 1601
alias stop! quit!
.synchronize(&block) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1894
def synchronize(&block) if lock? @@mutex.synchronize(&block) else yield end end
.template(name, &block)
Define a named template. The block must return the template source.
.unlink(path, opts = {}, &block)
[ GitHub ].use(middleware, *args, &block)
Use the specified ::Rack
middleware
# File 'lib/sinatra/base.rb', line 1582
def use(middleware, *args, &block) @prototype = nil @middleware << [middleware, args, block] end
.user_agent(pattern) (private) Also known as: .agent
Condition for matching user agent. Parameter should be Regexp. Will set params[:agent].
.warn_for_deprecation(message) (private)
used for deprecation warnings
# File 'lib/sinatra/base.rb', line 1903
def warn_for_deprecation( ) warn + "\n\tfrom #{cleaned_caller.first.join(':')}" end
Instance Attribute Details
#app (rw)
[ GitHub ]#env (rw)
[ GitHub ]#params (rw)
[ GitHub ]#request (rw)
[ GitHub ]#response (rw)
[ GitHub ]#template_cache (readonly)
[ GitHub ]# File 'lib/sinatra/base.rb', line 981
attr_reader :template_cache
Instance Method Details
#call(env)
::Rack
call interface.
#call!(env)
# File 'lib/sinatra/base.rb', line 996
def call!(env) # :nodoc: @env = env @params = IndifferentHash.new @request = Request.new(env) @response = Response.new @pinned_response = nil template_cache.clear if settings.reload_templates invoke { dispatch! } invoke { error_block!(response.status) } unless @env['sinatra.error'] unless @response['content-type'] if Array === body && body[0].respond_to?(:content_type) content_type body[0].content_type elsif (default = settings.default_content_type) content_type default end end @response.finish end
#dispatch! (private)
Dispatch a request with error handling.
# File 'lib/sinatra/base.rb', line 1179
def dispatch! # Avoid passing frozen string in force_encoding @params.merge!(@request.params).each do |key, val| next unless val.respond_to?(:force_encoding) val = val.dup if val.frozen? @params[key] = force_encoding(val) end invoke do static! if settings.static? && (request.get? || request.head?) filter! :before do @pinned_response = !response['content-type'].nil? end route! end rescue ::Exception => e invoke { handle_exception!(e) } ensure begin filter! :after unless env['sinatra.static_file'] rescue ::Exception => e invoke { handle_exception!(e) } unless @env['sinatra.error'] end end
#dump_errors!(boom) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1271
def dump_errors!(boom) if boom.respond_to?(: ) msg = boom. (highlight: false) if msg =~ /\A(.*?)(?: \(#{ Regexp.quote(boom.class.to_s) }\))?\n/ msg = $1 additional_msg = $'.lines(chomp: true) else additional_msg = [] end else msg = boom. additional_msg = [] end msg = ["#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - #{boom.class} - #{msg}:", *additional_msg, *boom.backtrace].join("\n\t") @env['rack.errors'].puts(msg) end
#error_block!(key, *block_params) (private)
Find an custom error block for the key(s) specified.
# File 'lib/sinatra/base.rb', line 1252
def error_block!(key, *block_params) base = settings while base.respond_to?(:errors) args_array = base.errors[key] next base = base.superclass unless args_array args_array.reverse_each do |args| first = args == args_array.first args += [block_params] resp = process_route(*args) return resp unless resp.nil? && !first end end return false unless key.respond_to?(:superclass) && (key.superclass < Exception) error_block!(key.superclass, *block_params) end
#filter!(type, base = settings, &block) (private)
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', line 1057
def filter!(type, base = settings, &block) filter!(type, base.superclass, &block) if base.superclass.respond_to?(:filters) base.filters[type].each do |args| result = process_route(*args) block.call(result) if block_given? end end
#force_encoding(*args) (private)
[ GitHub ]# File 'lib/sinatra/base.rb', line 1930
def force_encoding(*args) settings.force_encoding(*args) end
#forward
Forward the request to the downstream app -- middleware only.
#halt(*response)
Exit the current block, halts any further processing of the request, and returns the specified response.
#handle_exception!(boom) (private)
Error
handling during requests.
# File 'lib/sinatra/base.rb', line 1206
def handle_exception!(boom) error_params = @env['sinatra.error.params'] @params = @params.merge(error_params) if error_params @env['sinatra.error'] = boom http_status = if boom.is_a? Sinatra::Error if boom.respond_to? :http_status boom.http_status elsif settings.use_code? && boom.respond_to?(:code) boom.code end end http_status = 500 unless http_status&.between?(400, 599) status(http_status) if server_error? dump_errors! boom if settings.dump_errors? raise boom if settings.show_exceptions? && (settings.show_exceptions != :after_handler) elsif not_found? headers['X-Cascade'] = 'pass' if settings.x_cascade? end if (res = error_block!(boom.class, boom) || error_block!(status, boom)) return res end if not_found? || bad_request? if boom. && boom. != boom.class.name body Rack::Utils.escape_html(boom. ) else content_type 'text/html' body "<h1>#{not_found? ? 'Not Found' : 'Bad Request'}</h1>" end end return unless server_error? raise boom if settings.raise_errors? || settings.show_exceptions? error_block! Exception, boom end
#invoke(&block) (private)
Run the block with 'throw :halt' support and apply result to the response.
# File 'lib/sinatra/base.rb', line 1163
def invoke(&block) res = catch(:halt, &block) res = [res] if (Integer === res) || (String === res) if (Array === res) && (Integer === res.first) res = res.dup status(res.shift) body(res.pop) headers(*res) elsif res.respond_to? :each body res end nil # avoid double setting the same response tuple twice end
#pass(&block)
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', line 1038
def pass(&block) throw :pass, block end
#process_route(pattern, conditions, block = nil, values = []) (private)
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', line 1100
def process_route(pattern, conditions, block = nil, values = []) route = @request.path_info route = '/' if route.empty? && !settings.empty_path_info? route = route[0..-2] if !settings.strict_paths? && route != '/' && route.end_with?('/') params = pattern.params(route) return unless params params.delete('ignore') # TODO: better params handling, maybe turn it into "smart" object or detect changes force_encoding(params) @params = @params.merge(params) { |_k, v1, v2| v2 || v1 } if params.any? regexp_exists = pattern.is_a?(Mustermann::Regular) || (pattern.respond_to?(:patterns) && pattern.patterns.any? { |subpattern| subpattern.is_a?(Mustermann::Regular) }) if regexp_exists captures = pattern.match(route).captures.map { |c| URI_INSTANCE.unescape(c) if c } values += captures @params[:captures] = force_encoding(captures) unless captures.nil? || captures.empty? else values += params.values.flatten end catch(:pass) do conditions.each { |c| throw :pass if c.bind(self).call == false } block ? block[self, values] : yield(self, values) end rescue StandardError @env['sinatra.error.params'] = @params raise ensure params ||= {} params.each { |k, _| @params.delete(k) } unless @env['sinatra.error.params'] end
#route!(base = settings, pass_block = nil) (private)
Run routes defined on the class and all superclasses.
# File 'lib/sinatra/base.rb', line 1066
def route!(base = settings, pass_block = nil) routes = base.routes[@request.request_method] routes&.each do |pattern, conditions, block| response.delete_header('content-type') unless @pinned_response returned_pass_block = process_route(pattern, conditions) do |*args| env['sinatra.route'] = "#{@request.request_method} #{pattern}" route_eval { block[*args] } end # don't wipe out pass_block in superclass pass_block = returned_pass_block if returned_pass_block end # Run routes defined in superclass. if base.superclass.respond_to?(:routes) return route!(base.superclass, pass_block) end route_eval(&pass_block) if pass_block route_missing end
#route_eval (private)
Run a route block and throw :halt
with the result.
# File 'lib/sinatra/base.rb', line 1091
def route_eval throw :halt, yield end
#route_missing (private)
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.
#settings
Access settings defined with Base
.set.
# File 'lib/sinatra/base.rb', line 1024
def settings self.class.settings end
#static!(options = {}) (private)
Attempt to serve static files from public directory. Throws :halt
when
a matching file is found, returns nil otherwise.
# File 'lib/sinatra/base.rb', line 1146
def static!( = {}) return if (public_dir = settings.public_folder).nil? path = "#{public_dir}#{URI_INSTANCE.unescape(request.path_info)}" return unless valid_path?(path) path = File. (path) return unless path.start_with?("#{File. (public_dir)}/") return unless File.file?(path) env['sinatra.static_file'] = path cache_control(*settings.static_cache_control) if settings.static_cache_control? send_file path, .merge(disposition: nil) end