class Falcon::Hosts
def add(name, host = Host.new, &block)
def add(name, host = Host.new, &block) host = Host.new yield host if block_given? @named[name] = host.freeze end
def call(controller)
def call(controller) self.each do |name, host| if container = host.start controller << container end end proxy = hosts.proxy debug_trap = Async::IO::Trap.new(:USR1) profile = RubyProf::Profile.new(merge_fibers: true) controller << Async::Container::Forked.new do |task| Process.setproctitle("Falcon Proxy") server = Falcon::Server.new( proxy, Async::HTTP::URLEndpoint.parse( 'https://0.0.0.0', reuse_address: true, ssl_context: hosts.ssl_context ) ) Async::Reactor.run do |task| task.async do debug_trap.install! $stderr.puts "Send `kill -USR1 #{Process.pid}` for detailed status :)" debug_trap.trap do task.reactor.print_hierarchy($stderr) # Async.logger.level = Logger::DEBUG end end task.async do |task| start_time = Async::Clock.now while true task.sleep(600) duration = Async::Clock.now - start_time puts "Handled #{proxy.count} requests; #{(proxy.count.to_f / duration.to_f).round(1)} requests per second." end end $stderr.puts "Starting server" server.run end end end
def client_endpoints
def client_endpoints Hash[ @named.collect{|name, host| [name, host.endpoint]} ] end
def each(&block)
def each(&block) @named.each(&block) end
def endpoint
def endpoint @server_endpoint ||= Async::HTTP::URLEndpoint.parse( 'https://[::]', ssl_context: self.ssl_context, reuse_address: true ) end
def host_context(socket, hostname)
def host_context(socket, hostname) if host = @named[hostname] socket.hostname = hostname return host.ssl_context end end
def initialize
def initialize @named = {} @server_context = nil @server_endpoint = nil end
def proxy
def proxy Proxy.new(Falcon::BadRequest, self.client_endpoints) end
def redirection
def redirection Redirection.new(Falcon::BadRequest, self.client_endpoints) end
def ssl_context
def ssl_context @server_context ||= OpenSSL::SSL::SSLContext.new.tap do |context| context.servername_cb = Proc.new do |socket, hostname| self.host_context(socket, hostname) end context.session_id_context = "falcon" context.alpn_protocols = DEFAULT_ALPN_PROTOCOLS context.set_params context.setup end end