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
data/lib/falcon/command/paths.rb
CHANGED
@@ -24,13 +24,17 @@ require_relative '../configuration'
|
|
24
24
|
|
25
25
|
module Falcon
|
26
26
|
module Command
|
27
|
+
# A helper for resolving wildcard configuration paths.
|
27
28
|
module Paths
|
29
|
+
# Resolve a set of `@paths` that may contain wildcards, into a sorted, unique array.
|
30
|
+
# @returns [Array(String)]
|
28
31
|
def resolved_paths(&block)
|
29
32
|
@paths.collect do |path|
|
30
33
|
Dir.glob(path)
|
31
34
|
end.flatten.sort.uniq.each(&block)
|
32
35
|
end
|
33
36
|
|
37
|
+
# Build a configuration based on the resolved paths.
|
34
38
|
def configuration
|
35
39
|
configuration = Configuration.new
|
36
40
|
|
data/lib/falcon/command/proxy.rb
CHANGED
@@ -27,31 +27,44 @@ require 'samovar'
|
|
27
27
|
|
28
28
|
module Falcon
|
29
29
|
module Command
|
30
|
+
# Implements the `falcon proxy` command.
|
31
|
+
#
|
32
|
+
# Manages a {Controller::Proxy} instance which is responsible for proxing incoming requests.
|
30
33
|
class Proxy < Samovar::Command
|
31
34
|
self.description = "Proxy to one or more backend hosts."
|
32
35
|
|
36
|
+
# The command line options.
|
37
|
+
# @attribute [Samovar::Options]
|
33
38
|
options do
|
34
39
|
option '--bind <address>', "Bind to the given hostname/address", default: "https://[::]:443"
|
35
40
|
|
36
41
|
option '-t/--timeout <duration>', "Specify the maximum time to wait for non-blocking operations.", type: Float, default: nil
|
37
42
|
end
|
38
43
|
|
44
|
+
# One or more paths to the configuration files.
|
45
|
+
# @name paths
|
46
|
+
# @attribute [Array(String)]
|
39
47
|
many :paths
|
40
48
|
|
41
49
|
include Paths
|
42
50
|
|
51
|
+
# Prepare a new controller for the command.
|
43
52
|
def controller
|
44
53
|
Controller::Proxy.new(self)
|
45
54
|
end
|
46
55
|
|
56
|
+
# The container class to use.
|
47
57
|
def container_class
|
48
58
|
Async::Container.best_container_class
|
49
59
|
end
|
50
60
|
|
61
|
+
# Options for the container.
|
62
|
+
# See {Controller::Serve#setup}.
|
51
63
|
def container_options
|
52
64
|
{}
|
53
65
|
end
|
54
66
|
|
67
|
+
# Prepare the environment and run the controller.
|
55
68
|
def call
|
56
69
|
Async.logger.info(self) do |buffer|
|
57
70
|
buffer.puts "Falcon Proxy v#{VERSION} taking flight!"
|
@@ -63,6 +76,7 @@ module Falcon
|
|
63
76
|
self.controller.run
|
64
77
|
end
|
65
78
|
|
79
|
+
# The endpoint to bind to.
|
66
80
|
def endpoint(**options)
|
67
81
|
Async::HTTP::Endpoint.parse(@options[:bind], timeout: @options[:timeout], **options)
|
68
82
|
end
|
@@ -30,6 +30,8 @@ module Falcon
|
|
30
30
|
class Redirect < Samovar::Command
|
31
31
|
self.description = "Redirect from insecure HTTP to secure HTTP."
|
32
32
|
|
33
|
+
# The command line options.
|
34
|
+
# @attribute [Samovar::Options]
|
33
35
|
options do
|
34
36
|
option '--bind <address>', "Bind to the given hostname/address", default: "http://[::]:80"
|
35
37
|
option '--redirect <address>', "Redirect using this address as a template.", default: "https://[::]:443"
|
@@ -37,22 +39,30 @@ module Falcon
|
|
37
39
|
option '-t/--timeout <duration>', "Specify the maximum time to wait for non-blocking operations.", type: Float, default: nil
|
38
40
|
end
|
39
41
|
|
42
|
+
# One or more paths to the configuration files.
|
43
|
+
# @name paths
|
44
|
+
# @attribute [Array(String)]
|
40
45
|
many :paths
|
41
46
|
|
42
47
|
include Paths
|
43
48
|
|
49
|
+
# Prepare a new controller for the command.
|
44
50
|
def controller
|
45
51
|
Controller::Redirect.new(self)
|
46
52
|
end
|
47
53
|
|
54
|
+
# The container class to use.
|
48
55
|
def container_class
|
49
56
|
Async::Container.best_container_class
|
50
57
|
end
|
51
58
|
|
59
|
+
# Options for the container.
|
60
|
+
# See {Controller::Serve#setup}.
|
52
61
|
def container_options
|
53
62
|
{}
|
54
63
|
end
|
55
64
|
|
65
|
+
# Prepare the environment and run the controller.
|
56
66
|
def call
|
57
67
|
Async.logger.info(self) do |buffer|
|
58
68
|
buffer.puts "Falcon Redirect v#{VERSION} taking flight!"
|
@@ -64,10 +74,12 @@ module Falcon
|
|
64
74
|
self.controller.run
|
65
75
|
end
|
66
76
|
|
77
|
+
# The endpoint to bind to.
|
67
78
|
def endpoint(**options)
|
68
79
|
Async::HTTP::Endpoint.parse(@options[:bind], timeout: @options[:timeout], **options)
|
69
80
|
end
|
70
81
|
|
82
|
+
# The template endpoint to redirect to.
|
71
83
|
def redirect_endpoint(**options)
|
72
84
|
Async::HTTP::Endpoint.parse(@options[:redirect], **options)
|
73
85
|
end
|
data/lib/falcon/command/serve.rb
CHANGED
@@ -40,9 +40,14 @@ require 'bundler'
|
|
40
40
|
|
41
41
|
module Falcon
|
42
42
|
module Command
|
43
|
+
# Implements the `falcon serve` command. Designed for *development*.
|
44
|
+
#
|
45
|
+
# Manages a {Controller::Serve} instance which is responsible for running applications in a development environment.
|
43
46
|
class Serve < Samovar::Command
|
44
47
|
self.description = "Run an HTTP server for development purposes."
|
45
48
|
|
49
|
+
# The command line options.
|
50
|
+
# @attribute [Samovar::Options]
|
46
51
|
options do
|
47
52
|
option '-b/--bind <address>', "Bind to the given hostname/address.", default: "https://localhost:9292"
|
48
53
|
|
@@ -63,6 +68,7 @@ module Falcon
|
|
63
68
|
option '--threads <count>', "Number of threads (hybrid only).", type: Integer
|
64
69
|
end
|
65
70
|
|
71
|
+
# The container class to use.
|
66
72
|
def container_class
|
67
73
|
case @options[:container]
|
68
74
|
when :threaded
|
@@ -74,57 +80,58 @@ module Falcon
|
|
74
80
|
end
|
75
81
|
end
|
76
82
|
|
83
|
+
# Whether verbose logging is enabled.
|
84
|
+
# @returns [Boolean]
|
77
85
|
def verbose?
|
78
86
|
@parent&.verbose?
|
79
87
|
end
|
80
88
|
|
89
|
+
# Whether to enable the application HTTP cache.
|
90
|
+
# @returns [Boolean]
|
81
91
|
def cache?
|
82
92
|
@options[:cache]
|
83
93
|
end
|
84
94
|
|
95
|
+
# Load the rack application from the specified configuration path.
|
96
|
+
# @returns [Protocol::HTTP::Middleware]
|
85
97
|
def load_app
|
86
98
|
rack_app, _ = Rack::Builder.parse_file(@options[:config])
|
87
99
|
|
88
100
|
return Server.middleware(rack_app, verbose: self.verbose?, cache: self.cache?)
|
89
101
|
end
|
90
102
|
|
91
|
-
|
92
|
-
|
93
|
-
options = {}
|
94
|
-
|
95
|
-
keys.each do |key|
|
96
|
-
if @options.key?(key)
|
97
|
-
options[key] = @options[key]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
return options
|
102
|
-
end
|
103
|
-
|
103
|
+
# Options for the container.
|
104
|
+
# See {Controller::Serve#setup}.
|
104
105
|
def container_options
|
105
|
-
|
106
|
+
@options.slice(:count, :forks, :threads)
|
106
107
|
end
|
107
108
|
|
109
|
+
# Options for the {endpoint}.
|
108
110
|
def endpoint_options
|
109
|
-
|
111
|
+
@options.slice(:hostname, :port, :reuse_port, :timeout)
|
110
112
|
end
|
111
113
|
|
114
|
+
# The endpoint to bind to.
|
112
115
|
def endpoint
|
113
116
|
Endpoint.parse(@options[:bind], **endpoint_options)
|
114
117
|
end
|
115
118
|
|
119
|
+
# The endpoint suitable for a client to connect.
|
116
120
|
def client_endpoint
|
117
121
|
Async::HTTP::Endpoint.parse(@options[:bind], **endpoint_options)
|
118
122
|
end
|
119
123
|
|
124
|
+
# Create a new client suitable for accessing the application.
|
120
125
|
def client
|
121
126
|
Async::HTTP::Client.new(client_endpoint)
|
122
127
|
end
|
123
128
|
|
129
|
+
# Prepare a new controller for the command.
|
124
130
|
def controller
|
125
131
|
Controller::Serve.new(self)
|
126
132
|
end
|
127
133
|
|
134
|
+
# Prepare the environment and run the controller.
|
128
135
|
def call
|
129
136
|
Async.logger.info(self) do |buffer|
|
130
137
|
buffer.puts "Falcon v#{VERSION} taking flight! Using #{self.container_class} #{self.container_options}."
|
@@ -29,24 +29,33 @@ require 'async/io/unix_endpoint'
|
|
29
29
|
|
30
30
|
module Falcon
|
31
31
|
module Command
|
32
|
+
# Implements the `falcon supervisor` command.
|
33
|
+
#
|
34
|
+
# Talks to an instance of the supervisor to issue commands and print results.
|
32
35
|
class Supervisor < Samovar::Command
|
33
|
-
self.description = "Control and query a specific
|
36
|
+
self.description = "Control and query a specific supervisor."
|
34
37
|
|
38
|
+
# The command line options.
|
39
|
+
# @attribute [Samovar::Options]
|
35
40
|
options do
|
36
41
|
option "--path <path>", "The control IPC path.", default: "supervisor.ipc"
|
37
42
|
end
|
38
43
|
|
44
|
+
# Implements the `falcon supervisor restart` command.
|
39
45
|
class Restart < Samovar::Command
|
40
46
|
self.description = "Restart the process group."
|
41
47
|
|
48
|
+
# Send the restart message to the supervisor.
|
42
49
|
def call(stream)
|
43
50
|
stream.puts({please: 'restart'}.to_json, separator: "\0")
|
44
51
|
end
|
45
52
|
end
|
46
53
|
|
54
|
+
# Implements the `falcon supervisor metrics` command.
|
47
55
|
class Metrics < Samovar::Command
|
48
56
|
self.description = "Show metrics about the falcon processes."
|
49
57
|
|
58
|
+
# Send the metrics message to the supervisor and print the results.
|
50
59
|
def call(stream)
|
51
60
|
stream.puts({please: 'metrics'}.to_json, separator: "\0")
|
52
61
|
response = JSON.parse(stream.gets("\0"), symbolize_names: true)
|
@@ -55,15 +64,20 @@ module Falcon
|
|
55
64
|
end
|
56
65
|
end
|
57
66
|
|
67
|
+
# The nested command to execute.
|
68
|
+
# @name nested
|
69
|
+
# @attribute [Command]
|
58
70
|
nested :command, {
|
59
71
|
'restart' => Restart,
|
60
72
|
'metrics' => Metrics,
|
61
73
|
}, default: 'metrics'
|
62
74
|
|
75
|
+
# The endpoint the supervisor is bound to.
|
63
76
|
def endpoint
|
64
77
|
Async::IO::Endpoint.unix(@options[:path])
|
65
78
|
end
|
66
79
|
|
80
|
+
# Connect to the supervisor and execute the requested command.
|
67
81
|
def call
|
68
82
|
Async do
|
69
83
|
endpoint.connect do |socket|
|
data/lib/falcon/command/top.rb
CHANGED
@@ -33,9 +33,12 @@ require 'samovar'
|
|
33
33
|
|
34
34
|
module Falcon
|
35
35
|
module Command
|
36
|
+
# The top level command for the `falcon` executable.
|
36
37
|
class Top < Samovar::Command
|
37
38
|
self.description = "An asynchronous HTTP server."
|
38
39
|
|
40
|
+
# The command line options.
|
41
|
+
# @attribute [Samovar::Options]
|
39
42
|
options do
|
40
43
|
option '--verbose | --quiet', "Verbosity of output for debugging.", key: :logging
|
41
44
|
option '-h/--help', "Print out help information."
|
@@ -43,6 +46,9 @@ module Falcon
|
|
43
46
|
option '-e/--encoding', "Specify the default external encoding of the server.", default: "UTF-8"
|
44
47
|
end
|
45
48
|
|
49
|
+
# The nested command to execute.
|
50
|
+
# @name nested
|
51
|
+
# @attribute [Command]
|
46
52
|
nested :command, {
|
47
53
|
'serve' => Serve,
|
48
54
|
'host' => Host,
|
@@ -52,15 +58,23 @@ module Falcon
|
|
52
58
|
'supervisor' => Supervisor,
|
53
59
|
}, default: 'serve'
|
54
60
|
|
61
|
+
# Whether verbose logging is enabled.
|
62
|
+
# @returns [Boolean]
|
55
63
|
def verbose?
|
56
64
|
@options[:logging] == :verbose
|
57
65
|
end
|
58
66
|
|
67
|
+
# Whether quiet logging was enabled.
|
68
|
+
# @returns [Boolean]
|
59
69
|
def quiet?
|
60
70
|
@options[:logging] == :quiet
|
61
71
|
end
|
62
72
|
|
73
|
+
# Update the external encoding.
|
74
|
+
#
|
63
75
|
# If you don't specify these, it's possible to have issues when encodings mismatch on the server.
|
76
|
+
#
|
77
|
+
# @parameter encoding [Encoding] Defaults to `Encoding::UTF_8`.
|
64
78
|
def update_external_encoding!(encoding = Encoding::UTF_8)
|
65
79
|
if Encoding.default_external != encoding
|
66
80
|
Console.logger.warn(self) {"Updating Encoding.default_external from #{Encoding.default_external} to #{encoding}"}
|
@@ -68,12 +82,14 @@ module Falcon
|
|
68
82
|
end
|
69
83
|
end
|
70
84
|
|
85
|
+
# The desired external encoding.
|
71
86
|
def encoding
|
72
87
|
if name = @options[:encoding]
|
73
88
|
Encoding.find(name)
|
74
89
|
end
|
75
90
|
end
|
76
91
|
|
92
|
+
# Prepare the environment and invoke the sub-command.
|
77
93
|
def call
|
78
94
|
if encoding = self.encoding
|
79
95
|
update_external_encoding!(encoding)
|
@@ -27,9 +27,14 @@ require 'samovar'
|
|
27
27
|
|
28
28
|
module Falcon
|
29
29
|
module Command
|
30
|
+
# Implements the `falcon virtual` command. Designed for *deployment*.
|
31
|
+
#
|
32
|
+
# Manages a {Controller::Virtual} instance which is responsible for running the {Proxy} and {Redirect} instances.
|
30
33
|
class Virtual < Samovar::Command
|
31
34
|
self.description = "Run one or more virtual hosts with a front-end proxy."
|
32
35
|
|
36
|
+
# The command line options.
|
37
|
+
# @attribute [Samovar::Options]
|
33
38
|
options do
|
34
39
|
option '--bind-insecure <address>', "Bind redirection to the given hostname/address", default: "http://[::]:80"
|
35
40
|
option '--bind-secure <address>', "Bind proxy to the given hostname/address", default: "https://[::]:443"
|
@@ -37,26 +42,34 @@ module Falcon
|
|
37
42
|
option '-t/--timeout <duration>', "Specify the maximum time to wait for non-blocking operations.", type: Float, default: 30
|
38
43
|
end
|
39
44
|
|
45
|
+
# One or more paths to the configuration files.
|
46
|
+
# @name paths
|
47
|
+
# @attribute [Array(String)]
|
40
48
|
many :paths
|
41
49
|
|
42
50
|
include Paths
|
43
51
|
|
52
|
+
# Prepare a new controller for the command.
|
44
53
|
def controller
|
45
54
|
Controller::Virtual.new(self)
|
46
55
|
end
|
47
56
|
|
57
|
+
# The URI to bind the `HTTPS` -> `falcon host` proxy.
|
48
58
|
def bind_secure
|
49
59
|
@options[:bind_secure]
|
50
60
|
end
|
51
61
|
|
62
|
+
# The URI to bind the `HTTP` -> `HTTPS` redirector.
|
52
63
|
def bind_insecure
|
53
64
|
@options[:bind_insecure]
|
54
65
|
end
|
55
66
|
|
67
|
+
# The connection timeout to use for incoming connections.
|
56
68
|
def timeout
|
57
69
|
@options[:timeout]
|
58
70
|
end
|
59
71
|
|
72
|
+
# Prepare the environment and run the controller.
|
60
73
|
def call
|
61
74
|
Async.logger.info(self) do |buffer|
|
62
75
|
buffer.puts "Falcon Virtual v#{VERSION} taking flight!"
|
@@ -67,10 +80,12 @@ module Falcon
|
|
67
80
|
self.controller.run
|
68
81
|
end
|
69
82
|
|
83
|
+
# The insecure endpoint for connecting to the {Redirect} instance.
|
70
84
|
def insecure_endpoint(**options)
|
71
85
|
Async::HTTP::Endpoint.parse(@options[:bind_insecure], **options)
|
72
86
|
end
|
73
87
|
|
88
|
+
# The secure endpoint for connecting to the {Proxy} instance.
|
74
89
|
def secure_endpoint(**options)
|
75
90
|
Async::HTTP::Endpoint.parse(@options[:bind_secure], **options)
|
76
91
|
end
|
data/lib/falcon/configuration.rb
CHANGED
@@ -23,13 +23,36 @@
|
|
23
23
|
require 'build/environment'
|
24
24
|
|
25
25
|
module Falcon
|
26
|
+
# Manages environments which describes how to host a specific application.
|
27
|
+
#
|
28
|
+
# Environments are key-value maps with lazy value resolution. An environment can inherit from a parent environment, which can provide defaults
|
29
|
+
#
|
30
|
+
# A typical configuration file might look something like:
|
31
|
+
#
|
32
|
+
# ~~~ ruby
|
33
|
+
# #!/usr/bin/env falcon-host
|
34
|
+
# # frozen_string_literal: true
|
35
|
+
#
|
36
|
+
# load :rack, :self_signed_tls, :supervisor
|
37
|
+
#
|
38
|
+
# supervisor
|
39
|
+
#
|
40
|
+
# rack 'hello.localhost', :self_signed_tls do
|
41
|
+
# end
|
42
|
+
# ~~~
|
43
|
+
#
|
26
44
|
class Configuration
|
27
|
-
|
45
|
+
# Initialize an empty configuration.
|
46
|
+
def initialize
|
28
47
|
@environments = {}
|
29
48
|
end
|
30
49
|
|
50
|
+
# The map of named environments.
|
51
|
+
# @attribute [Hash(String, Build::Environment)]
|
31
52
|
attr :environments
|
32
53
|
|
54
|
+
# Enumerate all environments that have the specified key.
|
55
|
+
# @parameter key [Symbol] Filter environments that don't have this key.
|
33
56
|
def each(key = :authority)
|
34
57
|
return to_enum(key) unless block_given?
|
35
58
|
|
@@ -42,6 +65,7 @@ module Falcon
|
|
42
65
|
end
|
43
66
|
end
|
44
67
|
|
68
|
+
# Add the named environment to the configuration.
|
45
69
|
def add(environment)
|
46
70
|
name = environment.name
|
47
71
|
|
@@ -56,11 +80,17 @@ module Falcon
|
|
56
80
|
@environments[name] = environment
|
57
81
|
end
|
58
82
|
|
83
|
+
# Load the specified configuration file. See {Loader#load_file} for more details.
|
59
84
|
def load_file(path)
|
60
85
|
Loader.load_file(self, path)
|
61
86
|
end
|
62
87
|
|
88
|
+
# The domain specific language for loading configuration files.
|
63
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.
|
64
94
|
def initialize(configuration, root = nil)
|
65
95
|
@loaded = {}
|
66
96
|
@configuration = configuration
|
@@ -68,9 +98,17 @@ module Falcon
|
|
68
98
|
@root = root
|
69
99
|
end
|
70
100
|
|
71
|
-
|
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]
|
72
107
|
attr :configuration
|
73
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`.
|
74
112
|
def self.load_file(configuration, path)
|
75
113
|
path = File.realpath(path)
|
76
114
|
root = File.dirname(path)
|
@@ -80,11 +118,16 @@ module Falcon
|
|
80
118
|
loader.instance_eval(File.read(path), path)
|
81
119
|
end
|
82
120
|
|
121
|
+
# Load specific features into the current configuration.
|
122
|
+
#
|
123
|
+
# Falcon provides default environments for different purposes. These are included in the gem, in the `environments/` directory. This method loads the code in those files into the current configuration.
|
124
|
+
#
|
125
|
+
# @parameter features [Array(Symbol)] The features to load.
|
83
126
|
def load(*features)
|
84
127
|
features.each do |feature|
|
85
128
|
next if @loaded.include?(feature)
|
86
129
|
|
87
|
-
relative_path = File.join(__dir__, "
|
130
|
+
relative_path = File.join(__dir__, "environments", "#{feature}.rb")
|
88
131
|
|
89
132
|
self.instance_eval(File.read(relative_path), relative_path)
|
90
133
|
|
@@ -92,11 +135,18 @@ module Falcon
|
|
92
135
|
end
|
93
136
|
end
|
94
137
|
|
95
|
-
|
138
|
+
# Add the named environment, with zero or more parent environments, defined using the specified `block`.
|
139
|
+
# @parameter name [String] The name of the environment.
|
140
|
+
# @parameter parents [Array(Symbol)] The names of the parent environments to inherit.
|
141
|
+
# @yields {...} The block that will generate the environment.
|
142
|
+
def environment(name, *parents, &block)
|
96
143
|
raise KeyError.new("#{name} is already set", key: name) if @environments.key?(name)
|
97
144
|
@environments[name] = merge(name, *parents, &block)
|
98
145
|
end
|
99
|
-
|
146
|
+
|
147
|
+
# Define a host with the specified name.
|
148
|
+
# Adds `root` and `authority` keys.
|
149
|
+
# @parameter name [String] The name of the environment, usually a hostname.
|
100
150
|
def host(name, *parents, &block)
|
101
151
|
environment = merge(name, :host, *parents, &block)
|
102
152
|
|
@@ -106,6 +156,9 @@ module Falcon
|
|
106
156
|
@configuration.add(environment.flatten)
|
107
157
|
end
|
108
158
|
|
159
|
+
# Define a proxy with the specified name.
|
160
|
+
# Adds `root` and `authority` keys.
|
161
|
+
# @parameter name [String] The name of the environment, usually a hostname.
|
109
162
|
def proxy(name, *parents, &block)
|
110
163
|
environment = merge(name, :proxy, *parents, &block)
|
111
164
|
|
@@ -115,6 +168,9 @@ module Falcon
|
|
115
168
|
@configuration.add(environment.flatten)
|
116
169
|
end
|
117
170
|
|
171
|
+
# Define a rack application with the specified name.
|
172
|
+
# Adds `root` and `authority` keys.
|
173
|
+
# @parameter name [String] The name of the environment, usually a hostname.
|
118
174
|
def rack(name, *parents, &block)
|
119
175
|
environment = merge(name, :rack, *parents, &block)
|
120
176
|
|
@@ -124,9 +180,11 @@ module Falcon
|
|
124
180
|
@configuration.add(environment.flatten)
|
125
181
|
end
|
126
182
|
|
127
|
-
|
183
|
+
# Define a supervisor instance
|
184
|
+
# Adds `root` key.
|
185
|
+
def supervisor(&block)
|
128
186
|
name = File.join(@root, "supervisor")
|
129
|
-
environment = merge(name, :supervisor)
|
187
|
+
environment = merge(name, :supervisor, &block)
|
130
188
|
|
131
189
|
environment[:root] = @root
|
132
190
|
|
@@ -135,6 +193,10 @@ module Falcon
|
|
135
193
|
|
136
194
|
private
|
137
195
|
|
196
|
+
# Build a new environment with the specified name and the given parents.
|
197
|
+
# @parameter name [String]
|
198
|
+
# @parameter parents [Array(Build::Environment)]
|
199
|
+
# @yields {...} The block that will generate the environment.
|
138
200
|
def merge(name, *parents, &block)
|
139
201
|
environments = parents.map{|name| @environments.fetch(name)}
|
140
202
|
|