falcon 0.31.0 → 0.32.0

Sign up to get free protection for your applications and to get access to all the features.
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