itsi-server 0.2.15 → 0.2.17
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/Cargo.lock +75 -73
- data/exe/itsi +6 -1
- data/ext/itsi_acme/Cargo.toml +1 -1
- data/ext/itsi_scheduler/Cargo.toml +1 -1
- data/ext/itsi_server/Cargo.lock +1 -1
- data/ext/itsi_server/Cargo.toml +3 -1
- data/ext/itsi_server/extconf.rb +3 -1
- data/ext/itsi_server/src/lib.rs +7 -1
- data/ext/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +2 -0
- data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +6 -6
- data/ext/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +14 -13
- data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +71 -42
- data/ext/itsi_server/src/ruby_types/itsi_http_response.rs +151 -152
- data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +6 -15
- data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +32 -6
- data/ext/itsi_server/src/ruby_types/itsi_server.rs +1 -1
- data/ext/itsi_server/src/server/binds/listener.rs +49 -8
- data/ext/itsi_server/src/server/frame_stream.rs +142 -0
- data/ext/itsi_server/src/server/http_message_types.rs +143 -10
- data/ext/itsi_server/src/server/io_stream.rs +28 -5
- data/ext/itsi_server/src/server/lifecycle_event.rs +1 -1
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +2 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +8 -10
- data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +2 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +3 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +54 -58
- data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +6 -9
- data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +27 -42
- data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +65 -14
- data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +1 -1
- data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +8 -11
- data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +21 -8
- data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +2 -3
- data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +1 -5
- data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +1 -2
- data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +13 -6
- data/ext/itsi_server/src/server/mod.rs +1 -0
- data/ext/itsi_server/src/server/process_worker.rs +5 -5
- data/ext/itsi_server/src/server/serve_strategy/acceptor.rs +100 -0
- data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +87 -31
- data/ext/itsi_server/src/server/serve_strategy/mod.rs +1 -0
- data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +166 -206
- data/ext/itsi_server/src/server/signal.rs +37 -9
- data/ext/itsi_server/src/server/thread_worker.rs +92 -70
- data/ext/itsi_server/src/services/itsi_http_service.rs +67 -62
- data/ext/itsi_server/src/services/mime_types.rs +185 -183
- data/ext/itsi_server/src/services/rate_limiter.rs +16 -34
- data/ext/itsi_server/src/services/static_file_server.rs +35 -60
- data/lib/itsi/http_request.rb +31 -39
- data/lib/itsi/http_response.rb +5 -0
- data/lib/itsi/rack_env_pool.rb +59 -0
- data/lib/itsi/server/config/config_helpers.rb +1 -2
- data/lib/itsi/server/config/dsl.rb +5 -4
- data/lib/itsi/server/config/middleware/etag.md +3 -7
- data/lib/itsi/server/config/middleware/etag.rb +2 -4
- data/lib/itsi/server/config/middleware/proxy.rb +1 -1
- data/lib/itsi/server/config/middleware/rackup_file.rb +2 -2
- data/lib/itsi/server/config/options/auto_reload_config.rb +6 -2
- data/lib/itsi/server/config/options/include.rb +5 -2
- data/lib/itsi/server/config/options/listen_backlog.rb +1 -1
- data/lib/itsi/server/config/options/pipeline_flush.md +16 -0
- data/lib/itsi/server/config/options/pipeline_flush.rb +19 -0
- data/lib/itsi/server/config/options/send_buffer_size.md +15 -0
- data/lib/itsi/server/config/options/send_buffer_size.rb +19 -0
- data/lib/itsi/server/config/options/writev.md +25 -0
- data/lib/itsi/server/config/options/writev.rb +19 -0
- data/lib/itsi/server/config.rb +43 -31
- data/lib/itsi/server/default_config/Itsi.rb +1 -4
- data/lib/itsi/server/grpc/grpc_call.rb +2 -0
- data/lib/itsi/server/grpc/grpc_interface.rb +2 -2
- data/lib/itsi/server/rack/handler/itsi.rb +3 -1
- data/lib/itsi/server/rack_interface.rb +17 -12
- data/lib/itsi/server/route_tester.rb +1 -1
- data/lib/itsi/server/scheduler_interface.rb +2 -0
- data/lib/itsi/server/version.rb +1 -1
- data/lib/itsi/server.rb +1 -0
- data/lib/ruby_lsp/itsi/addon.rb +12 -13
- metadata +10 -1
@@ -7,8 +7,7 @@ module Itsi
|
|
7
7
|
etag \\
|
8
8
|
type: ${1|"strong","weak"|},
|
9
9
|
algorithm: ${2|"sha256","md5"|},
|
10
|
-
min_body_size: ${3|0,1024|}
|
11
|
-
handle_if_none_match: ${4|true,false|}
|
10
|
+
min_body_size: ${3|0,1024|}
|
12
11
|
SNIPPET
|
13
12
|
|
14
13
|
detail "Enables ETag generation for the server."
|
@@ -17,8 +16,7 @@ module Itsi
|
|
17
16
|
{
|
18
17
|
type: (Enum(["strong", "weak"]) & Required()).default("strong"),
|
19
18
|
algorithm: (Enum(["sha256", "md5"]) & Required()).default("sha256"),
|
20
|
-
min_body_size: Range(0...1024 ** 3).default(0)
|
21
|
-
handle_if_none_match: Bool().default(true)
|
19
|
+
min_body_size: Range(0...1024 ** 3).default(0)
|
22
20
|
}
|
23
21
|
end
|
24
22
|
end
|
@@ -7,7 +7,7 @@ module Itsi
|
|
7
7
|
to: "${1:http://backend.example.com{path_and_query}",
|
8
8
|
backends: [${2:"127.0.0.1:3001", "127.0.0.1:3002"}],
|
9
9
|
backend_priority: ${3|"round_robin","ordered","random"|},
|
10
|
-
headers: { ${4| "X-Forwarded-For" =>
|
10
|
+
headers: { ${4| "X-Forwarded-For" => "{addr}"|} },
|
11
11
|
verify_ssl: ${5|true,false|},
|
12
12
|
timeout: ${6|30,60|},
|
13
13
|
tls_sni: ${7|true,false|},
|
@@ -24,12 +24,12 @@ module Itsi
|
|
24
24
|
super(location, params)
|
25
25
|
raise "Rackup file must be a string" unless app.is_a?(String)
|
26
26
|
|
27
|
-
@app =
|
27
|
+
@app = app
|
28
28
|
end
|
29
29
|
|
30
30
|
def build!
|
31
31
|
app_args = {
|
32
|
-
preloader: -> { @app },
|
32
|
+
preloader: -> { Itsi::Server::RackInterface.for(@app) },
|
33
33
|
sendfile: @params[:sendfile],
|
34
34
|
nonblocking: @params[:nonblocking],
|
35
35
|
script_name: @params[:script_name],
|
@@ -14,11 +14,15 @@ module Itsi
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def build!
|
17
|
+
return if @auto_reloading
|
18
|
+
src = caller.find{|l| !(l =~ /lib\/itsi\/server\/config/) }.split(":").first
|
19
|
+
|
17
20
|
location.instance_eval do
|
18
21
|
return if @auto_reloading
|
19
22
|
|
20
23
|
if @included
|
21
24
|
@included.each do |file|
|
25
|
+
next if "#{file}.rb" == src
|
22
26
|
if ENV["BUNDLE_BIN_PATH"]
|
23
27
|
watch "#{file}.rb", [%w[bundle exec itsi restart]]
|
24
28
|
else
|
@@ -29,9 +33,9 @@ module Itsi
|
|
29
33
|
@auto_reloading = true
|
30
34
|
|
31
35
|
if ENV["BUNDLE_BIN_PATH"]
|
32
|
-
watch
|
36
|
+
watch src, [%w[bundle exec itsi restart]]
|
33
37
|
else
|
34
|
-
watch
|
38
|
+
watch src, [%w[itsi restart]]
|
35
39
|
end
|
36
40
|
end
|
37
41
|
end
|
@@ -26,8 +26,11 @@ module Itsi
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
filename = File.expand_path("#{included_file}.rb")
|
30
|
+
|
31
|
+
code = IO.read(filename)
|
32
|
+
location.instance_eval(code, filename, 1)
|
33
|
+
|
31
34
|
end
|
32
35
|
|
33
36
|
end
|
@@ -4,7 +4,7 @@ module Itsi
|
|
4
4
|
class ListenBacklog < Option
|
5
5
|
|
6
6
|
insert_text <<~SNIPPET
|
7
|
-
listen_backlog ${1|
|
7
|
+
listen_backlog ${1|1024,2048,4096|}
|
8
8
|
SNIPPET
|
9
9
|
|
10
10
|
detail "Specifies the size of the listen backlog for the socket. Larger backlog sizes can improve performance for high-throughput applications by allowing more pending connections to queue, but may increase memory usage. The default value is 1024."
|
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
title: Pipeline Flush
|
3
|
+
url: /options/pipeline_flush
|
4
|
+
---
|
5
|
+
|
6
|
+
Aggregates flushes to better support pipelined responses. (HTTP1 only)
|
7
|
+
The default value is `false`.
|
8
|
+
|
9
|
+
## Configuration
|
10
|
+
```ruby {filename=Itsi.rb}
|
11
|
+
pipeline_flush true
|
12
|
+
```
|
13
|
+
|
14
|
+
```ruby {filename=Itsi.rb}
|
15
|
+
pipeline_flush false
|
16
|
+
```
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Itsi
|
2
|
+
class Server
|
3
|
+
module Config
|
4
|
+
class PipelineFlush < Option
|
5
|
+
|
6
|
+
insert_text <<~SNIPPET
|
7
|
+
pipeline_flush ${1|true,false|}
|
8
|
+
SNIPPET
|
9
|
+
|
10
|
+
detail "Aggregates flushes to better support pipelined responses. (HTTP1 only)."
|
11
|
+
|
12
|
+
schema do
|
13
|
+
(Bool() & Required()).default(false)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
title: Send Buffer Size
|
3
|
+
url: /options/send_buffer_size
|
4
|
+
---
|
5
|
+
|
6
|
+
Configures the size of the send buffer for the socket. Larger buffer sizes can improve performance for high-throughput applications but may increase memory usage. The default value is 262,144 bytes.
|
7
|
+
|
8
|
+
## Configuration
|
9
|
+
```ruby {filename=Itsi.rb}
|
10
|
+
send_buffer_size 262_144
|
11
|
+
```
|
12
|
+
|
13
|
+
```ruby {filename=Itsi.rb}
|
14
|
+
send_buffer_size 1_048_576
|
15
|
+
```
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Itsi
|
2
|
+
class Server
|
3
|
+
module Config
|
4
|
+
class SendBufferSize < Option
|
5
|
+
|
6
|
+
insert_text <<~SNIPPET
|
7
|
+
send_buffer_size ${1|262_144,1_048_576|}
|
8
|
+
SNIPPET
|
9
|
+
|
10
|
+
detail "Specifies the size of the send buffer for the socket. Larger buffer sizes can improve performance for high-throughput applications but may increase memory usage. The default value is 262,144 bytes."
|
11
|
+
|
12
|
+
schema do
|
13
|
+
(Type(Integer) & Range(1..Float::INFINITY) & Required()).default(262_144)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
---
|
2
|
+
title: Write Vectored
|
3
|
+
url: /options/writev
|
4
|
+
---
|
5
|
+
|
6
|
+
Set whether HTTP/1 connections should try to use vectored writes,
|
7
|
+
or always flatten into a single buffer.
|
8
|
+
|
9
|
+
Note that setting this to false may mean more copies of body data,
|
10
|
+
but may also improve performance when an IO transport doesn't
|
11
|
+
support vectored writes well, such as most TLS implementations.
|
12
|
+
|
13
|
+
Setting this to true will force hyper to use queued strategy
|
14
|
+
which may eliminate unnecessary cloning on some TLS backends
|
15
|
+
|
16
|
+
Default is `nil` in which case hyper will try to guess which mode to use
|
17
|
+
|
18
|
+
## Configuration
|
19
|
+
```ruby {filename=Itsi.rb}
|
20
|
+
writev true
|
21
|
+
```
|
22
|
+
|
23
|
+
```ruby {filename=Itsi.rb}
|
24
|
+
writev false
|
25
|
+
```
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Itsi
|
2
|
+
class Server
|
3
|
+
module Config
|
4
|
+
class Writev < Option
|
5
|
+
|
6
|
+
insert_text <<~SNIPPET
|
7
|
+
writev ${1|true,false|}
|
8
|
+
SNIPPET
|
9
|
+
|
10
|
+
detail "Set whether HTTP/1 connections should try to use vectored writes"
|
11
|
+
|
12
|
+
schema do
|
13
|
+
(Bool() & Required()).default(false)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/itsi/server/config.rb
CHANGED
@@ -41,39 +41,43 @@ module Itsi
|
|
41
41
|
DSL.evaluate(&builder_proc)
|
42
42
|
elsif args[:static]
|
43
43
|
DSL.evaluate do
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
44
|
+
rate_limit key: "address", store_config: "in_memory", requests: 5, seconds: 10
|
45
|
+
etag type: "strong", algorithm: "md5", min_body_size: 1024 * 1024
|
46
|
+
compress min_size: 1024 * 1024, level: "fastest", algorithms: %w[zstd gzip br deflate],
|
47
|
+
mime_types: %w[all], compress_streams: true
|
48
|
+
log_requests before: { level: "DEBUG", format: "[{request_id}] {method} {path_and_query} - {addr} " },
|
49
|
+
after: { level: "DEBUG",
|
50
|
+
format: "[{request_id}] └─ {status} in {response_time}" }
|
51
|
+
nodelay false
|
52
|
+
static_assets \
|
53
|
+
relative_path: true,
|
54
|
+
allowed_extensions: [],
|
55
|
+
root_dir: ".",
|
56
|
+
not_found_behavior: { error: "not_found" },
|
57
|
+
auto_index: true,
|
58
|
+
try_html_extension: true,
|
59
|
+
max_file_size_in_memory: 1024 * 1024, # 1MB
|
60
|
+
max_files_in_memory: 1000,
|
61
|
+
file_check_interval: 1,
|
62
|
+
serve_hidden_files: false,
|
63
|
+
headers: {
|
64
|
+
"X-Content-Type-Options" => "nosniff"
|
65
|
+
}
|
67
66
|
end
|
68
67
|
elsif File.exist?(config_file_path.to_s)
|
69
|
-
DSL.evaluate
|
68
|
+
DSL.evaluate do
|
69
|
+
include config_file_path.gsub(".rb", "")
|
70
|
+
rackup_file args[:rackup_file], script_name: "/" if args.key?(:rackup_file)
|
71
|
+
end
|
70
72
|
elsif File.exist?("./config.ru")
|
71
73
|
DSL.evaluate do
|
72
74
|
preload true
|
73
|
-
rackup_file args.fetch(:rackup_file, "./config.ru")
|
75
|
+
rackup_file args.fetch(:rackup_file, "./config.ru"), script_name: "/"
|
74
76
|
end
|
75
77
|
else
|
76
|
-
DSL.evaluate
|
78
|
+
DSL.evaluate do
|
79
|
+
rackup_file args[:rackup_file], script_name: "/" if args.key?(:rackup_file)
|
80
|
+
end
|
77
81
|
end
|
78
82
|
|
79
83
|
itsifile_config.transform_keys!(&:to_sym)
|
@@ -106,9 +110,8 @@ module Itsi
|
|
106
110
|
Server.write_pid
|
107
111
|
end
|
108
112
|
|
109
|
-
|
110
113
|
srv_config = {
|
111
|
-
workers: args.fetch(:workers) { itsifile_config.fetch(:workers,
|
114
|
+
workers: args.fetch(:workers) { itsifile_config.fetch(:workers, nil) },
|
112
115
|
worker_memory_limit: args.fetch(:worker_memory_limit) { itsifile_config.fetch(:worker_memory_limit, nil) },
|
113
116
|
silence: args.fetch(:silence) { itsifile_config.fetch(:silence, false) },
|
114
117
|
shutdown_timeout: args.fetch(:shutdown_timeout) { itsifile_config.fetch(:shutdown_timeout, 5) },
|
@@ -129,7 +132,7 @@ module Itsi
|
|
129
132
|
multithreaded_reactor: args.fetch(:multithreaded_reactor) do
|
130
133
|
itsifile_config.fetch(:multithreaded_reactor, nil)
|
131
134
|
end,
|
132
|
-
pin_worker_cores: args.fetch(:pin_worker_cores) { itsifile_config.fetch(:pin_worker_cores,
|
135
|
+
pin_worker_cores: args.fetch(:pin_worker_cores) { itsifile_config.fetch(:pin_worker_cores, false) },
|
133
136
|
scheduler_class: args.fetch(:scheduler_class) { itsifile_config.fetch(:scheduler_class, nil) },
|
134
137
|
oob_gc_responses_threshold: args.fetch(:oob_gc_responses_threshold) do
|
135
138
|
itsifile_config.fetch(:oob_gc_responses_threshold, nil)
|
@@ -141,14 +144,21 @@ module Itsi
|
|
141
144
|
log_format: args.fetch(:log_format) { itsifile_config.fetch(:log_format, nil) },
|
142
145
|
log_target: args.fetch(:log_target) { itsifile_config.fetch(:log_target, nil) },
|
143
146
|
log_target_filters: args.fetch(:log_target_filters) { itsifile_config.fetch(:log_target_filters, nil) },
|
147
|
+
pipeline_flush: itsifile_config.fetch(:pipeline_flush, true),
|
148
|
+
writev: itsifile_config.fetch(:writev, false),
|
149
|
+
max_concurrent_streams: itsifile_config.fetch(:max_concurrent_streams, nil),
|
150
|
+
max_local_error_reset_streams: itsifile_config.fetch(:max_local_error_reset_streams, nil),
|
151
|
+
max_header_list_size: itsifile_config.fetch(:max_header_list_size, 2 * 1024 * 1024),
|
152
|
+
max_send_buf_size: itsifile_config.fetch(:max_send_buf_size, 64 * 1024),
|
144
153
|
binds: args.fetch(:binds) { itsifile_config.fetch(:binds, ["http://0.0.0.0:3000"]) },
|
145
154
|
middleware_loader: middleware_loader,
|
146
|
-
listeners: args.fetch(:listeners
|
155
|
+
listeners: args.fetch(:listeners, nil),
|
147
156
|
reuse_address: itsifile_config.fetch(:reuse_address, true),
|
148
157
|
reuse_port: itsifile_config.fetch(:reuse_port, true),
|
149
158
|
listen_backlog: itsifile_config.fetch(:listen_backlog, 1024),
|
150
159
|
nodelay: itsifile_config.fetch(:nodelay, true),
|
151
|
-
recv_buffer_size: itsifile_config.fetch(:recv_buffer_size, 262_144)
|
160
|
+
recv_buffer_size: itsifile_config.fetch(:recv_buffer_size, 262_144),
|
161
|
+
send_buffer_size: itsifile_config.fetch(:send_buffer_size, 262_144)
|
152
162
|
}.transform_keys(&:to_s)
|
153
163
|
|
154
164
|
[srv_config, errors_to_error_lines(errors)]
|
@@ -223,6 +233,8 @@ module Itsi
|
|
223
233
|
|
224
234
|
# Find config file path, if it exists.
|
225
235
|
def self.config_file_path(config_file_path = nil)
|
236
|
+
raise "Config file #{config_file_path} does not exist" if config_file_path && !File.exist?(config_file_path)
|
237
|
+
|
226
238
|
config_file_path ||= \
|
227
239
|
if File.exist?(ITSI_DEFAULT_CONFIG_FILE)
|
228
240
|
ITSI_DEFAULT_CONFIG_FILE
|
@@ -10,10 +10,7 @@ env = ENV.fetch("APP_ENV") { ENV.fetch("RACK_ENV", "development") }
|
|
10
10
|
|
11
11
|
# Number of worker processes to spawn
|
12
12
|
# If more than 1, Itsi will be booted in Cluster mode
|
13
|
-
workers ENV
|
14
|
-
require "etc"
|
15
|
-
env == "development" ? 1 : nil
|
16
|
-
}
|
13
|
+
workers ENV["ITSI_WORKERS"]&.to_i || env == "development" ? 1 : nil
|
17
14
|
|
18
15
|
# Number of threads to spawn per worker process
|
19
16
|
# For pure CPU bound applicationss, you'll get the best results keeping this number low
|
@@ -79,7 +79,7 @@ module Itsi
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def handle_client_streaming(active_call)
|
82
|
-
response = service.send(active_call.method_name, active_call
|
82
|
+
response = service.send(active_call.method_name, active_call)
|
83
83
|
active_call.remote_send(response)
|
84
84
|
end
|
85
85
|
|
@@ -94,7 +94,7 @@ module Itsi
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def handle_bidi_streaming(active_call)
|
97
|
-
result = service.send(active_call.method_name, active_call.
|
97
|
+
result = service.send(active_call.method_name, active_call.each, active_call) do |response|
|
98
98
|
active_call.remote_send(response)
|
99
99
|
end
|
100
100
|
return unless result.is_a?(Enumerator)
|
@@ -12,7 +12,7 @@ module Itsi
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
lambda do |request|
|
15
|
-
Server.respond(request, app.call(request.to_rack_env))
|
15
|
+
Server.respond(request, app.call(env = request.to_rack_env), env)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -20,14 +20,14 @@ module Itsi
|
|
20
20
|
# Here we build the env, and invoke the Rack app's call method.
|
21
21
|
# We then turn the Rack response into something Itsi server understands.
|
22
22
|
def call(app, request)
|
23
|
-
respond request, app.call(request.to_rack_env)
|
23
|
+
respond request, app.call(env = request.to_rack_env), env
|
24
24
|
end
|
25
25
|
|
26
26
|
# Itsi responses are asynchronous and can be streamed.
|
27
27
|
# Response chunks are sent using response.send_frame
|
28
28
|
# and the response is finished using response.close_write.
|
29
29
|
# If only a single chunk is written, you can use the #send_and_close method.
|
30
|
-
def respond(request, (status, headers, body))
|
30
|
+
def respond(request, (status, headers, body), env)
|
31
31
|
response = request.response
|
32
32
|
|
33
33
|
# Don't try and respond if we've been hijacked.
|
@@ -39,13 +39,16 @@ module Itsi
|
|
39
39
|
|
40
40
|
# 2. Set Headers
|
41
41
|
body_streamer = streaming_body?(body) ? body : headers.delete("rack.hijack")
|
42
|
-
|
43
|
-
|
42
|
+
|
43
|
+
response.reserve_headers(headers.size)
|
44
|
+
|
45
|
+
for key, value in headers
|
46
|
+
case value
|
47
|
+
when String then response[key] = value
|
48
|
+
when Array
|
44
49
|
value.each do |v|
|
45
50
|
response[key] = v
|
46
51
|
end
|
47
|
-
elsif value.is_a?(String)
|
48
|
-
response[key] = value
|
49
52
|
end
|
50
53
|
end
|
51
54
|
|
@@ -53,15 +56,15 @@ module Itsi
|
|
53
56
|
# As soon as we start setting the response
|
54
57
|
# the server will begin to stream it to the client.
|
55
58
|
|
56
|
-
# If we're partially hijacked or returned a streaming body,
|
57
|
-
# stream this response.
|
58
59
|
|
59
60
|
if body_streamer
|
61
|
+
# If we're partially hijacked or returned a streaming body,
|
62
|
+
# stream this response.
|
60
63
|
body_streamer.call(response)
|
61
64
|
|
62
|
-
# If we're enumerable with more than one chunk
|
63
|
-
# also stream, otherwise write in a single chunk
|
64
65
|
elsif body.respond_to?(:each) || body.respond_to?(:to_ary)
|
66
|
+
# If we're enumerable with more than one chunk
|
67
|
+
# also stream, otherwise write in a single chunk
|
65
68
|
unless body.respond_to?(:each)
|
66
69
|
body = body.to_ary
|
67
70
|
raise "Body #to_ary didn't return an array" unless body.is_a?(Array)
|
@@ -78,8 +81,10 @@ module Itsi
|
|
78
81
|
else
|
79
82
|
response.send_and_close(body.to_s)
|
80
83
|
end
|
84
|
+
rescue EOFError
|
85
|
+
response.close
|
81
86
|
ensure
|
82
|
-
|
87
|
+
RackEnvPool.checkin(env)
|
83
88
|
body.close if body.respond_to?(:close)
|
84
89
|
end
|
85
90
|
|
@@ -23,7 +23,7 @@ module Itsi
|
|
23
23
|
when "cors"
|
24
24
|
"\e[33mcors\e[0m(#{mw_args["allow_origins"].join(" ")}, #{mw_args["allow_methods"].join(" ")})"
|
25
25
|
when "etag"
|
26
|
-
"\e[33metag\e[0m(#{mw_args["type"]}/#{mw_args["algorithm"]}
|
26
|
+
"\e[33metag\e[0m(#{mw_args["type"]}/#{mw_args["algorithm"]})"
|
27
27
|
when "cache_control"
|
28
28
|
"\e[33mcache_control\e[0m(max_age: #{mw_args["max_age"]}, #{mw_args.select do |_, v|
|
29
29
|
v == true
|
data/lib/itsi/server/version.rb
CHANGED
data/lib/itsi/server.rb
CHANGED
@@ -12,6 +12,7 @@ require_relative "server/rack/handler/itsi"
|
|
12
12
|
require_relative "server/config"
|
13
13
|
require_relative "server/typed_handlers"
|
14
14
|
require_relative "standard_headers"
|
15
|
+
require_relative "rack_env_pool"
|
15
16
|
require_relative "http_request"
|
16
17
|
require_relative "http_response"
|
17
18
|
require_relative "passfile"
|
data/lib/ruby_lsp/itsi/addon.rb
CHANGED
@@ -5,8 +5,8 @@ require "itsi/server"
|
|
5
5
|
|
6
6
|
module RubyLsp
|
7
7
|
module Itsi
|
8
|
-
class Addon < ::RubyLsp::Addon
|
9
|
-
def activate(
|
8
|
+
class Addon < ::RubyLsp::Addon # rubocop:disable Style/Documentation
|
9
|
+
def activate(_global_state, message_queue)
|
10
10
|
@message_queue = message_queue
|
11
11
|
end
|
12
12
|
|
@@ -20,33 +20,34 @@ module RubyLsp
|
|
20
20
|
"0.1.0"
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
23
|
def create_completion_listener(response_builder, node_context, dispatcher, uri)
|
25
|
-
return unless uri.to_s.
|
24
|
+
return unless uri.to_s =~ /itsi.rb$/i
|
25
|
+
|
26
26
|
@in_itsi_file = true
|
27
27
|
CompletionListener.new(response_builder, node_context, dispatcher, uri)
|
28
28
|
end
|
29
29
|
|
30
30
|
def create_hover_listener(response_builder, node_context, dispatcher)
|
31
31
|
hl = dispatcher.listeners[:on_call_node_enter].find { |c| c.is_a?(RubyLsp::Listeners::Hover) }
|
32
|
-
return unless hl.instance_variable_get("@path").to_s.
|
32
|
+
return unless hl.instance_variable_get("@path").to_s =~ /itsi.rb$/i
|
33
|
+
|
33
34
|
HoverListener.new(response_builder, node_context, dispatcher)
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
|
-
class HoverListener
|
38
|
+
class HoverListener # rubocop:disable Style/Documentation
|
38
39
|
def initialize(response_builder, node_context, dispatcher)
|
39
40
|
@response_builder = response_builder
|
40
41
|
@node_context = node_context
|
41
42
|
@dispatcher = dispatcher
|
42
43
|
|
43
|
-
@options_by_name = ::Itsi::Server::Config::Option.subclasses.group_by(&:option_name).
|
44
|
-
@middlewares_by_name = ::Itsi::Server::Config::Middleware.subclasses.group_by(&:middleware_name).
|
44
|
+
@options_by_name = ::Itsi::Server::Config::Option.subclasses.group_by(&:option_name).transform_values(&:first)
|
45
|
+
@middlewares_by_name = ::Itsi::Server::Config::Middleware.subclasses.group_by(&:middleware_name).transform_values(&:first)
|
45
46
|
# Register for call nodes for hover events
|
46
47
|
dispatcher.register(self, :on_call_node_enter)
|
47
48
|
end
|
48
49
|
|
49
|
-
def on_call_node_enter(node)
|
50
|
+
def on_call_node_enter(node) # rubocop:disable Metrics/MethodLength
|
50
51
|
if (matched_class = @options_by_name[node.message.to_sym])
|
51
52
|
@response_builder.push(
|
52
53
|
matched_class.documentation,
|
@@ -61,7 +62,7 @@ module RubyLsp
|
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
64
|
-
class CompletionListener
|
65
|
+
class CompletionListener # rubocop:disable Style/Documentation
|
65
66
|
def initialize(response_builder, node_context, dispatcher, uri)
|
66
67
|
@response_builder = response_builder
|
67
68
|
@node_context = node_context
|
@@ -74,7 +75,7 @@ module RubyLsp
|
|
74
75
|
dispatcher.register(self, :completion_item_resolve)
|
75
76
|
end
|
76
77
|
|
77
|
-
def on_call_node_enter(node)
|
78
|
+
def on_call_node_enter(node) # rubocop:disable Metrics/AbcSize
|
78
79
|
# Only handle method calls that are being typed (i.e. no arguments yet)
|
79
80
|
return unless node.arguments.nil?
|
80
81
|
|
@@ -122,8 +123,6 @@ module RubyLsp
|
|
122
123
|
end
|
123
124
|
end
|
124
125
|
end
|
125
|
-
|
126
|
-
|
127
126
|
end
|
128
127
|
end
|
129
128
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: itsi-server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wouter Coppieters
|
@@ -197,6 +197,7 @@ files:
|
|
197
197
|
- ext/itsi_server/src/server/binds/tls.rs
|
198
198
|
- ext/itsi_server/src/server/binds/tls/locked_dir_cache.rs
|
199
199
|
- ext/itsi_server/src/server/byte_frame.rs
|
200
|
+
- ext/itsi_server/src/server/frame_stream.rs
|
200
201
|
- ext/itsi_server/src/server/http_message_types.rs
|
201
202
|
- ext/itsi_server/src/server/io_stream.rs
|
202
203
|
- ext/itsi_server/src/server/lifecycle_event.rs
|
@@ -233,6 +234,7 @@ files:
|
|
233
234
|
- ext/itsi_server/src/server/process_worker.rs
|
234
235
|
- ext/itsi_server/src/server/redirect_type.rs
|
235
236
|
- ext/itsi_server/src/server/request_job.rs
|
237
|
+
- ext/itsi_server/src/server/serve_strategy/acceptor.rs
|
236
238
|
- ext/itsi_server/src/server/serve_strategy/cluster_mode.rs
|
237
239
|
- ext/itsi_server/src/server/serve_strategy/mod.rs
|
238
240
|
- ext/itsi_server/src/server/serve_strategy/single_mode.rs
|
@@ -259,6 +261,7 @@ files:
|
|
259
261
|
- lib/itsi/http_request/response_status_shortcodes.rb
|
260
262
|
- lib/itsi/http_response.rb
|
261
263
|
- lib/itsi/passfile.rb
|
264
|
+
- lib/itsi/rack_env_pool.rb
|
262
265
|
- lib/itsi/server.rb
|
263
266
|
- lib/itsi/server/config.rb
|
264
267
|
- lib/itsi/server/config/config_helpers.rb
|
@@ -485,6 +488,8 @@ files:
|
|
485
488
|
- lib/itsi/server/config/options/oob_gc_responses_threshold.rb
|
486
489
|
- lib/itsi/server/config/options/pin_worker_cores.md
|
487
490
|
- lib/itsi/server/config/options/pin_worker_cores.rb
|
491
|
+
- lib/itsi/server/config/options/pipeline_flush.md
|
492
|
+
- lib/itsi/server/config/options/pipeline_flush.rb
|
488
493
|
- lib/itsi/server/config/options/preload.md
|
489
494
|
- lib/itsi/server/config/options/preload.rb
|
490
495
|
- lib/itsi/server/config/options/recv_buffer_size.md
|
@@ -501,6 +506,8 @@ files:
|
|
501
506
|
- lib/itsi/server/config/options/ruby_thread_request_backlog_size.rb
|
502
507
|
- lib/itsi/server/config/options/scheduler_threads.md
|
503
508
|
- lib/itsi/server/config/options/scheduler_threads.rb
|
509
|
+
- lib/itsi/server/config/options/send_buffer_size.md
|
510
|
+
- lib/itsi/server/config/options/send_buffer_size.rb
|
504
511
|
- lib/itsi/server/config/options/shutdown_timeout.md
|
505
512
|
- lib/itsi/server/config/options/shutdown_timeout.rb
|
506
513
|
- lib/itsi/server/config/options/stream_body.md
|
@@ -513,6 +520,8 @@ files:
|
|
513
520
|
- lib/itsi/server/config/options/worker_memory_limit.rb
|
514
521
|
- lib/itsi/server/config/options/workers.md
|
515
522
|
- lib/itsi/server/config/options/workers.rb
|
523
|
+
- lib/itsi/server/config/options/writev.md
|
524
|
+
- lib/itsi/server/config/options/writev.rb
|
516
525
|
- lib/itsi/server/config/typed_struct.rb
|
517
526
|
- lib/itsi/server/default_app/default_app.rb
|
518
527
|
- lib/itsi/server/default_app/index.html
|