class Roger::Server
The Roger
webserver. Initializes a rack server.
@option options :port [Integer] The specified port you'd want to use @option options :auto_port [Boolean] Wether or not you want Roger
to find a suitable port if the specified port is in use.
@option options :handler [String] The preferred handler to use
Attributes
@attr_accessor [Hash] Options pass to ::Roger::Rack::Roger
initialization
@see ::Roger::Rack:Roger
@attr_reader [Roger::Project] project The project used in this server
@attr_reader [nil, Class] used_handler
The actual used handler.
Only set if the server is running.
@attr_reader [nil, Integer] used_port
The actual port used to start
the webserver. Only set if the server is running.
Public Class Methods
# File lib/roger/server.rb, line 36 def initialize(project, options = {}) @project = project @stack = initialize_rack_builder @server_options = {} # Defaults self.port = 9000 self.handler = nil self.host = "0.0.0.0" self.auto_port = true @used_port = nil @used_handler = nil set_options(options) end
Public Instance Methods
# File lib/roger/server.rb, line 120 def handler=(h) @handler = if h.respond_to?(:run) h else get_handler(h) end end
# File lib/roger/server.rb, line 116 def host=(h) @host = server_options[:Host] = h end
Use the map handler to map endpoints to certain urls
@see ::Rack::Builder#map
# File lib/roger/server.rb, line 74 def map(*args, &block) @stack.map(*args, &block) end
# File lib/roger/server.rb, line 112 def port=(p) @port = server_options[:Port] = p end
# File lib/roger/server.rb, line 78 def run! project.mode = :server options = server_options_for_handler @used_port = options[:Port] @used_handler = handler handler.run application, options do |server| trap(:INT) do ## Use thins' hard #stop! if available, otherwise just #stop server.respond_to?(:stop!) ? server.stop! : server.stop puts "Roger, out!" end yield server if block_given? end ensure project.mode = nil @used_port = nil @used_handler = nil end
# File lib/roger/server.rb, line 101 def server_options_for_handler # Search for available port options = server_options.dup if auto_port && !port_free?(options[:Host], options[:Port]) options[:Port] = free_port_for_host_above(options[:Host], options[:Port]) end # Return the options options end
Sets the options, this is a separate method as we want to override certain things set in the rogerfile from the commandline
# File lib/roger/server.rb, line 57 def set_options(options) self.port = options[:port].to_i if options.key?(:port) self.handler = options[:handler] if options.key?(:handler) self.host = options[:host] if options.key?(:host) self.auto_port = options[:auto_port] if options.key?(:auto_port) end
Use the specified Rack
middleware
@see ::Rack::Builder#use
# File lib/roger/server.rb, line 67 def use(*args, &block) @stack.use(*args, &block) end
Protected Instance Methods
Build the final application that get's run by the Rack
Handler
# File lib/roger/server.rb, line 148 def application return @app if @app @stack.run Rack::Roger.new(project, @application_options || {}) @app = @stack end
# File lib/roger/server.rb, line 169 def call(env) env["roger.project"] = self.class.project @app.call(env) end
See what handlers work
# File lib/roger/server.rb, line 202 def detect_valid_handler(servers) handler = nil while (server_name = servers.shift) && handler.nil? begin handler = ::Rack::Handler.get(server_name) return [handler, server_name] rescue LoadError handler = nil rescue NameError handler = nil end end end
Get the first free port for host above port Will only ever test 100 ports.
# File lib/roger/server.rb, line 132 def free_port_for_host_above(host, port) test_port = port test_port += 1 until port_free?(host, test_port) || port + 100 <= test_port test_port end
Get the actual handler for use in the server Will always return a handler, it will try to use the fallbacks
# File lib/roger/server.rb, line 189 def get_handler(preferred_handler_name = nil) servers = %w(puma mongrel thin webrick) servers.unshift(preferred_handler_name) if preferred_handler_name handler, server_name = detect_valid_handler(servers) if preferred_handler_name && server_name != preferred_handler_name puts "Handler '#{preferred_handler_name}' not found, using fallback ('#{handler.inspect}')." end handler end
Initialize the Rack
builder instance for this server
@return ::Rack::Builder instance
# File lib/roger/server.rb, line 159 def initialize_rack_builder roger_env = Class.new do class << self attr_accessor :project end def initialize(app) @app = app end def call(env) env["roger.project"] = self.class.project @app.call(env) end end roger_env.project = project builder = ::Rack::Builder.new builder.use roger_env builder.use ::Rack::ShowExceptions builder.use ::Rack::Lint builder.use ::Rack::ConditionalGet builder.use ::Rack::Head builder end
See if a certain port is free on a certain host
# File lib/roger/server.rb, line 139 def port_free?(host, port) Addrinfo.tcp(host, port).listen.close true rescue SocketError, Errno::EADDRINUSE, Errno::EACCES false end