falcon 0.43.0 → 0.44.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/changes.md +22 -0
- data/lib/falcon/command/host.rb +6 -32
- data/lib/falcon/command/proxy.rb +20 -15
- data/lib/falcon/command/redirect.rb +21 -15
- data/lib/falcon/command/serve.rb +41 -65
- data/lib/falcon/command/top.rb +1 -1
- data/lib/falcon/command/virtual.rb +15 -23
- data/lib/falcon/configuration.rb +26 -124
- data/lib/falcon/environment/application.rb +60 -0
- data/lib/falcon/environment/lets_encrypt_tls.rb +34 -0
- data/lib/falcon/environment/proxy.rb +109 -0
- data/lib/falcon/environment/rack.rb +20 -0
- data/lib/falcon/environment/rackup.rb +26 -0
- data/lib/falcon/environment/redirect.rb +50 -0
- data/lib/falcon/environment/self_signed_tls.rb +45 -0
- data/lib/falcon/environment/server.rb +69 -0
- data/lib/falcon/environment/supervisor.rb +40 -0
- data/lib/falcon/environment/tls.rb +97 -0
- data/lib/falcon/{environments.rb → environment.rb} +3 -4
- data/lib/falcon/service/server.rb +84 -0
- data/lib/falcon/service/supervisor.rb +4 -3
- data/lib/falcon/{controller → service}/virtual.rb +71 -18
- data/lib/falcon/version.rb +2 -2
- data/license.md +2 -0
- data.tar.gz.sig +0 -0
- metadata +24 -26
- metadata.gz.sig +0 -0
- data/lib/.DS_Store +0 -0
- data/lib/falcon/controller/host.rb +0 -55
- data/lib/falcon/controller/proxy.rb +0 -109
- data/lib/falcon/controller/redirect.rb +0 -59
- data/lib/falcon/controller/serve.rb +0 -110
- data/lib/falcon/environments/application.rb +0 -56
- data/lib/falcon/environments/lets_encrypt_tls.rb +0 -30
- data/lib/falcon/environments/proxy.rb +0 -22
- data/lib/falcon/environments/rack.rb +0 -33
- data/lib/falcon/environments/self_signed_tls.rb +0 -38
- data/lib/falcon/environments/supervisor.rb +0 -34
- data/lib/falcon/environments/tls.rb +0 -86
- data/lib/falcon/service/application.rb +0 -99
- data/lib/falcon/service/generic.rb +0 -61
- data/lib/falcon/service/proxy.rb +0 -49
- data/lib/falcon/services.rb +0 -82
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
|
+
# Copyright, 2020, by Daniel Evans.
|
6
|
+
|
7
|
+
require_relative 'server'
|
8
|
+
require_relative '../proxy_endpoint'
|
9
|
+
|
10
|
+
module Falcon
|
11
|
+
module Environment
|
12
|
+
# Provides an environment for hosting a web application that uses TLS.
|
13
|
+
module Application
|
14
|
+
include Server
|
15
|
+
|
16
|
+
# The middleware stack for the application.
|
17
|
+
# @returns [Protocol::HTTP::Middleware]
|
18
|
+
def middleware
|
19
|
+
::Protocol::HTTP::Middleware::HelloWorld
|
20
|
+
end
|
21
|
+
|
22
|
+
# The scheme to use to communicate with the application.
|
23
|
+
# @returns [String]
|
24
|
+
def scheme
|
25
|
+
'https'
|
26
|
+
end
|
27
|
+
|
28
|
+
# The protocol to use to communicate with the application.
|
29
|
+
#
|
30
|
+
# Typically one of {Async::HTTP::Protocol::HTTP1} or {Async::HTTP::Protocl::HTTP2}.
|
31
|
+
#
|
32
|
+
# @returns [Async::HTTP::Protocol]
|
33
|
+
def protocol
|
34
|
+
Async::HTTP::Protocol::HTTP2
|
35
|
+
end
|
36
|
+
|
37
|
+
# The IPC path to use for communication with the application.
|
38
|
+
# @returns [String]
|
39
|
+
def ipc_path
|
40
|
+
::File.expand_path("application.ipc", root)
|
41
|
+
end
|
42
|
+
|
43
|
+
# The endpoint that will be used for communicating with the application server.
|
44
|
+
# @returns [Async::IO::Endpoint]
|
45
|
+
def endpoint
|
46
|
+
::Falcon::ProxyEndpoint.unix(ipc_path,
|
47
|
+
protocol: protocol,
|
48
|
+
scheme: scheme,
|
49
|
+
authority: authority
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Number of instances to start.
|
54
|
+
# @returns [Integer | nil]
|
55
|
+
def count
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2020-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require_relative 'tls'
|
7
|
+
require_relative '../environment'
|
8
|
+
|
9
|
+
module Falcon
|
10
|
+
module Environment
|
11
|
+
# Provides an environment that uses "Lets Encrypt" for TLS.
|
12
|
+
module LetsEncryptTLS
|
13
|
+
# The Lets Encrypt certificate store path.
|
14
|
+
# @parameter [String]
|
15
|
+
def lets_encrypt_root
|
16
|
+
'/etc/letsencrypt/live'
|
17
|
+
end
|
18
|
+
|
19
|
+
# The public certificate path.
|
20
|
+
# @attribute [String]
|
21
|
+
def ssl_certificate_path
|
22
|
+
File.join(lets_encrypt_root, authority, "fullchain.pem")
|
23
|
+
end
|
24
|
+
|
25
|
+
# The private key path.
|
26
|
+
# @attribute [String]
|
27
|
+
def ssl_private_key_path
|
28
|
+
File.join(lets_encrypt_root, authority, "privkey.pem")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
LEGACY_ENVIRONMENTS[:tls] = TLS
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require_relative 'server'
|
7
|
+
require_relative '../tls'
|
8
|
+
require_relative '../middleware/proxy'
|
9
|
+
require_relative '../environment'
|
10
|
+
|
11
|
+
module Falcon
|
12
|
+
module Environment
|
13
|
+
# Provides an environment for hosting a TLS-capable reverse proxy using SNI.
|
14
|
+
module Proxy
|
15
|
+
include Server
|
16
|
+
|
17
|
+
# The host that this proxy will receive connections for.
|
18
|
+
def url
|
19
|
+
"https://[::]:443"
|
20
|
+
end
|
21
|
+
|
22
|
+
# The default SSL session identifier.
|
23
|
+
def tls_session_id
|
24
|
+
"falcon"
|
25
|
+
end
|
26
|
+
|
27
|
+
# The services we will proxy to.
|
28
|
+
# @returns [Array(Async::Service::Environment)]
|
29
|
+
def environments
|
30
|
+
[]
|
31
|
+
end
|
32
|
+
|
33
|
+
# The hosts we will proxy to. This is a hash of SNI authority -> evaluator.
|
34
|
+
# @returns [Hash(String, Async::Service::Environment::Evaluator)]
|
35
|
+
def hosts
|
36
|
+
hosts = {}
|
37
|
+
|
38
|
+
environments.each do |environment|
|
39
|
+
evaluator = environment.evaluator
|
40
|
+
|
41
|
+
# next unless environment.implements?(Falcon::Environment::Application)
|
42
|
+
if evaluator.key?(:authority) and evaluator.key?(:ssl_context) and evaluator.key?(:endpoint)
|
43
|
+
Console.info(self) {"Proxying #{self.url} to #{evaluator.authority} using #{evaluator.endpoint}"}
|
44
|
+
hosts[evaluator.authority] = evaluator
|
45
|
+
|
46
|
+
if RUBY_VERSION < '3.1'
|
47
|
+
# Ensure the SSL context is set up before forking - it's buggy on Ruby < 3.1:
|
48
|
+
evaluator.ssl_context
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
return hosts
|
54
|
+
end
|
55
|
+
|
56
|
+
# Look up the host context for the given hostname, and update the socket hostname if necessary.
|
57
|
+
# @parameter socket [OpenSSL::SSL::SSLSocket] The incoming connection.
|
58
|
+
# @parameter hostname [String] The negotiated hostname.
|
59
|
+
def host_context(socket, hostname)
|
60
|
+
hosts = self.hosts
|
61
|
+
|
62
|
+
if host = hosts[hostname]
|
63
|
+
Console.logger.debug(self) {"Resolving #{hostname} -> #{host}"}
|
64
|
+
|
65
|
+
socket.hostname = hostname
|
66
|
+
|
67
|
+
return host.ssl_context
|
68
|
+
else
|
69
|
+
Console.logger.warn(self, hosts: hosts.keys) {"Unable to resolve #{hostname}!"}
|
70
|
+
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generate an SSL context which delegates to {host_context} to multiplex based on hostname.
|
76
|
+
def ssl_context
|
77
|
+
@server_context ||= OpenSSL::SSL::SSLContext.new.tap do |context|
|
78
|
+
context.servername_cb = Proc.new do |socket, hostname|
|
79
|
+
self.host_context(socket, hostname)
|
80
|
+
end
|
81
|
+
|
82
|
+
context.session_id_context = @session_id
|
83
|
+
|
84
|
+
context.ssl_version = :TLSv1_2_server
|
85
|
+
|
86
|
+
context.set_params(
|
87
|
+
ciphers: ::Falcon::TLS::SERVER_CIPHERS,
|
88
|
+
verify_mode: ::OpenSSL::SSL::VERIFY_NONE,
|
89
|
+
)
|
90
|
+
|
91
|
+
context.setup
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# The endpoint the server will bind to.
|
96
|
+
def endpoint
|
97
|
+
super.with(
|
98
|
+
ssl_context: self.ssl_context,
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
def middleware
|
103
|
+
return Middleware::Proxy.new(Middleware::BadRequest, self.hosts)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
LEGACY_ENVIRONMENTS[:proxy] = Proxy
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require_relative 'application'
|
7
|
+
require_relative 'rackup'
|
8
|
+
require_relative '../environment'
|
9
|
+
|
10
|
+
module Falcon
|
11
|
+
module Environment
|
12
|
+
# Provides an environment for hosting a web application that use a Rackup `config.ru` file.
|
13
|
+
module Rack
|
14
|
+
include Application
|
15
|
+
include Rackup
|
16
|
+
end
|
17
|
+
|
18
|
+
LEGACY_ENVIRONMENTS[:rack] = Rack
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'rack/builder'
|
7
|
+
require_relative '../server'
|
8
|
+
|
9
|
+
module Falcon
|
10
|
+
module Environment
|
11
|
+
# Provides an environment for hosting loading a Rackup `config.ru` file.
|
12
|
+
module Rackup
|
13
|
+
def rackup_path
|
14
|
+
'config.ru'
|
15
|
+
end
|
16
|
+
|
17
|
+
def rack_app
|
18
|
+
::Rack::Builder.parse_file(rackup_path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def middleware
|
22
|
+
::Falcon::Server.middleware(rack_app, verbose: verbose, cache: cache)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2020-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require_relative 'server'
|
7
|
+
require_relative '../middleware/redirect'
|
8
|
+
|
9
|
+
module Falcon
|
10
|
+
module Environment
|
11
|
+
# Provides an environment for redirecting insecure web traffic to a secure endpoint.
|
12
|
+
module Redirect
|
13
|
+
include Server
|
14
|
+
|
15
|
+
def redirect_url
|
16
|
+
"https://[::]:443"
|
17
|
+
end
|
18
|
+
|
19
|
+
def redirect_endpoint
|
20
|
+
Async::HTTP::Endpoint.parse(redirect_url)
|
21
|
+
end
|
22
|
+
|
23
|
+
# The services we will redirect to.
|
24
|
+
# @returns [Array(Async::Service::Environment)]
|
25
|
+
def environments
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
|
29
|
+
def hosts
|
30
|
+
hosts = {}
|
31
|
+
|
32
|
+
environments.each do |environment|
|
33
|
+
evaluator = environment.evaluator
|
34
|
+
|
35
|
+
if environment.implements?(Falcon::Environment::Application)
|
36
|
+
Console.info(self) {"Redirecting #{self.url} to #{evaluator.authority}"}
|
37
|
+
hosts[evaluator.authority] = evaluator
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
return hosts
|
42
|
+
end
|
43
|
+
|
44
|
+
# Load the {Middleware::Redirect} application with the specified hosts.
|
45
|
+
def middleware
|
46
|
+
Middleware::Redirect.new(Middleware::NotFound, hosts, redirect_endpoint)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'localhost/authority'
|
7
|
+
require_relative 'tls'
|
8
|
+
require_relative '../environment'
|
9
|
+
|
10
|
+
module Falcon
|
11
|
+
module Environment
|
12
|
+
# Provides an environment that exposes a self-signed TLS certificate using the `localhost` gem.
|
13
|
+
module SelfSignedTLS
|
14
|
+
# The default session identifier for the session cache.
|
15
|
+
# @returns [String]
|
16
|
+
def ssl_session_id
|
17
|
+
"falcon"
|
18
|
+
end
|
19
|
+
|
20
|
+
# The SSL context to use for incoming connections.
|
21
|
+
# @returns [OpenSSL::SSL::SSLContext]
|
22
|
+
def ssl_context
|
23
|
+
contexts = Localhost::Authority.fetch(authority)
|
24
|
+
|
25
|
+
contexts.server_context.tap do |context|
|
26
|
+
context.alpn_select_cb = lambda do |protocols|
|
27
|
+
if protocols.include? "h2"
|
28
|
+
return "h2"
|
29
|
+
elsif protocols.include? "http/1.1"
|
30
|
+
return "http/1.1"
|
31
|
+
elsif protocols.include? "http/1.0"
|
32
|
+
return "http/1.0"
|
33
|
+
else
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context.session_id_context = ssl_session_id
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
LEGACY_ENVIRONMENTS[:self_signed_tls] = SelfSignedTLS
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'async/service/generic'
|
7
|
+
require 'async/http/endpoint'
|
8
|
+
|
9
|
+
require_relative '../service/server'
|
10
|
+
require_relative '../server'
|
11
|
+
|
12
|
+
module Falcon
|
13
|
+
module Environment
|
14
|
+
# Provides an environment for hosting a web application that uses a Falcon server.
|
15
|
+
module Server
|
16
|
+
# The service class to use for the proxy.
|
17
|
+
# @returns [Class]
|
18
|
+
def service_class
|
19
|
+
Service::Server
|
20
|
+
end
|
21
|
+
|
22
|
+
# The server authority. Defaults to the server name.
|
23
|
+
# @returns [String]
|
24
|
+
def authority
|
25
|
+
self.name
|
26
|
+
end
|
27
|
+
|
28
|
+
# Options to use when creating the container.
|
29
|
+
def container_options
|
30
|
+
{restart: true}
|
31
|
+
end
|
32
|
+
|
33
|
+
# The host that this server will receive connections for.
|
34
|
+
def url
|
35
|
+
"http://[::]:9292"
|
36
|
+
end
|
37
|
+
|
38
|
+
def timeout
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# The upstream endpoint that will handle incoming requests.
|
43
|
+
# @returns [Async::HTTP::Endpoint]
|
44
|
+
def endpoint
|
45
|
+
::Async::HTTP::Endpoint.parse(url).with(
|
46
|
+
reuse_address: true,
|
47
|
+
timeout: timeout,
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
def verbose
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
def cache
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
def client_endpoint
|
60
|
+
::Async::HTTP::Endpoint.parse(url)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Any scripts to preload before starting the server.
|
64
|
+
def preload
|
65
|
+
[]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require_relative '../service/supervisor'
|
7
|
+
require_relative '../environment'
|
8
|
+
|
9
|
+
module Falcon
|
10
|
+
module Environment
|
11
|
+
# Provides an environment for hosting a supervisor which can monitor multiple applications.
|
12
|
+
module Supervisor
|
13
|
+
# The name of the supervisor
|
14
|
+
# @returns [String]
|
15
|
+
def name
|
16
|
+
"supervisor"
|
17
|
+
end
|
18
|
+
|
19
|
+
# The IPC path to use for communication with the supervisor.
|
20
|
+
# @returns [String]
|
21
|
+
def ipc_path
|
22
|
+
::File.expand_path("supervisor.ipc", root)
|
23
|
+
end
|
24
|
+
|
25
|
+
# The endpoint the supervisor will bind to.
|
26
|
+
# @returns [Async::IO::Endpoint]
|
27
|
+
def endpoint
|
28
|
+
Async::IO::Endpoint.unix(ipc_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
# The service class to use for the supervisor.
|
32
|
+
# @returns [Class]
|
33
|
+
def service_class
|
34
|
+
::Falcon::Service::Supervisor
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
LEGACY_ENVIRONMENTS[:supervisor] = Supervisor
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require_relative '../tls'
|
7
|
+
require_relative '../environment'
|
8
|
+
|
9
|
+
module Falcon
|
10
|
+
module Environment
|
11
|
+
# Provides an environment that exposes a TLS context for hosting a secure web application.
|
12
|
+
module TLS
|
13
|
+
# The default session identifier for the session cache.
|
14
|
+
# @returns [String]
|
15
|
+
def ssl_session_id
|
16
|
+
"falcon"
|
17
|
+
end
|
18
|
+
|
19
|
+
# The supported ciphers.
|
20
|
+
# @returns [Array(String)]
|
21
|
+
def ssl_ciphers
|
22
|
+
Falcon::TLS::SERVER_CIPHERS
|
23
|
+
end
|
24
|
+
|
25
|
+
# The public certificate path.
|
26
|
+
# @returns [String]
|
27
|
+
def ssl_certificate_path
|
28
|
+
File.expand_path("ssl/certificate.pem", root)
|
29
|
+
end
|
30
|
+
|
31
|
+
# The list of certificates loaded from that path.
|
32
|
+
# @returns [Array(OpenSSL::X509::Certificate)]
|
33
|
+
def ssl_certificates
|
34
|
+
OpenSSL::X509::Certificate.load_file(ssl_certificate_path)
|
35
|
+
end
|
36
|
+
|
37
|
+
# The main certificate.
|
38
|
+
# @returns [OpenSSL::X509::Certificate]
|
39
|
+
def ssl_certificate
|
40
|
+
ssl_certificates[0]
|
41
|
+
end
|
42
|
+
|
43
|
+
# The certificate chain.
|
44
|
+
# @returns [Array(OpenSSL::X509::Certificate)]
|
45
|
+
def ssl_certificate_chain
|
46
|
+
ssl_certificates[1..-1]
|
47
|
+
end
|
48
|
+
|
49
|
+
# The private key path.
|
50
|
+
# @returns [String]
|
51
|
+
def ssl_private_key_path
|
52
|
+
File.expand_path("ssl/private.key", root)
|
53
|
+
end
|
54
|
+
|
55
|
+
# The private key.
|
56
|
+
# @returns [OpenSSL::PKey::RSA]
|
57
|
+
def ssl_private_key
|
58
|
+
OpenSSL::PKey::RSA.new(File.read(ssl_private_key_path))
|
59
|
+
end
|
60
|
+
|
61
|
+
# The SSL context to use for incoming connections.
|
62
|
+
# @returns [OpenSSL::SSL::SSLContext]
|
63
|
+
def ssl_context
|
64
|
+
OpenSSL::SSL::SSLContext.new.tap do |context|
|
65
|
+
context.add_certificate(ssl_certificate, ssl_private_key, ssl_certificate_chain)
|
66
|
+
|
67
|
+
context.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT
|
68
|
+
context.session_id_context = ssl_session_id
|
69
|
+
|
70
|
+
context.alpn_select_cb = lambda do |protocols|
|
71
|
+
if protocols.include? "h2"
|
72
|
+
return "h2"
|
73
|
+
elsif protocols.include? "http/1.1"
|
74
|
+
return "http/1.1"
|
75
|
+
elsif protocols.include? "http/1.0"
|
76
|
+
return "http/1.0"
|
77
|
+
else
|
78
|
+
return nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# TODO Ruby 2.4 requires using ssl_version.
|
83
|
+
context.ssl_version = :TLSv1_2_server
|
84
|
+
|
85
|
+
context.set_params(
|
86
|
+
ciphers: ssl_ciphers,
|
87
|
+
verify_mode: OpenSSL::SSL::VERIFY_NONE,
|
88
|
+
)
|
89
|
+
|
90
|
+
context.setup
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
LEGACY_ENVIRONMENTS[:tls] = TLS
|
96
|
+
end
|
97
|
+
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2019-
|
5
|
-
|
6
|
-
require 'build/environment'
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
7
5
|
|
8
6
|
module Falcon
|
9
7
|
# Pre-defined environments for hosting web applications.
|
10
8
|
#
|
11
9
|
# See {Configuration::Loader#load} for more details.
|
12
|
-
module
|
10
|
+
module Environment
|
11
|
+
LEGACY_ENVIRONMENTS = {}
|
13
12
|
end
|
14
13
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2020-2024, by Samuel Williams.
|
5
|
+
# Copyright, 2020, by Michael Adams.
|
6
|
+
|
7
|
+
require 'async/service/generic'
|
8
|
+
require 'async/http/endpoint'
|
9
|
+
|
10
|
+
require_relative '../server'
|
11
|
+
|
12
|
+
module Falcon
|
13
|
+
module Service
|
14
|
+
class Server < Async::Service::Generic
|
15
|
+
def initialize(...)
|
16
|
+
super
|
17
|
+
|
18
|
+
@bound_endpoint = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Preload any resources specified by the environment.
|
22
|
+
def preload!
|
23
|
+
root = @evaluator.root
|
24
|
+
|
25
|
+
if scripts = @evaluator.preload
|
26
|
+
scripts = Array(scripts)
|
27
|
+
|
28
|
+
scripts.each do |path|
|
29
|
+
Console.logger.info(self) {"Preloading #{path}..."}
|
30
|
+
full_path = File.expand_path(path, root)
|
31
|
+
load(full_path)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Prepare the bound endpoint for the server.
|
37
|
+
def start
|
38
|
+
@endpoint = @evaluator.endpoint
|
39
|
+
|
40
|
+
Sync do
|
41
|
+
@bound_endpoint = @endpoint.bound
|
42
|
+
end
|
43
|
+
|
44
|
+
preload!
|
45
|
+
|
46
|
+
Console.logger.info(self) {"Starting #{self.name} on #{@endpoint}"}
|
47
|
+
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
# Setup the container with the application instance.
|
52
|
+
# @parameter container [Async::Container::Generic]
|
53
|
+
def setup(container)
|
54
|
+
container_options = @evaluator.container_options
|
55
|
+
|
56
|
+
container.run(name: self.name, **container_options) do |instance|
|
57
|
+
evaluator = @environment.evaluator
|
58
|
+
|
59
|
+
Async do |task|
|
60
|
+
server = Falcon::Server.new(evaluator.middleware, @bound_endpoint, protocol: @endpoint.protocol, scheme: @endpoint.scheme)
|
61
|
+
|
62
|
+
server.run
|
63
|
+
|
64
|
+
instance.ready!
|
65
|
+
|
66
|
+
task.children.each(&:wait)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Close the bound endpoint.
|
72
|
+
def stop(...)
|
73
|
+
if @bound_endpoint
|
74
|
+
@bound_endpoint.close
|
75
|
+
@bound_endpoint = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
@endpoint = nil
|
79
|
+
|
80
|
+
super
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -1,21 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Released under the MIT License.
|
4
|
-
# Copyright, 2019-
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
5
|
|
6
6
|
require 'process/metrics'
|
7
7
|
require 'json'
|
8
8
|
|
9
9
|
require 'async/io/endpoint'
|
10
10
|
require 'async/io/shared_endpoint'
|
11
|
+
require 'async/service/generic'
|
11
12
|
|
12
13
|
module Falcon
|
13
14
|
module Service
|
14
15
|
# Implements a host supervisor which can restart the host services and provide various metrics about the running processes.
|
15
|
-
class Supervisor < Generic
|
16
|
+
class Supervisor < Async::Service::Generic
|
16
17
|
# Initialize the supervisor using the given environment.
|
17
18
|
# @parameter environment [Build::Environment]
|
18
|
-
def initialize(
|
19
|
+
def initialize(...)
|
19
20
|
super
|
20
21
|
|
21
22
|
@bound_endpoint = nil
|