falcon 0.31.0 → 0.32.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f779301a15b9adf72ca83712fa1128a7ac7df69b4ec190fa5aee25e44ca23c57
4
- data.tar.gz: 3a939860b31ae73aa9627e8d62eb1721d4d2621e4d851713788cd5b09fd5d433
3
+ metadata.gz: 19fc217c5ab4d9c7e1b888d46366843e3d549c4d771cec14f0f17a4578144be8
4
+ data.tar.gz: fbb6d14f55d0fb392a98edcc4381a54db624376e3d40d0a5db4ba70ae9ccb9e4
5
5
  SHA512:
6
- metadata.gz: fa3b215cfe77d2f14fa6e6750954246daee7dc8551770a2dd1b726e5151b844f76e6c164c78e07f761191deced2ee7056723b389ce5fbc99d7b49f4878d84ee1
7
- data.tar.gz: a4a381b1c2f959ca30d37f20b152654cb4c77c992f3395a579e22a6fe0c03a4b0a7c081ee803991e973b8bc5d98d6ab77afca7eb00f76b5a3262825d332179c3
6
+ metadata.gz: 8a66a5a99d8902246e058565ee11023fad33dfe8a5909271e3536d43cc6a5d439b664142df4a82c83791f04ea86a631ea06f957fdf18b181818af8a6871d688e
7
+ data.tar.gz: 23c44cee1313788820af52e6787efe5157a7d228bd7032b77125a6f6d226d72576bf32073c35cdf78a1db05a466457ea14685dc110766eddbbe29950894857e3
data/VIRTUAL.md ADDED
@@ -0,0 +1,14 @@
1
+ For every `falcon.rb`:
2
+
3
+ Spawn a child which loads falcon.rb:
4
+ - Bind to `server.ipc`
5
+
6
+ Server loads falcon.rb:
7
+ - Figure out whether it is application or not.
8
+
9
+ Server forks client:
10
+ - Client binds to `server.ipc`.
11
+ - Server connects to `server.ipc`.
12
+
13
+
14
+ Server expects client to bind to `server.ipc`.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env -S falcon host
2
+
3
+ host 'beer.localhost', :rack, :self_signed do
4
+ root __dir__
5
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env -S ./bin/falcon virtual
2
+
3
+ host 'benchmark.local', :self_signed
@@ -1,3 +1,21 @@
1
1
  #!/usr/bin/env falcon --verbose serve -c
2
2
 
3
- run lambda {|env| [200, {}, ["Hello World"]]}
3
+ require 'async'
4
+
5
+ class RequestLogger
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ logger = Async.logger.with(level: :debug, name: "middleware")
12
+
13
+ Async(logger: logger) do
14
+ @app.call(env)
15
+ end.wait
16
+ end
17
+ end
18
+
19
+ use RequestLogger
20
+
21
+ run lambda {|env| Async.logger.debug(self) {env['HTTP_USER_AGENT']}; [200, {}, ["Hello World"]]}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env -S falcon host
2
+
3
+ host 'hello.localhost', :rack, :self_signed do
4
+ root __dir__
5
+ end
6
+
7
+ # service 'jobs' do
8
+ # shell ['rake', 'background:jobs:process']
9
+ # end
data/falcon.gemspec CHANGED
@@ -21,8 +21,8 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_dependency "async", "~> 1.13"
23
23
  spec.add_dependency "async-io", "~> 1.22"
24
- spec.add_dependency "async-http", "~> 0.41.0"
25
- spec.add_dependency "async-container", "~> 0.10.0"
24
+ spec.add_dependency "async-http", "~> 0.43.0"
25
+ spec.add_dependency "async-container", "~> 0.12.0"
26
26
 
27
27
  spec.add_dependency "rack", ">= 1.0"
28
28
 
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_development_dependency "trenni"
34
34
  spec.add_development_dependency "async-rspec", "~> 1.7"
35
- spec.add_development_dependency "async-websocket", "~> 0.11.0"
35
+ spec.add_development_dependency "async-websocket", "~> 0.12.0"
36
36
  spec.add_development_dependency "async-process", "~> 1.1"
37
37
 
38
38
  spec.add_development_dependency "covered", "~> 0.10"
@@ -77,7 +77,7 @@ module Falcon
77
77
  end
78
78
 
79
79
  def initialize(status, headers, body, protocol = nil)
80
- super(nil, status, nil, headers, body, protocol)
80
+ super(nil, status, headers, body, protocol)
81
81
  end
82
82
  end
83
83
  end
@@ -20,6 +20,7 @@
20
20
 
21
21
  require_relative 'command/serve'
22
22
  require_relative 'command/virtual'
23
+ require_relative 'command/host'
23
24
 
24
25
  require_relative 'version'
25
26
 
@@ -43,7 +44,8 @@ module Falcon
43
44
 
44
45
  nested :command, {
45
46
  'serve' => Serve,
46
- 'virtual' => Virtual
47
+ 'virtual' => Virtual,
48
+ 'host' => Host,
47
49
  }, default: 'serve'
48
50
 
49
51
  def verbose?
