class Rackup::Server
def self.start(options = nil)
)
:server => 'cgi'
end,
[200, {'content-type' => 'text/html'}, ['hello world']]
:app => lambda do |e|
Rack::Server.start(
example:
This method can be used to very easily launch a CGI application, for
any default options.
Providing an options hash will prevent ARGV parsing and will not include
provide standard ARGV rackup options, defaulting to load 'config.ru'.
Start a new rack server (like running rackup). This will parse ARGV and
def self.start(options = nil) new(options).start end
def app
def app @app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config end
def build_app(app)
def build_app(app) middleware[options[:environment]].reverse_each do |middleware| middleware = middleware.call(self) if middleware.respond_to?(:call) next unless middleware klass, *args = middleware app = klass.new(app, *args) end app end
def build_app_and_options_from_config
def build_app_and_options_from_config if !::File.exist? options[:config] abort "configuration #{options[:config]} not found" end return Rack::Builder.parse_file(self.options[:config]) end
def build_app_from_string
def build_app_from_string Rack::Builder.new_from_string(self.options[:builder]) end
def check_pid!
def check_pid! return unless ::File.exist?(options[:pid]) pid = ::File.read(options[:pid]).to_i raise Errno::ESRCH if pid == 0 Process.kill(0, pid) exit_with_pid(pid) rescue Errno::ESRCH ::File.delete(options[:pid]) rescue Errno::EPERM exit_with_pid(pid) end
def daemonize_app
def daemonize_app # Cannot be covered as it forks # :nocov: Process.daemon(true, options[:daemonize] == :noclose) # :nocov: end
def default_middleware_by_environment
def default_middleware_by_environment m = Hash.new {|h, k| h[k] = []} m["deployment"] = [ [Rack::ContentLength], logging_middleware, [Rack::TempfileReaper] ] m["development"] = [ [Rack::ContentLength], logging_middleware, [Rack::ShowExceptions], [Rack::Lint], [Rack::TempfileReaper] ] m end
def default_options
def default_options environment = ENV['RACK_ENV'] || 'development' default_host = environment == 'development' ? 'localhost' : '0.0.0.0' { environment: environment, pid: nil, Port: 9292, Host: default_host, AccessLog: [], config: "config.ru" } end
def exit_with_pid(pid)
def exit_with_pid(pid) $stderr.puts "A server is already running (pid: #{pid}, file: #{options[:pid]})." exit(1) end
def handle_profiling(heapfile, profile_mode, filename)
def handle_profiling(heapfile, profile_mode, filename) if heapfile require "objspace" ObjectSpace.trace_object_allocations_start yield GC.start ::File.open(heapfile, "w") { |f| ObjectSpace.dump_all(output: f) } exit end if profile_mode require "stackprof" require "tempfile" make_profile_name(filename) do |filename| ::File.open(filename, "w") do |f| StackProf.run(mode: profile_mode, out: f) do yield end puts "Profile written to: #{filename}" end end exit end yield end
def initialize(options = nil)
* :profile_mode
location for CPU/Memory (StackProf) profile output (defaults to a tempfile)
* :profile_file
location for ObjectSpace.dump_all to write the output to
* :heapfile
Additional options for profiling app initialization include:
require the given libraries
* :require
add given paths to $LOAD_PATH
* :include
turn on warnings ($-w = true)
* :warn
turn on debug output ($DEBUG = true)
* :debug
webrick access log options (or supporting Rackup::Handler)
* :AccessLog
the port to bind to (used by supporting Rackup::Handler)
* :Port
the host address to bind to (used by supporting Rackup::Handler)
* :Host
path to write a pid file after daemonize
* :pid
if :noclose, the server will not close STDOUT/STDERR
if truthy, the server will daemonize itself (fork, detach, etc)
* :daemonize
choose a specific Rackup::Handler, e.g. cgi, fcgi, webrick
* :server
note: when the server is a cgi server, CommonLogger is not included.
- none: no extra middleware
- deployment: CommonLogger
- development: CommonLogger, ShowExceptions, and Lint
your application. Default options available are:
this selects the middleware that will be wrapped around
* :environment
a rackup configuration file path to load (.ru)
* :config
a string to evaluate a Rack::Builder from
* :builder
a rack application to run (overrides :config and :builder)
* :app
Options may include:
def initialize(options = nil) @ignore_options = [] if options @use_default_options = false @options = options @app = options[:app] if options[:app] else @use_default_options = true @options = parse_options(ARGV) end end
def logging_middleware
def logging_middleware lambda { |server| /CGI/.match?(server.server.name) || server.options[:quiet] ? nil : [Rack::CommonLogger, $stderr] } end
def make_profile_name(filename)
def make_profile_name(filename) if filename yield filename else ::Dir::Tmpname.create("profile.dump") do |tmpname, _, _| yield tmpname end end end
def middleware
def middleware default_middleware_by_environment end
def middleware
def middleware self.class.middleware end
def opt_parser
def opt_parser Options.new end
def options
def options merged_options = @use_default_options ? default_options.merge(@options) : @options merged_options.reject { |k, v| @ignore_options.include?(k) } end
def parse_options(args)
def parse_options(args) # Don't evaluate CGI ISINDEX parameters. args.clear if ENV.include?(Rack::REQUEST_METHOD) @options = opt_parser.parse!(args) @options[:config] = ::File.expand_path(options[:config]) ENV["RACK_ENV"] = options[:environment] @options end
def server
def server @_server ||= Handler.get(options[:server]) || Handler.default end
def start(&block)
def start(&block) if options[:warn] $-w = true end if includes = options[:include] $LOAD_PATH.unshift(*includes) end Array(options[:require]).each do |library| require library end if options[:debug] $DEBUG = true require 'pp' p options[:server] pp wrapped_app pp app end check_pid! if options[:pid] # Touch the wrapped app, so that the config.ru is loaded before # daemonization (i.e. before chdir, etc). handle_profiling(options[:heapfile], options[:profile_mode], options[:profile_file]) do wrapped_app end daemonize_app if options[:daemonize] write_pid if options[:pid] trap(:INT) do if server.respond_to?(:shutdown) server.shutdown else exit end end server.run(wrapped_app, **options, &block) end
def wrapped_app
def wrapped_app @wrapped_app ||= build_app app end
def write_pid
def write_pid ::File.open(options[:pid], ::File::CREAT | ::File::EXCL | ::File::WRONLY ){ |f| f.write("#{Process.pid}") } at_exit { ::FileUtils.rm_f(options[:pid]) } rescue Errno::EEXIST check_pid! retry end