itsi 0.2.14 → 0.2.16

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/Cargo.lock +168 -219
  4. data/crates/itsi_scheduler/Cargo.toml +1 -1
  5. data/crates/itsi_scheduler/extconf.rb +3 -1
  6. data/crates/itsi_server/Cargo.lock +1 -1
  7. data/crates/itsi_server/Cargo.toml +3 -2
  8. data/crates/itsi_server/extconf.rb +3 -1
  9. data/crates/itsi_server/src/lib.rs +1 -0
  10. data/crates/itsi_server/src/ruby_types/itsi_grpc_call.rs +2 -2
  11. data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +9 -11
  12. data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +6 -1
  13. data/crates/itsi_server/src/server/binds/listener.rs +4 -1
  14. data/crates/itsi_server/src/server/http_message_types.rs +1 -1
  15. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +32 -34
  16. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +3 -4
  17. data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +23 -38
  18. data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +65 -14
  19. data/crates/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +1 -1
  20. data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +1 -1
  21. data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +21 -8
  22. data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +1 -5
  23. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +8 -6
  24. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +12 -3
  25. data/crates/itsi_server/src/server/process_worker.rs +2 -1
  26. data/crates/itsi_server/src/server/serve_strategy/acceptor.rs +96 -0
  27. data/crates/itsi_server/src/server/serve_strategy/mod.rs +1 -0
  28. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +80 -136
  29. data/crates/itsi_server/src/server/thread_worker.rs +10 -3
  30. data/crates/itsi_server/src/services/itsi_http_service.rs +26 -21
  31. data/crates/itsi_server/src/services/mime_types.rs +2893 -1413
  32. data/crates/itsi_server/src/services/rate_limiter.rs +16 -34
  33. data/crates/itsi_server/src/services/static_file_server.rs +147 -121
  34. data/crates/itsi_tracing/Cargo.toml +1 -1
  35. data/docs/content/features/_index.md +1 -1
  36. data/docs/content/itsi_scheduler/_index.md +15 -8
  37. data/examples/rails_with_static_assets/Gemfile.lock +2 -1
  38. data/examples/rails_with_static_assets/Itsi.rb +4 -1
  39. data/gems/scheduler/Cargo.lock +25 -82
  40. data/gems/scheduler/itsi-scheduler.gemspec +1 -1
  41. data/gems/scheduler/lib/itsi/schedule_refinement.rb +2 -2
  42. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  43. data/gems/server/Cargo.lock +167 -218
  44. data/gems/server/itsi-server.gemspec +3 -3
  45. data/gems/server/lib/itsi/server/config/config_helpers.rb +1 -2
  46. data/gems/server/lib/itsi/server/config/middleware/etag.md +3 -7
  47. data/gems/server/lib/itsi/server/config/middleware/etag.rb +2 -4
  48. data/gems/server/lib/itsi/server/config/options/listen_backlog.rb +1 -1
  49. data/gems/server/lib/itsi/server/config/options/send_buffer_size.md +15 -0
  50. data/gems/server/lib/itsi/server/config/options/send_buffer_size.rb +19 -0
  51. data/gems/server/lib/itsi/server/config.rb +24 -25
  52. data/gems/server/lib/itsi/server/route_tester.rb +1 -1
  53. data/gems/server/lib/itsi/server/version.rb +1 -1
  54. data/gems/server/test/middleware/etag.rb +3 -3
  55. data/gems/server/test/options/ruby_thread_request_backlog_size.rb +3 -4
  56. data/lib/itsi/version.rb +1 -1
  57. data/tasks.txt +8 -7
  58. metadata +9 -6
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = "Itsi Server - A light-weight Rack Server implementation for Ruby."
12
12
  spec.description = "Itsi Server - A light-weight Rack Server implementation for Ruby"
13
13
  spec.homepage = "https://itsi.fyi"
14
- spec.license = "MIT"
14
+ spec.license = "LGPL-3.0"
15
15
  spec.required_ruby_version = ">= 2.7.0"
16
16
  spec.required_rubygems_version = ">= 3.1"
17
17
 
@@ -36,10 +36,10 @@ Gem::Specification.new do |spec|
36
36
  spec.require_paths = ["lib"]
37
37
  spec.extensions = ["ext/itsi_server/extconf.rb"]
38
38
 
39
+ spec.add_dependency "json", "~> 2"
40
+ spec.add_dependency 'prism', '~> 1.4'
39
41
  spec.add_dependency "rack", ">= 1.6"
40
- spec.add_dependency "json", '~> 2'
41
42
  spec.add_dependency "rb_sys", "~> 0.9.91"
42
- spec.add_dependency 'prism', '~> 1.4'
43
43
 
44
44
  spec.add_development_dependency "ruby-lsp"
45
45
  # For more information and examples about making a new gem, check out our
@@ -97,14 +97,13 @@ module Itsi
97
97
  if !self.class.ancestors.include?(Middleware) && !location.parent.nil?
98
98
  raise "#{opt_name} must be set at the top level"
