falcon 0.36.4 → 0.36.5
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
- 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 +59 -32
- 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 +14 -1
- 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 +68 -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 +9 -0
- data/lib/falcon/service/generic.rb +18 -0
- data/lib/falcon/service/proxy.rb +6 -0
- data/lib/falcon/service/supervisor.rb +13 -1
- 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 +16 -72
- 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/examples/csv/config.ru
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
#!/usr/bin/env falcon --verbose serve -c
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
class MyApp
|
5
|
-
def initialize(app)
|
6
|
-
@app = app
|
7
|
-
|
8
|
-
@words = File.readlines('/usr/share/dict/words', chomp: true).each_slice(3).to_a
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(env)
|
12
|
-
body = Async::HTTP::Body::Writable.new(queue: Async::LimitedQueue.new(8))
|
13
|
-
|
14
|
-
Async do |task|
|
15
|
-
@words.each do |words|
|
16
|
-
Async.logger.debug("Sending #{words.inspect}")
|
17
|
-
body.write(words.join(",") + "\n")
|
18
|
-
task.sleep(1)
|
19
|
-
end
|
20
|
-
ensure
|
21
|
-
body.close($!)
|
22
|
-
end
|
23
|
-
|
24
|
-
return [200, [], body]
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Build the middleware stack:
|
29
|
-
use MyApp
|
30
|
-
|
31
|
-
run lambda {|env| [404, {}, []]}
|
data/examples/google/falcon.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env falcon-host
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
load :proxy, :self_signed_tls, :supervisor
|
5
|
-
|
6
|
-
supervisor
|
7
|
-
|
8
|
-
proxy "google.localhost", :self_signed_tls do
|
9
|
-
url 'https://www.google.com'
|
10
|
-
end
|
11
|
-
|
12
|
-
proxy "codeotaku.localhost", :self_signed_tls do
|
13
|
-
url 'https://www.codeotaku.com'
|
14
|
-
end
|
data/examples/hello/config.ru
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
#!/usr/bin/env falcon --verbose serve -c
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'async'
|
5
|
-
|
6
|
-
class RequestLogger
|
7
|
-
def initialize(app)
|
8
|
-
@app = app
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(env)
|
12
|
-
logger = Async.logger.with(level: :debug)
|
13
|
-
|
14
|
-
Async(logger: logger) do
|
15
|
-
@app.call(env)
|
16
|
-
end.wait
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# use RequestLogger
|
21
|
-
|
22
|
-
run lambda {|env| [200, {'cache-control' => 'max-age=10, public'}, ["Hello World"]]}
|
data/examples/hello/falcon.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
#!/usr/bin/env falcon-host
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
load :rack, :self_signed_tls, :supervisor
|
5
|
-
|
6
|
-
supervisor
|
7
|
-
|
8
|
-
rack 'hello.localhost', :self_signed_tls do
|
9
|
-
# scheme 'http'
|
10
|
-
# protocol {Async::HTTP::Protocol::HTTP1}
|
11
|
-
#
|
12
|
-
# endpoint do
|
13
|
-
# Async::HTTP::Endpoint.for(scheme, "localhost", port: 9292, protocol: protocol)
|
14
|
-
# end
|
15
|
-
|
16
|
-
append preload "preload.rb"
|
17
|
-
|
18
|
-
# Process will connect to supervisor to report statistics periodically, otherwise it would be killed.
|
19
|
-
# report :supervisor
|
20
|
-
end
|
21
|
-
|
22
|
-
# service 'jobs' do
|
23
|
-
# shell ['rake', 'background:jobs:process']
|
24
|
-
# end
|
data/examples/hello/preload.rb
DELETED
data/examples/internet/config.ru
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'async'
|
4
|
-
require 'async/http/internet'
|
5
|
-
|
6
|
-
# Experimental.
|
7
|
-
require 'kernel/sync'
|
8
|
-
|
9
|
-
class Search
|
10
|
-
def initialize(app)
|
11
|
-
@internet = Async::HTTP::Internet.new
|
12
|
-
|
13
|
-
@app = app
|
14
|
-
end
|
15
|
-
|
16
|
-
# This method uses the `Async` method to create a reactor if required, and then executes the contained code without waiting for the result. So even if the search query takes a long time (e.g. 100ms), it won't hold up the request processing.
|
17
|
-
def async(close: !Async::Task.current?)
|
18
|
-
Async do
|
19
|
-
response = @internet.get("https://google.com/search?q=async+ruby")
|
20
|
-
|
21
|
-
puts response.inspect
|
22
|
-
ensure
|
23
|
-
response&.finish
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# This method uses the experimental `Sync` method to create a reactor if required. If the code is already running in a reactor, it runs synchronously, otherwise it's effectively the same as `Async` and a blocking operation. This allow you to write efficient non-blocking code that works in both traditional web application servers, but gains additional scalability in `Async`-aware servers like Falcon.
|
28
|
-
# You can achieve a similar result by calling `Async{}.wait`, but this is less efficient as it will allocate a sub-task even thought it's not needed.
|
29
|
-
def sync(close: !Async::Task.current?)
|
30
|
-
Sync do
|
31
|
-
response = @internet.get("https://google.com/search?q=async+ruby")
|
32
|
-
|
33
|
-
puts response.inspect
|
34
|
-
ensure
|
35
|
-
response&.finish
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# The only point of this is to invoke one of the above two methods.
|
40
|
-
def call(env)
|
41
|
-
case env['PATH_INFO']
|
42
|
-
when '/sync'
|
43
|
-
self.sync
|
44
|
-
when '/async'
|
45
|
-
self.async
|
46
|
-
end
|
47
|
-
|
48
|
-
return @app.call(env)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
use Search
|
53
|
-
|
54
|
-
run lambda{|env| [404, [], []]}
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Allocations
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def allocations
|
9
|
-
counts = Hash.new{|h,k| h[k] = 0}
|
10
|
-
|
11
|
-
ObjectSpace.each_object do |object|
|
12
|
-
counts[object.class] += 1
|
13
|
-
end
|
14
|
-
|
15
|
-
return counts
|
16
|
-
end
|
17
|
-
|
18
|
-
def print_allocations(minimum = 100)
|
19
|
-
buffer = StringIO.new
|
20
|
-
|
21
|
-
total = allocations.values.sum
|
22
|
-
|
23
|
-
allocations.select{|k,v| v >= minimum}.sort_by{|k,v| -v}.each do |key, value|
|
24
|
-
buffer.puts "#{key}: #{value} allocations"
|
25
|
-
end
|
26
|
-
|
27
|
-
buffer.puts "** Total: #{total} allocations."
|
28
|
-
|
29
|
-
return buffer.string
|
30
|
-
end
|
31
|
-
|
32
|
-
def call(env)
|
33
|
-
if env["PATH_INFO"] == "/allocations"
|
34
|
-
return [200, [], [print_allocations]]
|
35
|
-
else
|
36
|
-
return @app.call(env)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/examples/memory/config.ru
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'allocations'
|
4
|
-
|
5
|
-
use Allocations
|
6
|
-
|
7
|
-
run lambda{|env| [404, [], []]}
|
8
|
-
|
9
|
-
# % curl --insecure https://localhost:9292/allocations
|
10
|
-
# String: 32179 allocations
|
11
|
-
# Array: 10228 allocations
|
12
|
-
# Hash: 1299 allocations
|
13
|
-
# Class: 1118 allocations
|
14
|
-
# ** Total: 50162 allocations.
|
data/examples/push/client.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'async'
|
5
|
-
require 'async/http/endpoint'
|
6
|
-
require 'async/http/client'
|
7
|
-
|
8
|
-
Async do
|
9
|
-
endpoint = Async::HTTP::Endpoint.parse("https://localhost:9292")
|
10
|
-
client = Async::HTTP::Client.new(endpoint, Async::HTTP::Protocol::HTTP2::WithPush)
|
11
|
-
|
12
|
-
response = client.get("/index.html")
|
13
|
-
|
14
|
-
puts response.status
|
15
|
-
puts response.read
|
16
|
-
puts
|
17
|
-
|
18
|
-
while promise = response.promises.dequeue
|
19
|
-
promise.wait
|
20
|
-
|
21
|
-
puts "** Promise: #{promise.request.path} **"
|
22
|
-
puts promise.read
|
23
|
-
puts
|
24
|
-
end
|
25
|
-
ensure
|
26
|
-
client.close
|
27
|
-
end
|
28
|
-
|
29
|
-
puts "Done"
|
data/examples/push/config.ru
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
#!/usr/bin/env falcon --verbose serve --concurrency 1 --config
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
class EarlyHints
|
5
|
-
def initialize(app)
|
6
|
-
@app = app
|
7
|
-
end
|
8
|
-
|
9
|
-
def call(env)
|
10
|
-
path = env['PATH_INFO']
|
11
|
-
early_hints = early_hints = env['rack.early_hints']
|
12
|
-
|
13
|
-
Async.logger.debug("path: #{path} #{early_hints}")
|
14
|
-
|
15
|
-
if path == "/index.html" and early_hints
|
16
|
-
early_hints.push("/style.css")
|
17
|
-
early_hints.push("/script.js")
|
18
|
-
end
|
19
|
-
|
20
|
-
@app.call(env)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
use EarlyHints
|
25
|
-
|
26
|
-
use Rack::Static, :urls => [""], :root => __dir__, :index => 'index.html'
|
27
|
-
|
28
|
-
run lambda{|env| [404, [], ["Not Found"]]}
|
data/examples/push/index.html
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
<!doctype HTML>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Hello World</title>
|
5
|
-
|
6
|
-
<link rel="stylesheet" href="/style.css" />
|
7
|
-
<script type="text/javascript" src="script.js"></script>
|
8
|
-
</head>
|
9
|
-
<body>
|
10
|
-
<h1>Early Hints</h1>
|
11
|
-
|
12
|
-
<p>Check the developer tools to see if early hints worked!</p>
|
13
|
-
</body>
|
14
|
-
</html>
|
data/examples/push/script.js
DELETED
data/examples/push/style.css
DELETED
data/examples/redis/Gemfile
DELETED
data/examples/redis/config.ru
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'sinatra/base'
|
4
|
-
require 'async/redis'
|
5
|
-
require 'async/clock'
|
6
|
-
|
7
|
-
CLIENT = Async::Redis::Client.new(Async::Redis.local_endpoint)
|
8
|
-
|
9
|
-
class MyApp < Sinatra::Base
|
10
|
-
get "/" do
|
11
|
-
puts "Starting BLPOP SLEEP..."
|
12
|
-
duration = Async::Clock.measure do
|
13
|
-
CLIENT.call "BLPOP", "SLEEP", 1
|
14
|
-
end
|
15
|
-
puts "Finished BLPOP SLEEP after #{duration.round(2)}s"
|
16
|
-
|
17
|
-
"ok"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
use MyApp # Then, it will get to Sinatra.
|
22
|
-
run lambda {|env| [404, {}, []]} # Bottom of the stack, give 404.
|
23
|
-
|
24
|
-
# Start server like this:
|
25
|
-
# falcon --verbose serve --threaded --count 1 --bind http://localhost:9292
|
26
|
-
|
27
|
-
# Test server, e.g.:
|
28
|
-
# time ab -n 64 -c 64 http://localhost:9292/
|
data/examples/sequel/Gemfile
DELETED
data/examples/sequel/config.ru
DELETED
Binary file
|
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'async'
|
4
|
-
require 'async/http/endpoint'
|
5
|
-
require 'async/websocket/adapters/rack'
|
6
|
-
|
7
|
-
require 'falcon'
|
8
|
-
|
9
|
-
module WebSocketApp
|
10
|
-
def self.call(env)
|
11
|
-
Async::WebSocket::Adapters::Rack.open(env, protocols: %w[ws]) do |connection|
|
12
|
-
while (message = connection.read)
|
13
|
-
pp message
|
14
|
-
end
|
15
|
-
end or [200, [], ["Websocket only."]]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
Async do
|
20
|
-
websocket_endpoint = Async::HTTP::Endpoint.parse('http://127.0.0.1:3000')
|
21
|
-
|
22
|
-
app = Falcon::Server.middleware(WebSocketApp)
|
23
|
-
|
24
|
-
server = Falcon::Server.new(app, websocket_endpoint)
|
25
|
-
|
26
|
-
server.run.each(&:wait)
|
27
|
-
end
|
data/examples/sinatra/Gemfile
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: https://rubygems.org/
|
3
|
-
specs:
|
4
|
-
async (1.9.1)
|
5
|
-
nio4r (~> 2.3)
|
6
|
-
timers (~> 4.1)
|
7
|
-
async-container (0.5.0)
|
8
|
-
async (~> 1.0)
|
9
|
-
async-io (~> 1.4)
|
10
|
-
async-http (0.24.3)
|
11
|
-
async (~> 1.6)
|
12
|
-
async-io (~> 1.12)
|
13
|
-
http-2 (~> 0.9.0)
|
14
|
-
async-io (1.12.1)
|
15
|
-
async (~> 1.3)
|
16
|
-
falcon (0.15.2)
|
17
|
-
async-container (~> 0.5.0)
|
18
|
-
async-http (~> 0.24.0)
|
19
|
-
async-io (~> 1.9)
|
20
|
-
rack (>= 1.0)
|
21
|
-
samovar (~> 1.3)
|
22
|
-
hitimes (1.2.6)
|
23
|
-
http-2 (0.9.1)
|
24
|
-
mapping (1.1.1)
|
25
|
-
mustermann (1.0.2)
|
26
|
-
nio4r (2.3.1)
|
27
|
-
rack (2.0.8)
|
28
|
-
rack-protection (2.0.3)
|
29
|
-
rack
|
30
|
-
rainbow (2.2.2)
|
31
|
-
rake
|
32
|
-
rake (13.0.1)
|
33
|
-
samovar (1.8.0)
|
34
|
-
mapping (~> 1.0)
|
35
|
-
rainbow (~> 2.0)
|
36
|
-
sinatra (2.0.3)
|
37
|
-
mustermann (~> 1.0)
|
38
|
-
rack (~> 2.0)
|
39
|
-
rack-protection (= 2.0.3)
|
40
|
-
tilt (~> 2.0)
|
41
|
-
tilt (2.0.8)
|
42
|
-
timers (4.1.2)
|
43
|
-
hitimes
|
44
|
-
|
45
|
-
PLATFORMS
|
46
|
-
ruby
|
47
|
-
|
48
|
-
DEPENDENCIES
|
49
|
-
falcon
|
50
|
-
sinatra
|
51
|
-
|
52
|
-
BUNDLED WITH
|
53
|
-
1.16.1
|