@@ -0,0 +1,76 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative '../server'
22
+ require_relative '../endpoint'
23
+ require_relative '../hosts'
24
+ require_relative '../configuration'
25
+
26
+ require 'async/container'
27
+ require 'async/container/controller'
28
+
29
+ require 'async/io/host_endpoint'
30
+ require 'async/io/shared_endpoint'
31
+ require 'async/io/ssl_endpoint'
32
+
33
+ require 'samovar'
34
+
35
+ require 'rack/builder'
36
+ require 'rack/server'
37
+
38
+ module Falcon
39
+ module Command
40
+ class Host < Samovar::Command
41
+ self.description = "Run a specific virtual host."
42
+
43
+ one :path, "A path specified if running from a script."
44
+
45
+ def assume_privileges(path)
46
+ stat = File.stat(path)
47
+
48
+ Process::GID.change_privilege(stat.gid)
49
+ Process::UID.change_privilege(stat.uid)
50
+ end
51
+
52
+ def run(container, verbose = false)
53
+ configuration = Configuration.new(verbose)
54
+ configuration.load_file(@path)
55
+
56
+ Async.logger.info(self) {"Starting services described by #{@path}..."}
57
+
58
+ assume_privileges(@path)
59
+
60
+ configuration.each do |environment|
61
+ Falcon::Host.new(environment).run(container)
62
+ end
63
+
64
+ return container
65
+ end
66
+
67
+ def call
68
+ container = Async::Container::Forked.new
69
+
70
+ container = run(container, parent.verbose?)
71
+
72
+ container.wait
73
+ end
74
+ end
75
+ end
76
+ end
@@ -44,8 +44,6 @@ module Falcon
44
44
  option '-h/--hostname <hostname>', "Specify the hostname which would be used for certificates, etc."
45
45
  option '-t/--timeout <duration>', "Specify the maximum time to wait for blocking operations.", type: Float, default: 60*10
46
46
 
47
- option '--reuse-port', "Enable SO_REUSEPORT if possible.", default: false
48
-
49
47
  option '-c/--config <path>', "Rackup configuration file to load", default: 'config.ru'
50
48
 
51
49
  option '--forked | --threaded | --hybrid', "Select a specific parallelism model", key: :container, default: :forked
@@ -38,7 +38,7 @@ require 'rack/server'
38
38
  module Falcon
39
39
  module Command
40
40
  class Virtual < Samovar::Command
41
- self.description = "Run an HTTP server with one or more virtual hosts."
41
+ self.description = "Run one or more virtual hosts with a front-end proxy."
42
42
 
43
43
  options do
44
44
  option '--bind-insecure <address>', "Bind redirection to the given hostname/address", default: "http://[::]"
@@ -64,6 +64,14 @@ module Falcon
64
64
 
65
65
  container.wait
66
66
  end
67
+
68
+ def insecure_endpoint
69
+ Async::HTTP::Endpoint.parse(@options[:bind_insecure])
70
+ end
71
+
72
+ def secure_endpoint
73
+ Async::HTTP::Endpoint.parse(@options[:bind_secure])
74
+ end
67
75
  end
68
76
  end
69
77
  end
@@ -87,7 +87,9 @@ module Falcon
87
87
 
88
88
  context.session_id_context = ssl_session_id
89
89
 
90
- context.set_params
90
+ context.set_params(
91
+ verify_mode: OpenSSL::SSL::VERIFY_NONE,
92
+ )
91
93
 
92
94
  context.setup
93
95
  end
@@ -137,10 +139,10 @@ module Falcon
137
139
 
138
140
  authority 'localhost'
139
141
  scheme 'https'
140
- protocol {::Async::HTTP::Protocol::HTTP2}
141
142
  ipc_path {::File.expand_path("server.ipc", root)}
142
143
 
143
- endpoint {ProxyEndpoint.unix(ipc_path, protocol: protocol, scheme: scheme, authority: authority)}
144
+ endpoint {ProxyEndpoint.unix(ipc_path, protocol: Async::HTTP::Protocol::HTTP2, scheme: scheme, authority: authority)}
145
+ protocol {endpoint.protocol}
144
146
 
145
147
  bound_endpoint do
146
148
  Async::Reactor.run do
data/lib/falcon/hosts.rb CHANGED
@@ -69,22 +69,25 @@ module Falcon
69
69
  Process::UID.change_privilege(stat.uid)
70
70
  end
71
71
 
72
+ def spawn(container)
73
+ container.spawn(name: self.name, restart: true) do |instance|
74
+ path = File.join(self.root, "falcon.rb")
75
+
76
+ assume_privileges(path)
77
+
78
+ instance.exec("bundle", "exec", path)
79
+ end
80
+ end
81
+
72
82
  def run(container)
73
83
  if @environment.include?(:server)
74
84
  bound_endpoint = self.bound_endpoint
75
85
 
76
- container.run(count: 1, name: self.name) do |task, instance|
86
+ container.run(name: self.name, restart: true) do |task, instance|
77
87
  Async.logger.info(self) {"Starting application server..."}
78
88
 
79
- if root = self.root
80
- Dir.chdir(root)
81
- end
82
-
83
89
  server = @evaluator.server