99
99
  end
100
-
101
100
  @location = location
102
101
  @params = case schema
103
102
  when TypedStruct::Validation
104
103
  schema.validate!(params)
105
104
  when Array
106
105
  default, validation = schema
107
- params ? validation.validate!(params) : default
106
+ !params.nil? ? validation.validate!(params) : default
108
107
  when nil
109
108
  nil
110
109
  else
@@ -13,8 +13,7 @@ ETags are useful for optimizing client-side caching, conditional GETs, and reduc
13
13
  etag \
14
14
  type: "strong",
15
15
  algorithm: "sha256",
16
- min_body_size: 0,
17
- handle_if_none_match: true
16
+ min_body_size: 0
18
17
  ```
19
18
 
20
19
  ## ETag Applied to a sub-location
@@ -23,8 +22,7 @@ location "/assets" do
23
22
  etag \
24
23
  type: "weak",
25
24
  algorithm: "md5",
26
- min_body_size: 1024,
27
- handle_if_none_match: true
25
+ min_body_size: 1024
28
26
  end
29
27
  ```
30
28
 
@@ -40,12 +38,10 @@ end
40
38
 
41
39
  - **min_body_size**: Minimum response body size (in bytes) required before an ETag is generated. Use this to skip ETags for small or trivial responses.
42
40
 
43
- - **handle_if_none_match**: When `true`, incoming requests with a matching `If-None-Match` header will receive a `304 Not Modified` response (instead of a full body), if the ETag matches the computed value.
44
-
45
41
  ## How It Works
46
42
 
47
43
  ### Before the Response
48
- If `handle_if_none_match` is enabled and the request includes an `If-None-Match` header, the value is stored in the request context for comparison later.
44
+ If the request includes an `If-None-Match` header, the value is stored in the request context for comparison later.
49
45
 
50
46
  ### After the Response
51
47
 
@@ -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
@@ -4,7 +4,7 @@ module Itsi
4
4
  class ListenBacklog < Option
5
5
 
6
6
  insert_text <<~SNIPPET
7
- listen_backlog ${1|262_144,1_048_576|}
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,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
@@ -41,29 +41,28 @@ module Itsi
41
41
  DSL.evaluate(&builder_proc)
42
42
  elsif args[:static]
43
43
  DSL.evaluate do
44
- location "*" do
45
- rate_limit key: "address", store_config: "in_memory", requests: 2, seconds: 5
46
- etag type: "strong", algorithm: "md5", min_body_size: 1024 * 1024
47
- compress min_size: 1024 * 1024, level: "fastest", algorithms: %w[zstd gzip br deflate],
48
- mime_types: %w[all], compress_streams: true
49
- log_requests before: { level: "INFO", format: "[{request_id}] {method} {path_and_query} - {addr} " },
50
- after: { level: "INFO",
51
- format: "[{request_id}] └─ {status} in {response_time}" }
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
- }
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
68
  DSL.evaluate(config_file_path)
@@ -106,7 +105,6 @@ module Itsi
106
105
  Server.write_pid
107
106
  end
108
107
 
109
-
110
108
  srv_config = {
111
109
  workers: args.fetch(:workers) { itsifile_config.fetch(:workers, 1) },
112
110
  worker_memory_limit: args.fetch(:worker_memory_limit) { itsifile_config.fetch(:worker_memory_limit, nil) },
@@ -148,7 +146,8 @@ module Itsi
148
146
  reuse_port: itsifile_config.fetch(:reuse_port, true),
149
147
  listen_backlog: itsifile_config.fetch(:listen_backlog, 1024),
150
148
  nodelay: itsifile_config.fetch(:nodelay, true),
151
- recv_buffer_size: itsifile_config.fetch(:recv_buffer_size, 262_144)
149
+ recv_buffer_size: itsifile_config.fetch(:recv_buffer_size, 262_144),
150
+ send_buffer_size: itsifile_config.fetch(:send_buffer_size, 262_144)
152
151
  }.transform_keys(&:to_s)
153
152
 
154
153
  [srv_config, errors_to_error_lines(errors)]
@@ -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"]}, #{mw_args["handle_if_none_match"] ? "if_none_match" : ""})"
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Itsi
4
4
  class Server
5
- VERSION = "0.2.14"
5
+ VERSION = "0.2.16"
6
6
  end
7
7
  end
@@ -4,7 +4,7 @@ class TestETag < Minitest::Test
4
4
  def test_strong_etag_added
5
5
  server(
6
6
  itsi_rb: lambda do
7
- etag type: "strong", algorithm: "sha256", min_body_size: 0, handle_if_none_match: false
7
+ etag type: "strong", algorithm: "sha256", min_body_size: 0
8
8
  get("/foo") { |r| r.ok "etag-body" }
9
9
  end
10
10
  ) do
@@ -17,7 +17,7 @@ class TestETag < Minitest::Test
17
17
  def test_weak_etag_added_with_md5
