falcon 0.36.1 → 0.36.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/falcon/adapters/early_hints.rb +8 -0
- data/lib/falcon/adapters/input.rb +32 -11
- data/lib/falcon/adapters/output.rb +20 -1
- data/lib/falcon/adapters/rack.rb +61 -34
- data/lib/falcon/adapters/response.rb +23 -1
- data/lib/falcon/adapters/rewindable.rb +10 -3
- data/lib/falcon/command.rb +2 -0
- data/lib/falcon/command/host.rb +13 -2
- data/lib/falcon/command/paths.rb +4 -0
- data/lib/falcon/command/proxy.rb +14 -0
- data/lib/falcon/command/redirect.rb +12 -0
- data/lib/falcon/command/serve.rb +22 -15
- data/lib/falcon/command/supervisor.rb +15 -1
- data/lib/falcon/command/top.rb +16 -0
- data/lib/falcon/command/virtual.rb +15 -0
- data/lib/falcon/configuration.rb +69 -7
- data/lib/falcon/controller/host.rb +12 -0
- data/lib/falcon/controller/proxy.rb +13 -0
- data/lib/falcon/controller/redirect.rb +7 -0
- data/lib/falcon/controller/serve.rb +15 -2
- data/lib/falcon/controller/virtual.rb +17 -0
- data/lib/falcon/endpoint.rb +8 -0
- data/lib/falcon/{configuration/proxy.rb → environments.rb} +9 -5
- data/lib/falcon/environments/application.rb +72 -0
- data/lib/falcon/{configuration/application.rb → environments/lets_encrypt_tls.rb} +21 -20
- data/lib/falcon/{configuration/lets_encrypt_tls.rb → environments/proxy.rb} +13 -6
- data/lib/falcon/{configuration → environments}/rack.rb +14 -2
- data/lib/falcon/{configuration → environments}/self_signed_tls.rb +9 -1
- data/lib/falcon/{configuration → environments}/supervisor.rb +19 -5
- data/lib/falcon/{configuration → environments}/tls.rb +39 -5
- data/lib/falcon/extensions/openssl.rb +1 -0
- data/lib/falcon/middleware/proxy.rb +26 -5
- data/lib/falcon/middleware/redirect.rb +11 -0
- data/lib/falcon/{verbose.rb → middleware/verbose.rb} +34 -26
- data/lib/falcon/proxy_endpoint.rb +21 -0
- data/lib/falcon/server.rb +8 -2
- data/lib/falcon/service/application.rb +23 -1
- data/lib/falcon/service/generic.rb +18 -0
- data/lib/falcon/service/proxy.rb +6 -0
- data/lib/falcon/service/supervisor.rb +14 -2
- data/lib/falcon/services.rb +21 -0
- data/lib/falcon/tls.rb +4 -2
- data/lib/falcon/version.rb +1 -1
- data/lib/rack/handler/falcon.rb +7 -1
- metadata +63 -119
- data/.editorconfig +0 -5
- data/.github/FUNDING.yml +0 -3
- data/.github/workflows/development.yml +0 -60
- data/.gitignore +0 -14
- data/.rspec +0 -3
- data/Gemfile +0 -17
- data/README.md +0 -316
- data/examples/beer/config.ru +0 -57
- data/examples/beer/falcon.rb +0 -8
- data/examples/benchmark/config.ru +0 -39
- data/examples/benchmark/falcon.rb +0 -6
- data/examples/csv/config.ru +0 -31
- data/examples/google/falcon.rb +0 -14
- data/examples/hello/config.ru +0 -22
- data/examples/hello/falcon.rb +0 -24
- data/examples/hello/preload.rb +0 -7
- data/examples/internet/config.ru +0 -54
- data/examples/memory/allocations.rb +0 -39
- data/examples/memory/config.ru +0 -14
- data/examples/push/client.rb +0 -29
- data/examples/push/config.ru +0 -28
- data/examples/push/index.html +0 -14
- data/examples/push/script.js +0 -2
- data/examples/push/style.css +0 -4
- data/examples/redis/Gemfile +0 -9
- data/examples/redis/config.ru +0 -28
- data/examples/sequel/Gemfile +0 -4
- data/examples/sequel/config.ru +0 -8
- data/examples/sequel/data.sqlite3 +0 -0
- data/examples/server/standalone.rb +0 -27
- data/examples/sinatra/Gemfile +0 -7
- data/examples/sinatra/Gemfile.lock +0 -53
- data/examples/sinatra/config.ru +0 -16
- data/examples/trailers/config.ru +0 -34
- data/examples/trailers/falcon.rb +0 -8
- data/falcon.gemspec +0 -45
- data/gems/rack1.gemfile +0 -4
- data/gems/rack3.gemfile +0 -4
- data/logo-square.afdesign +0 -0
- data/logo.afdesign +0 -0
- data/logo.svg +0 -107
- data/server.rb +0 -21
- data/tasks/benchmark.rake +0 -103
@@ -22,9 +22,17 @@
|
|
22
22
|
|
23
23
|
require 'localhost/authority'
|
24
24
|
|
25
|
-
|
25
|
+
# A self-signed SSL context environment.
|
26
|
+
#
|
27
|
+
# @scope Falcon Environments
|
28
|
+
# @name self_signed_tls
|
29
|
+
environment(:self_signed_tls) do
|
30
|
+
# The default session identifier for the session cache.
|
31
|
+
# @attribute [String]
|
26
32
|
ssl_session_id {"falcon"}
|
27
33
|
|
34
|
+
# The SSL context to use for incoming connections.
|
35
|
+
# @attribute [OpenSSL::SSL::SSLContext]
|
28
36
|
ssl_context do
|
29
37
|
contexts = Localhost::Authority.fetch(authority)
|
30
38
|
|
@@ -22,15 +22,29 @@
|
|
22
22
|
|
23
23
|
require_relative '../service/supervisor'
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
# A application process monitor environment.
|
26
|
+
#
|
27
|
+
# @scope Falcon Environments
|
28
|
+
# @name supervisor
|
29
|
+
environment(:supervisor) do
|
30
|
+
# The name of the supervisor
|
31
|
+
# @attribute [String]
|
28
32
|
name "supervisor"
|
29
33
|
|
30
|
-
|
34
|
+
# The IPC path to use for communication with the supervisor.
|
35
|
+
# @attribute [String]
|
36
|
+
ipc_path do
|
37
|
+
::File.expand_path("supervisor.ipc", root)
|
38
|
+
end
|
31
39
|
|
32
|
-
endpoint
|
40
|
+
# The endpoint the supervisor will bind to.
|
41
|
+
# @attribute [Async::IO::Endpoint]
|
42
|
+
endpoint do
|
43
|
+
Async::IO::Endpoint.unix(ipc_path)
|
44
|
+
end
|
33
45
|
|
46
|
+
# The service class to use for the supervisor.
|
47
|
+
# @attribute [Class]
|
34
48
|
service do
|
35
49
|
::Falcon::Service::Supervisor
|
36
50
|
end
|
@@ -24,19 +24,53 @@ require_relative '../extensions/openssl'
|
|
24
24
|
require_relative '../controller/proxy'
|
25
25
|
require_relative '../tls'
|
26
26
|
|
27
|
-
|
27
|
+
# A general SSL context environment.
|
28
|
+
#
|
29
|
+
# @scope Falcon Environments
|
30
|
+
# @name tls
|
31
|
+
environment(:tls) do
|
32
|
+
# The default session identifier for the session cache.
|
33
|
+
# @attribute [String]
|
28
34
|
ssl_session_id "falcon"
|
35
|
+
|
36
|
+
# The supported ciphers.
|
37
|
+
# @attribute [Array(String)]
|
29
38
|
ssl_ciphers Falcon::TLS::SERVER_CIPHERS
|
30
39
|
|
31
|
-
|
32
|
-
|
40
|
+
# The public certificate path.
|
41
|
+
# @attribute [String]
|
42
|
+
ssl_certificate_path do
|
43
|
+
File.expand_path("ssl/certificate.pem", root)
|
44
|
+
end
|
45
|
+
|
46
|
+
# The list of certificates loaded from that path.
|
47
|
+
# @attribute [Array(OpenSSL::X509::Certificate)]
|
48
|
+
ssl_certificates do
|
49
|
+
OpenSSL::X509.load_certificates(ssl_certificate_path)
|
50
|
+
end
|
33
51
|
|
52
|
+
# The main certificate.
|
53
|
+
# @attribute [OpenSSL::X509::Certificate]
|
34
54
|
ssl_certificate {ssl_certificates[0]}
|
55
|
+
|
56
|
+
# The certificate chain.
|
57
|
+
# @attribute [Array(OpenSSL::X509::Certificate)]
|
35
58
|
ssl_certificate_chain {ssl_certificates[1..-1]}
|
36
59
|
|
37
|
-
|
38
|
-
|
60
|
+
# The private key path.
|
61
|
+
# @attribute [String]
|
62
|
+
ssl_private_key_path do
|
63
|
+
File.expand_path("ssl/private.key", root)
|
64
|
+
end
|
65
|
+
|
66
|
+
# The private key.
|
67
|
+
# @attribute [OpenSSL::PKey::RSA]
|
68
|
+
ssl_private_key do
|
69
|
+
OpenSSL::PKey::RSA.new(File.read(ssl_private_key_path))
|
70
|
+
end
|
39
71
|
|
72
|
+
# The SSL context to use for incoming connections.
|
73
|
+
# @attribute [OpenSSL::SSL::SSLContext]
|
40
74
|
ssl_context do
|
41
75
|
OpenSSL::SSL::SSLContext.new.tap do |context|
|
42
76
|
context.add_certificate(ssl_certificate, ssl_private_key, ssl_certificate_chain)
|
@@ -25,6 +25,7 @@ require 'openssl/x509'
|
|
25
25
|
module OpenSSL::X509
|
26
26
|
CERTIFICATE_PATTERN = /-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m
|
27
27
|
|
28
|
+
# An extension to load an array of certificates from a file at the given path.
|
28
29
|
def self.load_certificates(path)
|
29
30
|
File.read(path).scan(CERTIFICATE_PATTERN).collect do |text|
|
30
31
|
Certificate.new(text)
|
@@ -26,6 +26,7 @@ require 'protocol/http/middleware'
|
|
26
26
|
|
27
27
|
module Falcon
|
28
28
|
module Middleware
|
29
|
+
# A static middleware which always returns a 400 bad request response.
|
29
30
|
module BadRequest
|
30
31
|
def self.call(request)
|
31
32
|
return Protocol::HTTP::Response[400, {}, []]
|
@@ -35,14 +36,17 @@ module Falcon
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
39
|
+
# A HTTP middleware for proxying requests to a given set of hosts.
|
40
|
+
# Typically used for implementing virtual servers.
|
38
41
|
class Proxy < Protocol::HTTP::Middleware
|
39
|
-
FORWARDED = 'forwarded'
|
40
|
-
X_FORWARDED_FOR = 'x-forwarded-for'
|
41
|
-
X_FORWARDED_PROTO = 'x-forwarded-proto'
|
42
|
+
FORWARDED = 'forwarded'
|
43
|
+
X_FORWARDED_FOR = 'x-forwarded-for'
|
44
|
+
X_FORWARDED_PROTO = 'x-forwarded-proto'
|
42
45
|
|
43
|
-
VIA = 'via'
|
44
|
-
CONNECTION = 'connection'
|
46
|
+
VIA = 'via'
|
47
|
+
CONNECTION = 'connection'
|
45
48
|
|
49
|
+
# HTTP hop headers which *should* not be passed through the proxy.
|
46
50
|
HOP_HEADERS = [
|
47
51
|
'connection',
|
48
52
|
'keep-alive',
|
@@ -52,6 +56,9 @@ module Falcon
|
|
52
56
|
'upgrade',
|
53
57
|
]
|
54
58
|
|
59
|
+
# Initialize the proxy middleware.
|
60
|
+
# @parameter app [Protocol::HTTP::Middleware] The middleware to use if a request can't be proxied.
|
61
|
+
# @parameter hosts [Array(Service::Proxy)] The host applications to proxy to.
|
55
62
|
def initialize(app, hosts)
|
56
63
|
super(app)
|
57
64
|
|
@@ -63,18 +70,26 @@ module Falcon
|
|
63
70
|
@count = 0
|
64
71
|
end
|
65
72
|
|
73
|
+
# The number of requests that have been proxied.
|
74
|
+
# @attribute [Integer]
|
66
75
|
attr :count
|
67
76
|
|
77
|
+
# Close all the connections to the upstream hosts.
|
68
78
|
def close
|
69
79
|
@clients.each_value(&:close)
|
70
80
|
|
71
81
|
super
|
72
82
|
end
|
73
83
|
|
84
|
+
# Establish a connection to the specified upstream endpoint.
|
85
|
+
# @parameter endpoint [Async::HTTP::Endpoint]
|
74
86
|
def connect(endpoint)
|
75
87
|
@clients[endpoint] ||= Async::HTTP::Client.new(endpoint)
|
76
88
|
end
|
77
89
|
|
90
|
+
# Lookup the appropriate host for the given request.
|
91
|
+
# @parameter request [Protocol::HTTP::Request]
|
92
|
+
# @returns [Service::Proxy]
|
78
93
|
def lookup(request)
|
79
94
|
# Trailing dot and port is ignored/normalized.
|
80
95
|
if authority = request.authority&.sub(/(\.)?(:\d+)?$/, '')
|
@@ -82,6 +97,8 @@ module Falcon
|
|
82
97
|
end
|
83
98
|
end
|
84
99
|
|
100
|
+
# Prepare the headers to be sent to an upstream host.
|
101
|
+
# In particular, we delete all connection and hop headers.
|
85
102
|
def prepare_headers(headers)
|
86
103
|
if connection = headers[CONNECTION]
|
87
104
|
headers.extract(connection)
|
@@ -90,6 +107,8 @@ module Falcon
|
|
90
107
|
headers.extract(HOP_HEADERS)
|
91
108
|
end
|
92
109
|
|
110
|
+
# Prepare the request to be proxied to the specified host.
|
111
|
+
# In particular, we set appropriate {VIA}, {FORWARDED}, {X_FORWARDED_FOR} and {X_FORWARDED_PROTO} headers.
|
93
112
|
def prepare_request(request, host)
|
94
113
|
forwarded = []
|
95
114
|
|
@@ -124,6 +143,8 @@ module Falcon
|
|
124
143
|
return request
|
125
144
|
end
|
126
145
|
|
146
|
+
# Proxy the request if the authority matches a specific host.
|
147
|
+
# @parameter request [Protocol::HTTP::Request]
|
127
148
|
def call(request)
|
128
149
|
if host = lookup(request)
|
129
150
|
@count += 1
|
@@ -24,6 +24,7 @@ require 'async/http/client'
|
|
24
24
|
|
25
25
|
module Falcon
|
26
26
|
module Middleware
|
27
|
+
# A static middleware which always returns a 404 not found response.
|
27
28
|
module NotFound
|
28
29
|
def self.call(request)
|
29
30
|
return Protocol::HTTP::Response[404, {}, []]
|
@@ -33,7 +34,13 @@ module Falcon
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
37
|
+
# A HTTP middleware for redirecting a given set of hosts to a different endpoint.
|
38
|
+
# Typically used for implementing HTTP -> HTTPS redirects.
|
36
39
|
class Redirect < Protocol::HTTP::Middleware
|
40
|
+
# Initialize the redirect middleware.
|
41
|
+
# @parameter app [Protocol::HTTP::Middleware] The middleware to wrap.
|
42
|
+
# @parameter hosts [Hash(String, Service::Proxy)] The map of hosts.
|
43
|
+
# @parameter endpoint [Endpoint] The template endpoint to use to build the redirect location.
|
37
44
|
def initialize(app, hosts, endpoint)
|
38
45
|
super(app)
|
39
46
|
|
@@ -41,6 +48,8 @@ module Falcon
|
|
41
48
|
@endpoint = endpoint
|
42
49
|
end
|
43
50
|
|
51
|
+
# Lookup the appropriate host for the given request.
|
52
|
+
# @parameter request [Protocol::HTTP::Request]
|
44
53
|
def lookup(request)
|
45
54
|
# Trailing dot and port is ignored/normalized.
|
46
55
|
if authority = request.authority&.sub(/(\.)?(:\d+)?$/, '')
|
@@ -48,6 +57,8 @@ module Falcon
|
|
48
57
|
end
|
49
58
|
end
|
50
59
|
|
60
|
+
# Redirect the request if the authority matches a specific host.
|
61
|
+
# @parameter request [Protocol::HTTP::Request]
|
51
62
|
def call(request)
|
52
63
|
if host = lookup(request)
|
53
64
|
if @endpoint.default_port?
|
@@ -24,36 +24,44 @@ require 'async/logger'
|
|
24
24
|
require 'async/http/statistics'
|
25
25
|
|
26
26
|
module Falcon
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
@
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@logger.info(request) {"Headers: #{request.headers.to_h} from #{address.inspect}"}
|
39
|
-
|
40
|
-
task.annotate("#{request.method} #{request.path} from #{address.inspect}")
|
41
|
-
end
|
42
|
-
|
43
|
-
def call(request)
|
44
|
-
annotate(request)
|
45
|
-
|
46
|
-
statistics = Async::HTTP::Statistics.start
|
47
|
-
|
48
|
-
response = super
|
27
|
+
module Middleware
|
28
|
+
# A HTTP middleware for logging requests and responses.
|
29
|
+
class Verbose < Protocol::HTTP::Middleware
|
30
|
+
# Initialize the verbose middleware.
|
31
|
+
# @parameter app [Protocol::HTTP::Middleware] The middleware to wrap.
|
32
|
+
# @parameter logger [Console::Logger] The logger to use.
|
33
|
+
def initialize(app, logger = Async.logger)
|
34
|
+
super(app)
|
35
|
+
|
36
|
+
@logger = logger
|
37
|
+
end
|
49
38
|
|
50
|
-
|
51
|
-
|
39
|
+
# Log details of the incoming request.
|
40
|
+
def annotate(request)
|
41
|
+
task = Async::Task.current
|
42
|
+
address = request.remote_address
|
43
|
+
|
44
|
+
@logger.info(request) {"Headers: #{request.headers.to_h} from #{address.inspect}"}
|
52
45
|
|
53
|
-
|
46
|
+
task.annotate("#{request.method} #{request.path} from #{address.inspect}")
|
54
47
|
end
|
55
48
|
|
56
|
-
|
49
|
+
# Log details of the incoming request using {annotate} and wrap the response to log response details too.
|
50
|
+
def call(request)
|
51
|
+
annotate(request)
|
52
|
+
|
53
|
+
statistics = Async::HTTP::Statistics.start
|
54
|
+
|
55
|
+
response = super
|
56
|
+
|
57
|
+
statistics.wrap(response) do |statistics, error|
|
58
|
+
@logger.info(request) {"Responding with: #{response.status} #{response.headers.to_h}; #{statistics.inspect}"}
|
59
|
+
|
60
|
+
@logger.error(request) {"#{error.class}: #{error.message}"} if error
|
61
|
+
end
|
62
|
+
|
63
|
+
return response
|
64
|
+
end
|
57
65
|
end
|
58
66
|
end
|
59
67
|
end
|
@@ -23,7 +23,10 @@
|
|
23
23
|
require 'async/io/unix_endpoint'
|
24
24
|
|
25
25
|
module Falcon
|
26
|
+
# An endpoint suitable for proxing requests, typically via a unix pipe.
|
26
27
|
class ProxyEndpoint < Async::IO::Endpoint
|
28
|
+
# Initialize the proxy endpoint.
|
29
|
+
# @parameter endpoint [Async::IO::Endpoint] The endpoint which will be used for connecting/binding.
|
27
30
|
def initialize(endpoint, **options)
|
28
31
|
super(**options)
|
29
32
|
|
@@ -34,28 +37,44 @@ module Falcon
|
|
34
37
|
"\#<#{self.class} endpoint=#{@endpoint}>"
|
35
38
|
end
|
36
39
|
|
40
|
+
# The actual endpoint for I/O.
|
41
|
+
# @attribute [Async::IO::Endpoint]
|
37
42
|
attr :endpoint
|
38
43
|
|
44
|
+
# The protocol to use for this connection.
|
45
|
+
# @returns [Async::HTTP::Protocol] A specific protocol, e.g. {Async::HTTP::P}
|
39
46
|
def protocol
|
40
47
|
@options[:protocol]
|
41
48
|
end
|
42
49
|
|
50
|
+
# The scheme to use for this endpoint.
|
51
|
+
# e.g. `"http"`.
|
52
|
+
# @returns [String]
|
43
53
|
def scheme
|
44
54
|
@options[:scheme]
|
45
55
|
end
|
46
56
|
|
57
|
+
# The authority to use for this endpoint.
|
58
|
+
# e.g. `"myapp.com"`.
|
59
|
+
# @returns [String]
|
47
60
|
def authority
|
48
61
|
@options[:authority]
|
49
62
|
end
|
50
63
|
|
64
|
+
# Connect to the endpoint.
|
51
65
|
def connect(&block)
|
52
66
|
@endpoint.connect(&block)
|
53
67
|
end
|
54
68
|
|
69
|
+
# Bind to the endpoint.
|
55
70
|
def bind(&block)
|
56
71
|
@endpoint.bind(&block)
|
57
72
|
end
|
58
73
|
|
74
|
+
# Enumerate the endpoint.
|
75
|
+
# If the endpoint has multiple underlying endpoints, this will enumerate them individually.
|
76
|
+
# @yields {|endpoint| ...}
|
77
|
+
# @parameter endpoint [ProxyEndpoint]
|
59
78
|
def each
|
60
79
|
return to_enum unless block_given?
|
61
80
|
|
@@ -64,6 +83,8 @@ module Falcon
|
|
64
83
|
end
|
65
84
|
end
|
66
85
|
|
86
|
+
# Create a proxy unix endpoint with the specific path.
|
87
|
+
# @returns [ProxyEndpoint]
|
67
88
|
def self.unix(path, **options)
|
68
89
|
self.new(::Async::IO::Endpoint.unix(path), **options)
|
69
90
|
end
|
data/lib/falcon/server.rb
CHANGED
@@ -27,16 +27,22 @@ require 'protocol/http/content_encoding'
|
|
27
27
|
|
28
28
|
require 'async/http/cache'
|
29
29
|
|
30
|
-
require_relative 'verbose'
|
30
|
+
require_relative 'middleware/verbose'
|
31
|
+
|
31
32
|
require_relative 'adapters/rewindable'
|
32
33
|
require_relative 'adapters/rack'
|
33
34
|
|
34
35
|
module Falcon
|
36
|
+
# A server listening on a specific endpoint, hosting a specific middleware.
|
35
37
|
class Server < Async::HTTP::Server
|
38
|
+
# Wrap a rack application into a middleware suitable the server.
|
39
|
+
# @parameter rack_app [Proc | Object] A rack application/middleware.
|
40
|
+
# @parameter verbose [Boolean] Whether to add the {Verbose} middleware.
|
41
|
+
# @parameter cache [Boolean] Whether to add the {Async::HTTP::Cache} middleware.
|
36
42
|
def self.middleware(rack_app, verbose: false, cache: true)
|
37
43
|
::Protocol::HTTP::Middleware.build do
|
38
44
|
if verbose
|
39
|
-
use Verbose
|
45
|
+
use Middleware::Verbose
|
40
46
|
end
|
41
47
|
|
42
48
|
if cache
|
@@ -27,6 +27,7 @@ require 'async/io/shared_endpoint'
|
|
27
27
|
|
28
28
|
module Falcon
|
29
29
|
module Service
|
30
|
+
# Implements an application server using an internal clear-text proxy.
|
30
31
|
class Application < Proxy
|
31
32
|
def initialize(environment)
|
32
33
|
super
|
@@ -34,11 +35,20 @@ module Falcon
|
|
34
35
|
@bound_endpoint = nil
|
35
36
|
end
|
36
37
|
|
38
|
+
# The middleware that will be served by this application.
|
39
|
+
# @returns [Protocol::HTTP::Middleware]
|
37
40
|
def middleware
|
38
41
|
# In a multi-threaded container, we don't want to modify the shared evaluator's cache, so we create a new evaluator:
|
39
42
|
@environment.evaluator.middleware
|
40
43
|
end
|
41
44
|
|
45
|
+
# Number of instances to start.
|
46
|
+
# @returns [Integer | nil]
|
47
|
+
def count
|
48
|
+
@environment.evaluator.count
|
49
|
+
end
|
50
|
+
|
51
|
+
# Preload any resources specified by the environment.
|
42
52
|
def preload!
|
43
53
|
if scripts = @evaluator.preload
|
44
54
|
scripts.each do |path|
|
@@ -49,6 +59,8 @@ module Falcon
|
|
49
59
|
end
|
50
60
|
end
|
51
61
|
|
62
|
+
# Prepare the bound endpoint for the application instances.
|
63
|
+
# Invoke {preload!} to load shared resources into the parent process.
|
52
64
|
def start
|
53
65
|
Async.logger.info(self) {"Binding to #{self.endpoint}..."}
|
54
66
|
|
@@ -61,11 +73,20 @@ module Falcon
|
|
61
73
|
super
|
62
74
|
end
|
63
75
|
|
76
|
+
# Setup instances of the application into the container.
|
77
|
+
# @parameter container [Async::Container::Generic]
|
64
78
|
def setup(container)
|
65
79
|
protocol = self.protocol
|
66
80
|
scheme = self.scheme
|
67
81
|
|
68
|
-
|
82
|
+
run_options = {
|
83
|
+
name: self.name,
|
84
|
+
restart: true,
|
85
|
+
}
|
86
|
+
|
87
|
+
run_options[:count] = count unless count.nil?
|
88
|
+
|
89
|
+
container.run(**run_options) do |instance|
|
69
90
|
Async(logger: logger) do |task|
|
70
91
|
Async.logger.info(self) {"Starting application server for #{self.root}..."}
|
71
92
|
|
@@ -82,6 +103,7 @@ module Falcon
|
|
82
103
|
super
|
83
104
|
end
|
84
105
|
|
106
|
+
# Close the bound endpoint.
|
85
107
|
def stop
|
86
108
|
@bound_endpoint&.close
|
87
109
|
@bound_endpoint = nil
|