falcon 0.42.3 → 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/bake/falcon/supervisor.rb +3 -1
- data/changes.md +22 -0
- data/lib/falcon/command/host.rb +7 -50
- data/lib/falcon/command/paths.rb +2 -19
- data/lib/falcon/command/proxy.rb +21 -33
- data/lib/falcon/command/redirect.rb +22 -33
- data/lib/falcon/command/serve.rb +44 -82
- data/lib/falcon/command/supervisor.rb +2 -19
- data/lib/falcon/command/top.rb +2 -19
- data/lib/falcon/command/virtual.rb +16 -41
- data/lib/falcon/command.rb +3 -19
- data/lib/falcon/configuration.rb +28 -142
- data/lib/falcon/endpoint.rb +2 -19
- 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/environment.rb +13 -0
- data/lib/falcon/middleware/proxy.rb +3 -20
- data/lib/falcon/middleware/redirect.rb +2 -19
- data/lib/falcon/middleware/verbose.rb +2 -19
- data/lib/falcon/proxy_endpoint.rb +2 -19
- data/lib/falcon/railtie.rb +10 -0
- data/lib/falcon/server.rb +2 -19
- data/lib/falcon/service/server.rb +84 -0
- data/lib/falcon/service/supervisor.rb +5 -21
- data/lib/falcon/{controller → service}/virtual.rb +72 -36
- data/lib/falcon/tls.rb +2 -19
- data/lib/falcon/version.rb +3 -20
- data/lib/falcon.rb +5 -19
- data/lib/rack/handler/falcon.rb +4 -0
- data/lib/rackup/handler/falcon.rb +83 -0
- data/license.md +41 -0
- data/readme.md +60 -0
- data.tar.gz.sig +0 -0
- metadata +37 -117
- metadata.gz.sig +0 -0
- data/lib/.DS_Store +0 -0
- data/lib/falcon/controller/host.rb +0 -72
- data/lib/falcon/controller/proxy.rb +0 -126
- data/lib/falcon/controller/redirect.rb +0 -76
- data/lib/falcon/controller/serve.rb +0 -126
- data/lib/falcon/environments/application.rb +0 -72
- data/lib/falcon/environments/lets_encrypt_tls.rb +0 -47
- data/lib/falcon/environments/proxy.rb +0 -37
- data/lib/falcon/environments/rack.rb +0 -50
- data/lib/falcon/environments/self_signed_tls.rb +0 -55
- data/lib/falcon/environments/supervisor.rb +0 -51
- data/lib/falcon/environments/tls.rb +0 -103
- data/lib/falcon/environments.rb +0 -31
- data/lib/falcon/service/application.rb +0 -115
- data/lib/falcon/service/generic.rb +0 -78
- data/lib/falcon/service/proxy.rb +0 -66
- data/lib/falcon/services.rb +0 -99
data/lib/falcon/configuration.rb
CHANGED
@@ -1,26 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
10
|
-
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
# THE SOFTWARE.
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2019-2024, by Samuel Williams.
|
5
|
+
# Copyright, 2019, by Sho Ito.
|
22
6
|
|
23
|
-
require '
|
7
|
+
require 'async/service'
|
24
8
|
|
25
9
|
module Falcon
|
26
10
|
# Manages environments which describes how to host a specific application.
|
@@ -41,177 +25,79 @@ module Falcon
|
|
41
25
|
# end
|
42
26
|
# ~~~
|
43
27
|
#
|
44
|
-
class Configuration
|
45
|
-
# Initialize an empty configuration.
|
46
|
-
def initialize
|
47
|
-
@environments = {}
|
48
|
-
end
|
49
|
-
|
50
|
-
# The map of named environments.
|
51
|
-
# @attribute [Hash(String, Build::Environment)]
|
52
|
-
attr :environments
|
53
|
-
|
54
|
-
# Enumerate all environments that have the specified key.
|
55
|
-
# @parameter key [Symbol] Filter environments that don't have this key.
|
56
|
-
def each(key = :authority)
|
57
|
-
return to_enum(key) unless block_given?
|
58
|
-
|
59
|
-
@environments.each do |name, environment|
|
60
|
-
environment = environment.flatten
|
61
|
-
|
62
|
-
if environment.include?(key)
|
63
|
-
yield environment
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Add the named environment to the configuration.
|
69
|
-
def add(environment)
|
70
|
-
name = environment.name
|
71
|
-
|
72
|
-
unless name
|
73
|
-
raise ArgumentError, "Environment name is nil #{environment.inspect}"
|
74
|
-
end
|
75
|
-
|
76
|
-
environment = environment.flatten
|
77
|
-
|
78
|
-
raise KeyError.new("#{name.inspect} is already set", key: name) if @environments.key?(name)
|
79
|
-
|
80
|
-
@environments[name] = environment
|
81
|
-
end
|
82
|
-
|
28
|
+
class Configuration < ::Async::Service::Configuration
|
83
29
|
# Load the specified configuration file. See {Loader#load_file} for more details.
|
84
30
|
def load_file(path)
|
85
31
|
Loader.load_file(self, path)
|
86
32
|
end
|
87
33
|
|
88
34
|
# The domain specific language for loading configuration files.
|
89
|
-
class Loader
|
90
|
-
# Initialize the loader, attached to a specific configuration instance.
|
91
|
-
# Any environments generated by the loader will be added to the configuration.
|
92
|
-
# @parameter configuration [Configuration]
|
93
|
-
# @parameter root [String] The file-system root path for relative path computations.
|
94
|
-
def initialize(configuration, root = nil)
|
95
|
-
@loaded = {}
|
96
|
-
@configuration = configuration
|
97
|
-
@environments = {}
|
98
|
-
@root = root
|
99
|
-
end
|
100
|
-
|
101
|
-
# The file-system root path which is injected into the environments as required.
|
102
|
-
# @attribute [String]
|
103
|
-
attr :root
|
104
|
-
|
105
|
-
# The attached configuration instance.
|
106
|
-
# @attribute [Configuration]
|
107
|
-
attr :configuration
|
108
|
-
|
109
|
-
# Load the specified file into the given configuration.
|
110
|
-
# @parameter configuration [Configuration]
|
111
|
-
# @oaram path [String] The path to the configuration file, e.g. `falcon.rb`.
|
112
|
-
def self.load_file(configuration, path)
|
113
|
-
path = File.realpath(path)
|
114
|
-
root = File.dirname(path)
|
115
|
-
|
116
|
-
loader = self.new(configuration, root)
|
117
|
-
|
118
|
-
loader.instance_eval(File.read(path), path)
|
119
|
-
end
|
120
|
-
|
35
|
+
class Loader < ::Async::Service::Loader
|
121
36
|
# Load specific features into the current configuration.
|
122
37
|
#
|
123
|
-
#
|
124
|
-
#
|
38
|
+
# @deprecated Use `require` instead.
|
125
39
|
# @parameter features [Array(Symbol)] The features to load.
|
126
40
|
def load(*features)
|
127
41
|
features.each do |feature|
|
128
|
-
next if @loaded.include?(feature)
|
129
|
-
|
130
42
|
case feature
|
131
43
|
when Symbol
|
132
|
-
|
133
|
-
|
134
|
-
self.instance_eval(File.read(relative_path), relative_path)
|
135
|
-
|
136
|
-
@loaded[feature] = relative_path
|
137
|
-
when Module
|
138
|
-
feature.load(self)
|
139
|
-
|
140
|
-
@loaded[feature] = feature
|
44
|
+
require File.join(__dir__, "environment", "#{feature}.rb")
|
141
45
|
else
|
142
46
|
raise LoadError, "Unsure about how to load #{feature}!"
|
143
47
|
end
|
144
48
|
end
|
145
49
|
end
|
146
50
|
|
147
|
-
# Add the named environment, with zero or more parent environments, defined using the specified `block`.
|
148
|
-
# @parameter name [String] The name of the environment.
|
149
|
-
# @parameter parents [Array(Symbol)] The names of the parent environments to inherit.
|
150
|
-
# @yields {...} The block that will generate the environment.
|
151
|
-
def environment(name, *parents, &block)
|
152
|
-
raise KeyError.new("#{name} is already set", key: name) if @environments.key?(name)
|
153
|
-
@environments[name] = merge(name, *parents, &block)
|
154
|
-
end
|
155
|
-
|
156
51
|
# Define a host with the specified name.
|
157
52
|
# Adds `root` and `authority` keys.
|
53
|
+
# @deprecated Use `service` and `include Falcon::Environment::Server` instead.
|
158
54
|
# @parameter name [String] The name of the environment, usually a hostname.
|
159
55
|
def host(name, *parents, &block)
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
environment[:authority] = name
|
164
|
-
|
165
|
-
@configuration.add(environment.flatten)
|
56
|
+
@configuration.add(
|
57
|
+
merge(*parents, name: name, root: @root, authority: name, &block)
|
58
|
+
)
|
166
59
|
end
|
167
60
|
|
168
61
|
# Define a proxy with the specified name.
|
169
62
|
# Adds `root` and `authority` keys.
|
63
|
+
# @deprecated Use `service` and `include Falcon::Environment::Proxy` instead.
|
170
64
|
# @parameter name [String] The name of the environment, usually a hostname.
|
171
65
|
def proxy(name, *parents, &block)
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
environment[:authority] = name
|
176
|
-
|
177
|
-
@configuration.add(environment.flatten)
|
66
|
+
@configuration.add(
|
67
|
+
merge(:proxy, *parents, name: name, root: @root, authority: name, &block)
|
68
|
+
)
|
178
69
|
end
|
179
70
|
|
180
71
|
# Define a rack application with the specified name.
|
181
72
|
# Adds `root` and `authority` keys.
|
73
|
+
# @deprecated Use `service` and `include Falcon::Environment::Rack` instead.
|
182
74
|
# @parameter name [String] The name of the environment, usually a hostname.
|
183
75
|
def rack(name, *parents, &block)
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
environment[:authority] = name
|
188
|
-
|
189
|
-
@configuration.add(environment.flatten)
|
76
|
+
@configuration.add(
|
77
|
+
merge(:rack, *parents, name: name, root: @root, authority: name, &block)
|
78
|
+
)
|
190
79
|
end
|
191
80
|
|
192
81
|
# Define a supervisor instance
|
193
|
-
#
|
82
|
+
# @deprecated Use `service` and `include Falcon::Environment::Supervisor` instead.
|
194
83
|
def supervisor(&block)
|
195
84
|
name = File.join(@root, "supervisor")
|
196
|
-
environment = merge(name, :supervisor, &block)
|
197
85
|
|
198
|
-
|
199
|
-
|
200
|
-
|
86
|
+
@configuration.add(
|
87
|
+
merge(:supervisor, name: name, root: @root, &block)
|
88
|
+
)
|
201
89
|
end
|
202
90
|
|
203
91
|
private
|
204
92
|
|
205
93
|
# Build a new environment with the specified name and the given parents.
|
206
94
|
# @parameter name [String]
|
207
|
-
# @parameter parents [Array(
|
95
|
+
# @parameter parents [Array(Symbol)]
|
208
96
|
# @yields {...} The block that will generate the environment.
|
209
|
-
def merge(
|
210
|
-
|
211
|
-
|
212
|
-
parent = Build::Environment.combine(*environments)
|
97
|
+
def merge(*parents, **initial, &block)
|
98
|
+
facets = parents.map{|parent| Environment::LEGACY_ENVIRONMENTS.fetch(parent)}
|
213
99
|
|
214
|
-
|
100
|
+
::Async::Service::Environment.build(*facets, **initial, &block)
|
215
101
|
end
|
216
102
|
end
|
217
103
|
end
|
data/lib/falcon/endpoint.rb
CHANGED
@@ -1,24 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
10
|
-
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be included in
|
13
|
-
# all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
# THE SOFTWARE.
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2018-2023, by Samuel Williams.
|
22
5
|
|
23
6
|
require 'async/http/endpoint'
|
24
7
|
require 'localhost/authority'
|
@@ -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
|