lib/falcon/hosts.rb in falcon-0.18.14 vs lib/falcon/hosts.rb in falcon-0.19.0
- old
+ new
@@ -18,23 +18,33 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
require 'async/io/endpoint'
+require_relative 'proxy'
+require_relative 'redirection'
+
+require 'async/container/forked'
+
module Falcon
class Host
def initialize
@app = nil
+ @app_root = nil
+ @config_path = "config.ru"
+
@endpoint = nil
@ssl_certificate = nil
@ssl_key = nil
@ssl_context = nil
end
attr_accessor :app
+ attr_accessor :app_root
+ attr_accessor :config_path
attr_accessor :endpoint
attr_accessor :ssl_certificate
attr_accessor :ssl_key
@@ -47,10 +57,44 @@
ssl_context
super
end
+ def app?
+ @app || @config_path
+ end
+
+ def load_app(verbose = false)
+ return @app if @app
+
+ if @config_path
+ rack_app, options = Rack::Builder.parse_file(@config_path)
+
+ return Server.middleware(rack_app, verbose: verbose)
+ end
+ end
+
+ def self_signed!(hostname)
+ authority = Localhost::Authority.fetch(hostname)
+
+ @ssl_context = authority.server_context.tap do |context|
+ context.alpn_select_cb = lambda do |protocols|
+ if protocols.include? "h2"
+ return "h2"
+ elsif protocols.include? "http/1.1"
+ return "http/1.1"
+ elsif protocols.include? "http/1.0"
+ return "http/1.0"
+ else
+ return nil
+ end
+ end
+
+ context.session_id_context = "falcon"
+ end
+ end
+
def ssl_certificate_path= path
@ssl_certificate = OpenSSL::X509::Certificate.new(File.read(path))
end
def ssl_key_path= path
@@ -68,13 +112,17 @@
context.setup
end
end
- def start
- if app = self.app
+ def start(*args)
+ if self.app?
Async::Container::Forked.new do
+ Dir.chdir(@app_root) if @app_root
+
+ app = self.load_app(*args)
+
server = Falcon::Server.new(app, self.server_endpoint)
server.run
end
end
@@ -140,8 +188,63 @@
]
end
def proxy
Proxy.new(Falcon::BadRequest, self.client_endpoints)
+ end
+
+ def redirection
+ Redirection.new(Falcon::BadRequest, self.client_endpoints)
+ end
+
+ 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
end
end