falcon 0.22.3 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -2
- data/falcon.gemspec +3 -3
- data/lib/falcon/adapters/push.rb +59 -0
- data/lib/falcon/adapters/rack.rb +13 -0
- data/lib/falcon/server.rb +1 -0
- data/lib/falcon/version.rb +1 -1
- data/tasks/benchmark.rake +22 -7
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0e70db57599ceb24ef8ba959ccf4e9d7c43c774e5bafec0e08956d98362dc31
|
4
|
+
data.tar.gz: 742ea2d7f69b142c9e05cc4f9f2dca3d372c3b41f0b3e4d0733923b7e50853e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f140e5df2529863dc8ad27cdd16cc6fa7d24e13db1d95f545e09b4e49255762b44cf5f497402be4461570277d6a7d76afda7d9291a397aeae99177743b74f8e7
|
7
|
+
data.tar.gz: e951345f66cfaad7e3e3d82e818cc7079f4156b60a03f1e1ee717ebffab8ac8c2585c317061836fd90346cef0d5103510e5a091209750446a6d061c5468fc799
|
data/.travis.yml
CHANGED
@@ -27,11 +27,9 @@ matrix:
|
|
27
27
|
- rvm: jruby-head
|
28
28
|
env: JRUBY_OPTS="--debug -X+O"
|
29
29
|
- rvm: ruby-head
|
30
|
-
- rvm: rbx-3
|
31
30
|
allow_failures:
|
32
31
|
- rvm: truffleruby
|
33
32
|
- rvm: ruby-head
|
34
33
|
- rvm: jruby-head
|
35
34
|
- rvm: truffleruby
|
36
|
-
- rvm: rbx-3
|
37
35
|
- gemfile: gems/rack3.gemfile
|
data/falcon.gemspec
CHANGED
@@ -16,11 +16,11 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
|
-
spec.add_dependency("http-protocol", "~> 0.
|
19
|
+
spec.add_dependency("http-protocol", "~> 0.15")
|
20
20
|
|
21
21
|
spec.add_dependency("async", "~> 1.13")
|
22
22
|
spec.add_dependency("async-io", "~> 1.18")
|
23
|
-
spec.add_dependency("async-http", "~> 0.
|
23
|
+
spec.add_dependency("async-http", "~> 0.38.0")
|
24
24
|
spec.add_dependency("async-container", "~> 0.9.0")
|
25
25
|
|
26
26
|
spec.add_dependency("rack", ">= 1.0")
|
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
|
34
34
|
spec.add_development_dependency "async-process", "~> 1.1"
|
35
35
|
|
36
|
-
spec.add_development_dependency "covered"
|
36
|
+
spec.add_development_dependency "covered", "~> 0.10"
|
37
37
|
spec.add_development_dependency "bundler"
|
38
38
|
spec.add_development_dependency "rspec", "~> 3.6"
|
39
39
|
spec.add_development_dependency "rake"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Copyright, 2019, 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 'async/http/middleware'
|
22
|
+
|
23
|
+
module Falcon
|
24
|
+
module Adapters
|
25
|
+
# Interprets link headers to implement server push.
|
26
|
+
# https://tools.ietf.org/html/rfc8288
|
27
|
+
class Push < Async::HTTP::Middleware
|
28
|
+
PRELOAD = /<(?<path>.*?)>;.*?rel=preload/
|
29
|
+
|
30
|
+
def self.early_hints(headers)
|
31
|
+
headers.each do |key, value|
|
32
|
+
if key.casecmp("link").zero? and match = PRELOAD.match(value)
|
33
|
+
yield match[:path]
|
34
|
+
else
|
35
|
+
Async.logger.warn(request) {"Unsure how to handle early hints header: #{key}"}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def call(request)
|
41
|
+
response = super
|
42
|
+
|
43
|
+
Async.logger.debug(self) {response}
|
44
|
+
|
45
|
+
if request.push?
|
46
|
+
Async.logger.debug(self) {response.headers['link']}
|
47
|
+
|
48
|
+
response.headers['link']&.each do |link|
|
49
|
+
if match = link.match(PRELOAD)
|
50
|
+
request.push(match[:path])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
return response
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/falcon/adapters/rack.rb
CHANGED
@@ -55,6 +55,9 @@ module Falcon
|
|
55
55
|
RACK_HIJACK = 'rack.hijack'.freeze
|
56
56
|
RACK_IS_HIJACK = 'rack.hijack?'.freeze
|
57
57
|
RACK_HIJACK_IO = 'rack.hijack_io'.freeze
|
58
|
+
RACK_EARLY_HINTS = "rack.early_hints".freeze
|
59
|
+
|
60
|
+
ASYNC_HTTP_REQUEST = "async.http.request".freeze
|
58
61
|
|
59
62
|
# Header constants
|
60
63
|
HTTP_X_FORWARDED_PROTO = 'HTTP_X_FORWARDED_PROTO'.freeze
|
@@ -120,6 +123,8 @@ module Falcon
|
|
120
123
|
env = {
|
121
124
|
RACK_VERSION => [2, 0, 0],
|
122
125
|
|
126
|
+
ASYNC_HTTP_REQUEST => request,
|
127
|
+
|
123
128
|
RACK_INPUT => Input.new(request.body),
|
124
129
|
RACK_ERRORS => $stderr,
|
125
130
|
RACK_LOGGER => Async.logger,
|
@@ -155,6 +160,14 @@ module Falcon
|
|
155
160
|
|
156
161
|
self.unwrap_request(request, env)
|
157
162
|
|
163
|
+
if request.push?
|
164
|
+
env[RACK_EARLY_HINTS] = lambda do |headers|
|
165
|
+
Falcon::Adapters::Push.early_hints(headers) do |path|
|
166
|
+
request.push(path)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
158
171
|
if request.hijack?
|
159
172
|
env[RACK_IS_HIJACK] = true
|
160
173
|
|
data/lib/falcon/server.rb
CHANGED
data/lib/falcon/version.rb
CHANGED
data/tasks/benchmark.rake
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
|
2
2
|
namespace :benchmark do
|
3
|
-
task :
|
3
|
+
task :hello do
|
4
|
+
@config_path = File.expand_path("../examples/hello/config.ru", __dir__)
|
5
|
+
@request_path = "/"
|
6
|
+
end
|
7
|
+
|
8
|
+
task :small do
|
9
|
+
@config_path = File.expand_path("../examples/benchmark/config.ru", __dir__)
|
10
|
+
@request_path = "/small"
|
11
|
+
end
|
12
|
+
|
13
|
+
task :big do
|
14
|
+
@config_path ||= File.expand_path("../examples/benchmark/config.ru", __dir__)
|
15
|
+
@request_path ||= "/big"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :compare => :big do
|
4
19
|
require 'etc'
|
5
20
|
|
6
21
|
require 'async/reactor'
|
@@ -10,8 +25,7 @@ namespace :benchmark do
|
|
10
25
|
require 'async/http/url_endpoint'
|
11
26
|
|
12
27
|
host = "http://127.0.0.1:9292"
|
13
|
-
|
14
|
-
|
28
|
+
|
15
29
|
threads = Etc.nprocessors
|
16
30
|
|
17
31
|
perf = ["perf", "record", "-F", "max", "-a", "--"]
|
@@ -20,7 +34,8 @@ namespace :benchmark do
|
|
20
34
|
# ["puma", "--bind", host.gsub("http", "tcp")],
|
21
35
|
["puma", "--workers", threads.to_s, "--bind", host.gsub("http", "tcp")],
|
22
36
|
# ["rbspy", "record", "--", "falcon", "serve", "--threaded", "--bind", host, "--config"]
|
23
|
-
["falcon", "serve", "--bind", host, "--config"]
|
37
|
+
["falcon", "serve", "--bind", host, "--config"],
|
38
|
+
# ["falcon", "serve", "--reuse-port", "--bind", host, "--config"],
|
24
39
|
]
|
25
40
|
|
26
41
|
Async.logger.info!
|
@@ -37,7 +52,7 @@ namespace :benchmark do
|
|
37
52
|
|
38
53
|
server_task = task.async do
|
39
54
|
$stderr.puts "Starting #{command.first}"
|
40
|
-
server_status = Async::Process.spawn(*command, config_path)
|
55
|
+
server_status = Async::Process.spawn(*command, @config_path)
|
41
56
|
end
|
42
57
|
|
43
58
|
begin
|
@@ -47,7 +62,7 @@ namespace :benchmark do
|
|
47
62
|
|
48
63
|
socket = endpoint.connect
|
49
64
|
|
50
|
-
request = Async::HTTP::Request.new("http", "localhost", "GET",
|
65
|
+
request = Async::HTTP::Request.new("http", "localhost", "GET", @request_path)
|
51
66
|
stream = Async::IO::Stream.new(socket)
|
52
67
|
protocol = Async::HTTP::Protocol::HTTP1.client(stream)
|
53
68
|
|
@@ -76,7 +91,7 @@ namespace :benchmark do
|
|
76
91
|
|
77
92
|
# Async::Process.spawn("ab", "-n", "2000", "#{host}/small")
|
78
93
|
|
79
|
-
Async::Process.spawn("wrk", "-c", c.to_s, "-t", (n+1).to_s, "-d", "2", "#{host}
|
94
|
+
Async::Process.spawn("wrk", "-c", c.to_s, "-t", (n+1).to_s, "-d", "2", "#{host}#{@request_path}")
|
80
95
|
end
|
81
96
|
ensure
|
82
97
|
server_task.stop
|
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.
|
4
|
+
version: 0.23.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-02-
|
11
|
+
date: 2019-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http-protocol
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.15'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.15'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: async
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.
|
61
|
+
version: 0.38.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.
|
68
|
+
version: 0.38.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: async-container
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,16 +168,16 @@ dependencies:
|
|
168
168
|
name: covered
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
|
-
- - "
|
171
|
+
- - "~>"
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: '0'
|
173
|
+
version: '0.10'
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
|
-
- - "
|
178
|
+
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: '0'
|
180
|
+
version: '0.10'
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: bundler
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -250,6 +250,7 @@ files:
|
|
250
250
|
- lib/falcon.rb
|
251
251
|
- lib/falcon/adapters/input.rb
|
252
252
|
- lib/falcon/adapters/output.rb
|
253
|
+
- lib/falcon/adapters/push.rb
|
253
254
|
- lib/falcon/adapters/rack.rb
|
254
255
|
- lib/falcon/adapters/response.rb
|
255
256
|
- lib/falcon/adapters/rewindable.rb
|