falcon 0.43.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -1
- data/changes.md +36 -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 +44 -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 +28 -30
- 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
|
+
::Protocol::Rack::Adapter.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
|