18
18
  server(
19
19
  itsi_rb: lambda do
20
- etag type: "weak", algorithm: "md5", min_body_size: 0, handle_if_none_match: false
20
+ etag type: "weak", algorithm: "md5", min_body_size: 0
21
21
  get("/foo") { |r| r.ok "etag-weak-md5" }
22
22
  end
23
23
  ) do
@@ -42,7 +42,7 @@ class TestETag < Minitest::Test
42
42
  body = "etag-content"
43
43
  server(
44
44
  itsi_rb: lambda do
45
- etag type: "strong", min_body_size: 0, handle_if_none_match: true
45
+ etag type: "strong", min_body_size: 0
46
46
  get("/foo") { |r| r.ok body }
47
47
  end
48
48
  ) do
@@ -10,11 +10,10 @@ class TestRubyThreadRequestBacklogSize < Minitest::Test
10
10
  ruby_thread_request_backlog_size 1
11
11
  get("/foo"){|r| sleep 0.1; r.ok "ok" }
12
12
  end) do
13
- responses = 3.times.map{ Thread.new{ get_resp("/foo") } }.map(&:value)
13
+ responses = 10.times.map{ Thread.new{ get_resp("/foo") } }.map(&:value)
14
14
 
15
- assert_equal "ok", responses.first.body
16
- assert_equal "200", responses.first.code
17
- assert_equal "503", responses.last.code
15
+ assert responses.map(&:code).include?("200")
16
+ assert responses.map(&:code).include?("503")
18
17
  end
19
18
  end
20
19
 
data/lib/itsi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Itsi
2
- VERSION = '0.2.14'
2
+ VERSION = '0.2.16'
3
3
  end
data/tasks.txt CHANGED
@@ -1,16 +1,17 @@
1
- - Add tests for script name and request backlog size, Add tests for scheduler.
2
- - Respond on Reddit
3
- - Min rust version
1
+ - Test CRB without main
2
+ - Try and compile new Itsi with jemalloc on Linux
3
+ - ACME HTTP-01 challenge
4
+ - Add way to opt non Itsi.rb files into LSP
5
+ - Fat binary gems
6
+ - First class Rackless Websockets
4
7
 
5
8
  Tasks:
6
- - Add way to opt non Itsi.rb files into LSP
7
- - Better parallelization a lá Iodine
8
9
  - Static ruby build
9
10
  - OTel
11
+ - Even faster Hash creation for Rack
10
12
  - Image resizer
11
- - First class Rackless Websockets
12
13
  - Print out warning if we can detect that a location block will never be hit.
13
- - Built in Obs Dashboard + Stats
14
+ - Built in obs Dashboard + Stats
14
15
  - WASM pluggable middleware
15
16
  - Support UDP Proxy
16
17
  - Support Unix Socket Proxy
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itsi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.14
4
+ version: 0.2.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wouter Coppieters
@@ -15,28 +15,28 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.2.14
18
+ version: 0.2.16
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 0.2.14
25
+ version: 0.2.16
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: itsi-server
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.2.14
32
+ version: 0.2.16
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.2.14
39
+ version: 0.2.16
40
40
  description: Wrapper Gem for both the Itsi server and the Itsi Fiber scheduler
41
41
  email:
42
42
  - wc@pico.net.nz
@@ -171,6 +171,7 @@ files:
171
171
  - crates/itsi_server/src/server/process_worker.rs
172
172
  - crates/itsi_server/src/server/redirect_type.rs
173
173
  - crates/itsi_server/src/server/request_job.rs
174
+ - crates/itsi_server/src/server/serve_strategy/acceptor.rs
174
175
  - crates/itsi_server/src/server/serve_strategy/cluster_mode.rs
175
176
  - crates/itsi_server/src/server/serve_strategy/mod.rs
176
177
  - crates/itsi_server/src/server/serve_strategy/single_mode.rs
@@ -949,6 +950,8 @@ files:
949
950
  - gems/server/lib/itsi/server/config/options/ruby_thread_request_backlog_size.rb
950
951
  - gems/server/lib/itsi/server/config/options/scheduler_threads.md
951
952
  - gems/server/lib/itsi/server/config/options/scheduler_threads.rb
953
+ - gems/server/lib/itsi/server/config/options/send_buffer_size.md
954
+ - gems/server/lib/itsi/server/config/options/send_buffer_size.rb
952
955
  - gems/server/lib/itsi/server/config/options/shutdown_timeout.md
953
956
  - gems/server/lib/itsi/server/config/options/shutdown_timeout.rb
954
957
  - gems/server/lib/itsi/server/config/options/stream_body.md
@@ -1027,7 +1030,7 @@ files:
1027
1030
  - tasks.txt
1028
1031
  homepage: https://itsi.fyi
1029
1032
  licenses:
1030
- - MIT
1033
+ - LGPL-3.0
1031
1034
  metadata:
1032
1035
  homepage_uri: https://itsi.fyi
1033
1036
  source_code_uri: https://github.com/wouterken/itsi