# class Rack::Server

### Attributes

options[W]

### Public Class Methods

default_middleware_by_environment() click to toggle source

    # File lib/rack/server.rb, line 259
    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

logging_middleware() click to toggle source

    # File lib/rack/server.rb, line 253
    def logging_middleware
      lambda { |server|
        /CGI/.match?(server.server.name) || server.options[:quiet] ? nil : [Rack::CommonLogger, $stderr]
      }
    end

middleware() click to toggle source

    # File lib/rack/server.rb, line 277
    def middleware
      default_middleware_by_environment
    end

new(options = nil) click to toggle source

`Options` may include:

- :app

      a rack application to run (overrides :config and :builder)

- :builder

      a string to evaluate a Rack::Builder from

- :config

      a rackup configuration file path to load (.ru)

- :environment

      this selects the middleware that will be wrapped around
      your application. Default options available are:
        - development: CommonLogger, ShowExceptions, and Lint
        - deployment: CommonLogger
        - none: no extra middleware
      note: when the server is a cgi server, CommonLogger is not included.

- :server

      choose a specific Rack::Handler, e.g. cgi, fcgi, webrick

- :daemonize

      if true, the server will daemonize itself (fork, detach, etc)

- :pid

      path to write a pid file after daemonize

- :Host

      the host address to bind to (used by supporting Rack::Handler)

- :Port

      the port to bind to (used by supporting Rack::Handler)

- :AccessLog

      webrick access log options (or supporting Rack::Handler)

- :debug

      turn on debug output ($DEBUG = true)

- :warn

      turn on warnings ($-w = true)

- :include

      add given paths to $LOAD_PATH

- :require

      require the given libraries

Additional options for profiling app initialization include:

- :heapfile

      location for ObjectSpace.dump_all to write the output to

- :profile_file

      location for CPU/Memory (StackProf) profile output (defaults to a tempfile)

- :profile_mode

      StackProf profile mode (cpu|wall|object)

    # File lib/rack/server.rb, line 215
    def initialize(options = nil)
      @ignore_options = []

      if options
        @use_default_options = false
        @options = options
        @app = options[:app] if options[:app]
      else
        argv = defined?(SPEC_ARGV) ? SPEC_ARGV : ARGV
        @use_default_options = true
        @options = parse_options(argv)
      end
    end

start(options = nil) click to toggle source

Start a new rack server (like running rackup). This will parse ARGV and provide standard ARGV rackup options, defaulting to load 'config.ru'.

Providing an options hash will prevent ARGV parsing and will not include any default options.

This method can be used to very easily launch a CGI application, for example:

    Rack::Server.start(
      :app => lambda do |e|
        [200, {'Content-Type' => 'text/html'}, ['hello world']]
      end,
      :server => 'cgi'
    )

Further options available here are documented on Rack::Server#initialize

    # File lib/rack/server.rb, line 167
    def self.start(options = nil)
      new(options).start
    end

### Public Instance Methods

app() click to toggle source

    # File lib/rack/server.rb, line 248
    def app
      @app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
    end

default_options() click to toggle source

    # File lib/rack/server.rb, line 234
    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

middleware() click to toggle source

    # File lib/rack/server.rb, line 282
    def middleware
      self.class.middleware
    end

options() click to toggle source

    # File lib/rack/server.rb, line 229
    def options
      merged_options = @use_default_options ? default_options.merge(@options) : @options
      merged_options.reject { |k, v| @ignore_options.include?(k) }
    end

server() click to toggle source

    # File lib/rack/server.rb, line 330
    def server
      @_server ||= Rack::Handler.get(options[:server])

      unless @_server
        @_server = Rack::Handler.default

        # We already speak FastCGI
        @ignore_options = [:File, :Port] if @_server.to_s == 'Rack::Handler::FastCGI'
      end

      @_server
    end

start(&block) click to toggle source

    # File lib/rack/server.rb, line 286
    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

### Private Instance Methods

build_app(app) click to toggle source

    # File lib/rack/server.rb, line 411
    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

build_app_and_options_from_config() click to toggle source

    # File lib/rack/server.rb, line 344
    def build_app_and_options_from_config
      if !::File.exist? options[:config]
        abort "configuration #{options[:config]} not found"
      end

      app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
      @options.merge!(options) { |key, old, new| old }
      app
    end

build_app_from_string() click to toggle source

    # File lib/rack/server.rb, line 392
    def build_app_from_string
      Rack::Builder.new_from_string(self.options[:builder])
    end

check_pid!() click to toggle source

    # File lib/rack/server.rb, line 440
    def check_pid!
      case pidfile_process_status
      when :running, :not_owned
        $stderr.puts "A server is already running. Check #{options[:pid]}."
        exit(1)
      when :dead
        ::File.delete(options[:pid])
      end
    end

daemonize_app() click to toggle source

    # File lib/rack/server.rb, line 425
    def daemonize_app
      # Cannot be covered as it forks
      # :nocov:
      Process.daemon
      # :nocov:
    end

handle_profiling(heapfile, profile_mode, filename) { || ... } click to toggle source

    # File lib/rack/server.rb, line 354
    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

make_profile_name(filename) { |filename| ... } click to toggle source

    # File lib/rack/server.rb, line 382
    def make_profile_name(filename)
      if filename
        yield filename
      else
        ::Dir::Tmpname.create("profile.dump") do |tmpname, _, _|
          yield tmpname
        end
      end
    end

opt_parser() click to toggle source

    # File lib/rack/server.rb, line 407
    def opt_parser
      Options.new
    end

parse_options(args) click to toggle source

    # File lib/rack/server.rb, line 396
    def parse_options(args)
      # Don't evaluate CGI ISINDEX parameters.
      # http://www.meb.uni-bonn.de/docs/cgi/cl.html
      args.clear if ENV.include?(REQUEST_METHOD)

      @options = opt_parser.parse!(args)
      @options[:config] = ::File.expand_path(options[:config])
      ENV["RACK_ENV"] = options[:environment]
      @options
    end

pidfile_process_status() click to toggle source

    # File lib/rack/server.rb, line 450
    def pidfile_process_status
      return :exited unless ::File.exist?(options[:pid])

      pid = ::File.read(options[:pid]).to_i
      return :dead if pid == 0

      Process.kill(0, pid)
      :running
    rescue Errno::ESRCH
      :dead
    rescue Errno::EPERM
      :not_owned
    end

wrapped_app() click to toggle source

    # File lib/rack/server.rb, line 421
    def wrapped_app
      @wrapped_app ||= build_app app
    end

write_pid() click to toggle source

    # File lib/rack/server.rb, line 432
    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