84
90
 
85
- # Drop root privileges:
86
- assume_privileges(root)
87
-
88
91
  server.run
89
92
 
90
93
  task.children.each(&:wait)
@@ -95,6 +98,7 @@ module Falcon
95
98
 
96
99
  class Hosts
97
100
  DEFAULT_ALPN_PROTOCOLS = ['h2', 'http/1.1'].freeze
101
+ SERVER_CIPHERS = "EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5".freeze
98
102
 
99
103
  def initialize(configuration)
100
104
  @named = {}
@@ -126,7 +130,11 @@ module Falcon
126
130
 
127
131
  context.session_id_context = "falcon"
128
132
  context.alpn_protocols = DEFAULT_ALPN_PROTOCOLS
129
- context.set_params
133
+
134
+ context.set_params(
135
+ ciphers: SERVER_CIPHERS,
136
+ verify_mode: OpenSSL::SSL::VERIFY_NONE,
137
+ )
130
138
 
131
139
  context.setup
132
140
  end
@@ -160,24 +168,31 @@ module Falcon
160
168
 
161
169
  def run(container = Async::Container::Forked.new, **options)
162
170
  @named.each do |name, host|
163
- host.run(container)
171
+ host.spawn(container)
164
172
  end
165
173
 
166
174
  secure_endpoint = Async::HTTP::Endpoint.parse(options[:bind_secure], ssl_context: self.ssl_context)
167
175
  insecure_endpoint = Async::HTTP::Endpoint.parse(options[:bind_insecure])
168
176
 
169
- container.run(count: 1, name: "Falcon Proxy") do |task, instance|
177
+ secure_endpoint_bound = insecure_endpoint_bound = nil
178
+
179
+ Async::Reactor.run do
180
+ secure_endpoint_bound = Async::IO::SharedEndpoint.bound(secure_endpoint)
181
+ insecure_endpoint_bound = Async::IO::SharedEndpoint.bound(insecure_endpoint)
182
+ end.wait
183
+
184
+ container.run(name: "Falcon Proxy", restart: true) do |task, instance|
170
185
  proxy = self.proxy
171
186
 
172
- proxy_server = Falcon::Server.new(proxy, secure_endpoint)
187
+ proxy_server = Falcon::Server.new(proxy, secure_endpoint_bound, secure_endpoint.protocol, secure_endpoint.scheme)
173
188
 
174
189
  proxy_server.run
175
190
  end
176
191
 
177
- container.run(count: 1, name: "Falcon Redirector") do |task, instance|
192
+ container.run(name: "Falcon Redirector", restart: true) do |task, instance|
178
193
  redirection = self.redirection(secure_endpoint)
179
194
 
180
- redirection_server = Falcon::Server.new(redirection, insecure_endpoint)
195
+ redirection_server = Falcon::Server.new(redirection, insecure_endpoint_bound, insecure_endpoint.protocol, insecure_endpoint.scheme)
181
196
 
182
197
  redirection_server.run
183
198
  end
data/lib/falcon/proxy.rb CHANGED
@@ -97,7 +97,7 @@ module Falcon
97
97
  # end
98
98
 
99
99
  # The authority of the request must match the authority of the endpoint we are proxying to, otherwise SNI and other things won't work correctly.
100
- request.authority = host.endpoint.authority
100
+ request.authority = host.authority
101
101
 
102
102
  if address = request.remote_address
103
103
  request.headers.add(X_FORWARDED_FOR, address.ip_address)
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Falcon
22
- VERSION = "0.31.0"
22
+ VERSION = "0.32.0"
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: falcon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.31.0
4
+ version: 0.32.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-23 00:00:00.000000000 Z
11
+ date: 2019-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -44,28 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.41.0
47
+ version: 0.43.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.41.0
54
+ version: 0.43.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: async-container
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.10.0
61
+ version: 0.12.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.10.0
68
+ version: 0.12.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rack
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -156,14 +156,14 @@ dependencies:
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: 0.11.0
159
+ version: 0.12.0
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: 0.11.0
166
+ version: 0.12.0
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: async-process
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -249,10 +249,14 @@ files:
249
249
  - Gemfile
250
250
  - README.md
251
251
  - Rakefile
252
+ - VIRTUAL.md
252
253
  - bin/falcon
253
254
  - examples/beer/config.ru
255
+ - examples/beer/falcon.rb
254
256
  - examples/benchmark/config.ru
257
+ - examples/benchmark/falcon.rb
255
258
  - examples/hello/config.ru
259
+ - examples/hello/falcon.rb
256
260
  - examples/push/client.rb
257
261
  - examples/push/config.ru
258
262
  - examples/push/index.html
@@ -274,6 +278,7 @@ files:
274
278
  - lib/falcon/adapters/response.rb
275
279
  - lib/falcon/adapters/rewindable.rb
276
280
  - lib/falcon/command.rb
281
+ - lib/falcon/command/host.rb
277
282
  - lib/falcon/command/serve.rb
278
283
  - lib/falcon/command/virtual.rb
279
284
  - lib/falcon/configuration.rb