itsi 0.1.11 → 0.1.12
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 +1535 -45
- data/{sandbox/itsi_itsi_file/Itsi.rb → Itsi.rb} +19 -13
- data/Rakefile +8 -7
- data/crates/itsi_error/src/lib.rs +9 -0
- data/crates/itsi_rb_helpers/Cargo.toml +1 -0
- data/crates/itsi_rb_helpers/src/heap_value.rs +18 -0
- data/crates/itsi_rb_helpers/src/lib.rs +34 -7
- data/crates/itsi_server/Cargo.toml +69 -30
- data/crates/itsi_server/src/lib.rs +79 -147
- data/crates/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
- data/crates/itsi_server/src/{body_proxy/itsi_body_proxy.rs → ruby_types/itsi_body_proxy/mod.rs} +22 -3
- data/crates/itsi_server/src/ruby_types/itsi_grpc_request.rs +147 -0
- data/crates/itsi_server/src/ruby_types/itsi_grpc_response.rs +19 -0
- data/crates/itsi_server/src/ruby_types/itsi_grpc_stream/mod.rs +216 -0
- data/{gems/server/ext/itsi_server/src/request/itsi_request.rs → crates/itsi_server/src/ruby_types/itsi_http_request.rs} +101 -117
- data/crates/itsi_server/src/{response/itsi_response.rs → ruby_types/itsi_http_response.rs} +72 -41
- data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
- data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +355 -0
- data/crates/itsi_server/src/ruby_types/itsi_server.rs +82 -0
- data/crates/itsi_server/src/ruby_types/mod.rs +55 -0
- data/crates/itsi_server/src/server/bind.rs +13 -5
- data/crates/itsi_server/src/server/byte_frame.rs +32 -0
- data/crates/itsi_server/src/server/cache_store.rs +74 -0
- data/crates/itsi_server/src/server/itsi_service.rs +172 -0
- data/crates/itsi_server/src/server/lifecycle_event.rs +3 -0
- data/crates/itsi_server/src/server/listener.rs +102 -2
- data/crates/itsi_server/src/server/middleware_stack/middleware.rs +153 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +47 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +58 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +82 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +321 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +139 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +300 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +287 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +48 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +127 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +191 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +72 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +85 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +195 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +82 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +216 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +124 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +43 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +34 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +93 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +162 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +158 -0
- data/crates/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
- data/crates/itsi_server/src/server/middleware_stack/mod.rs +315 -0
- data/crates/itsi_server/src/server/mod.rs +8 -1
- data/crates/itsi_server/src/server/process_worker.rs +38 -12
- data/crates/itsi_server/src/server/rate_limiter.rs +565 -0
- data/crates/itsi_server/src/server/request_job.rs +11 -0
- data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +119 -42
- data/crates/itsi_server/src/server/serve_strategy/mod.rs +9 -6
- data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +256 -111
- data/crates/itsi_server/src/server/signal.rs +19 -0
- data/crates/itsi_server/src/server/static_file_server.rs +984 -0
- data/crates/itsi_server/src/server/thread_worker.rs +139 -94
- data/crates/itsi_server/src/server/types.rs +43 -0
- data/crates/itsi_server/test.md +14 -0
- data/crates/itsi_tracing/Cargo.toml +1 -0
- data/crates/itsi_tracing/src/lib.rs +216 -45
- data/docs/.gitignore +7 -0
- data/docs/.gitpod.yml +15 -0
- data/docs/Itsi.rb +17 -0
- data/docs/content/_index.md +17 -0
- data/docs/content/about.md +6 -0
- data/docs/content/docs/_index.md +18 -0
- data/docs/content/docs/first-page.md +9 -0
- data/docs/content/docs/folder/_index.md +10 -0
- data/docs/content/docs/folder/leaf.md +7 -0
- data/docs/go.mod +5 -0
- data/docs/go.sum +2 -0
- data/docs/hugo.yaml +77 -0
- data/examples/static_assets_example.rb +83 -0
- data/gems/_index.md +18 -0
- data/gems/scheduler/CODE_OF_CONDUCT.md +7 -0
- data/gems/scheduler/Cargo.lock +75 -14
- data/gems/scheduler/README.md +5 -0
- data/gems/scheduler/_index.md +7 -0
- data/gems/scheduler/itsi-scheduler.gemspec +4 -1
- data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
- data/gems/scheduler/lib/itsi/scheduler.rb +2 -2
- data/gems/scheduler/test/test_file_io.rb +0 -1
- data/gems/scheduler/test/test_itsi_scheduler.rb +1 -1
- data/gems/server/CHANGELOG.md +5 -0
- data/gems/server/CODE_OF_CONDUCT.md +7 -0
- data/gems/server/Cargo.lock +1536 -45
- data/gems/server/README.md +4 -0
- data/gems/server/_index.md +6 -0
- data/gems/server/exe/itsi +33 -74
- data/gems/server/itsi-server.gemspec +3 -2
- data/gems/server/lib/itsi/{request.rb → http_request.rb} +29 -5
- data/gems/server/lib/itsi/http_response.rb +39 -0
- data/gems/server/lib/itsi/server/Itsi.rb +11 -19
- data/gems/server/lib/itsi/server/config/dsl.rb +506 -0
- data/gems/server/lib/itsi/server/config.rb +103 -8
- data/gems/server/lib/itsi/server/default_app/default_app.rb +38 -0
- data/gems/server/lib/itsi/server/grpc_interface.rb +213 -0
- data/gems/server/lib/itsi/server/rack/handler/itsi.rb +8 -17
- data/gems/server/lib/itsi/server/rack_interface.rb +23 -4
- data/gems/server/lib/itsi/server/scheduler_interface.rb +1 -1
- data/gems/server/lib/itsi/server/scheduler_mode.rb +4 -0
- data/gems/server/lib/itsi/server/signal_trap.rb +7 -1
- data/gems/server/lib/itsi/server/version.rb +1 -1
- data/gems/server/lib/itsi/server.rb +74 -63
- data/gems/server/lib/itsi/standard_headers.rb +86 -0
- data/gems/server/test/helpers/test_helper.rb +12 -12
- data/gems/server/test/test_itsi_server.rb +2 -2
- data/lib/itsi/version.rb +1 -1
- data/sandbox/itsi_file/Gemfile +11 -0
- data/sandbox/itsi_file/Gemfile.lock +69 -0
- data/sandbox/itsi_file/Itsi.rb +276 -0
- data/sandbox/itsi_file/error.html +2 -0
- data/sandbox/itsi_file/organisations_controller.rb +20 -0
- data/sandbox/itsi_file/public/assets/image.png +0 -0
- data/sandbox/itsi_file/public/assets/index.html +1 -0
- data/sandbox/itsi_sandbox_hanami/Gemfile.lock +2 -2
- data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
- data/sandbox/itsi_sandbox_rack/config.ru +2 -15
- data/sandbox/itsi_sandbox_rails/.dockerignore +2 -5
- data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +1 -1
- data/sandbox/itsi_sandbox_rails/.gitignore +2 -1
- data/sandbox/itsi_sandbox_rails/Dockerfile +6 -9
- data/sandbox/itsi_sandbox_rails/Gemfile +16 -22
- data/sandbox/itsi_sandbox_rails/Gemfile.lock +100 -225
- data/sandbox/itsi_sandbox_rails/app/assets/config/manifest.js +4 -0
- data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +11 -6
- data/sandbox/itsi_sandbox_rails/app/channels/application_cable/channel.rb +4 -0
- data/sandbox/itsi_sandbox_rails/app/channels/application_cable/connection.rb +4 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +7 -8
- data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +0 -3
- data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +2 -7
- data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +3 -4
- data/sandbox/itsi_sandbox_rails/bin/setup +8 -5
- data/sandbox/itsi_sandbox_rails/config/application.rb +1 -35
- data/sandbox/itsi_sandbox_rails/config/cable.yml +3 -10
- data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -1
- data/sandbox/itsi_sandbox_rails/config/database.yml +9 -19
- data/sandbox/itsi_sandbox_rails/config/environment.rb +1 -1
- data/sandbox/itsi_sandbox_rails/config/environments/development.rb +21 -12
- data/sandbox/itsi_sandbox_rails/config/environments/production.rb +49 -34
- data/sandbox/itsi_sandbox_rails/config/environments/test.rb +19 -5
- data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +5 -0
- data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +1 -1
- data/sandbox/itsi_sandbox_rails/config/initializers/permissions_policy.rb +13 -0
- data/sandbox/itsi_sandbox_rails/config/puma.rb +2 -9
- data/sandbox/itsi_sandbox_rails/config.ru +0 -1
- data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +1 -1
- data/sandbox/itsi_sandbox_rails/db/schema.rb +2 -2
- data/sandbox/itsi_sandbox_rails/lib/assets/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/public/404.html +66 -113
- data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +65 -113
- data/sandbox/itsi_sandbox_rails/public/422.html +66 -113
- data/sandbox/itsi_sandbox_rails/public/500.html +65 -113
- data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
- data/sandbox/itsi_sandbox_rails/public/icon.svg +2 -2
- data/sandbox/itsi_sandbox_rails/test/channels/application_cable/connection_test.rb +13 -0
- data/sandbox/itsi_sandbox_roda/Gemfile.lock +3 -10
- data/tasks.txt +72 -35
- metadata +89 -139
- data/crates/itsi_server/src/body_proxy/mod.rs +0 -2
- data/crates/itsi_server/src/request/itsi_request.rs +0 -298
- data/crates/itsi_server/src/request/mod.rs +0 -1
- data/crates/itsi_server/src/response/mod.rs +0 -1
- data/crates/itsi_server/src/server/itsi_server.rs +0 -288
- data/gems/scheduler/ext/itsi_error/Cargo.lock +0 -368
- data/gems/scheduler/ext/itsi_error/Cargo.toml +0 -11
- data/gems/scheduler/ext/itsi_error/src/from.rs +0 -68
- data/gems/scheduler/ext/itsi_error/src/lib.rs +0 -24
- data/gems/scheduler/ext/itsi_instrument_entry/Cargo.toml +0 -15
- data/gems/scheduler/ext/itsi_instrument_entry/src/lib.rs +0 -31
- data/gems/scheduler/ext/itsi_rb_helpers/Cargo.lock +0 -355
- data/gems/scheduler/ext/itsi_rb_helpers/Cargo.toml +0 -10
- data/gems/scheduler/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
- data/gems/scheduler/ext/itsi_rb_helpers/src/lib.rs +0 -201
- data/gems/scheduler/ext/itsi_scheduler/Cargo.toml +0 -24
- data/gems/scheduler/ext/itsi_scheduler/extconf.rb +0 -6
- data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
- data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
- data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
- data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
- data/gems/scheduler/ext/itsi_scheduler/src/lib.rs +0 -38
- data/gems/scheduler/ext/itsi_server/Cargo.lock +0 -2956
- data/gems/scheduler/ext/itsi_server/Cargo.toml +0 -50
- data/gems/scheduler/ext/itsi_server/extconf.rb +0 -6
- data/gems/scheduler/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
- data/gems/scheduler/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
- data/gems/scheduler/ext/itsi_server/src/body_proxy/mod.rs +0 -2
- data/gems/scheduler/ext/itsi_server/src/env.rs +0 -43
- data/gems/scheduler/ext/itsi_server/src/lib.rs +0 -180
- data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +0 -298
- data/gems/scheduler/ext/itsi_server/src/request/mod.rs +0 -1
- data/gems/scheduler/ext/itsi_server/src/response/itsi_response.rs +0 -357
- data/gems/scheduler/ext/itsi_server/src/response/mod.rs +0 -1
- data/gems/scheduler/ext/itsi_server/src/server/bind.rs +0 -174
- data/gems/scheduler/ext/itsi_server/src/server/bind_protocol.rs +0 -37
- data/gems/scheduler/ext/itsi_server/src/server/io_stream.rs +0 -104
- data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +0 -288
- data/gems/scheduler/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
- data/gems/scheduler/ext/itsi_server/src/server/listener.rs +0 -318
- data/gems/scheduler/ext/itsi_server/src/server/mod.rs +0 -11
- data/gems/scheduler/ext/itsi_server/src/server/process_worker.rs +0 -203
- data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -260
- data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
- data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -276
- data/gems/scheduler/ext/itsi_server/src/server/signal.rs +0 -74
- data/gems/scheduler/ext/itsi_server/src/server/thread_worker.rs +0 -399
- data/gems/scheduler/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
- data/gems/scheduler/ext/itsi_server/src/server/tls.rs +0 -265
- data/gems/scheduler/ext/itsi_tracing/Cargo.lock +0 -274
- data/gems/scheduler/ext/itsi_tracing/Cargo.toml +0 -16
- data/gems/scheduler/ext/itsi_tracing/src/lib.rs +0 -58
- data/gems/server/ext/itsi_error/Cargo.lock +0 -368
- data/gems/server/ext/itsi_error/Cargo.toml +0 -11
- data/gems/server/ext/itsi_error/src/from.rs +0 -68
- data/gems/server/ext/itsi_error/src/lib.rs +0 -24
- data/gems/server/ext/itsi_instrument_entry/Cargo.toml +0 -15
- data/gems/server/ext/itsi_instrument_entry/src/lib.rs +0 -31
- data/gems/server/ext/itsi_rb_helpers/Cargo.lock +0 -355
- data/gems/server/ext/itsi_rb_helpers/Cargo.toml +0 -10
- data/gems/server/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
- data/gems/server/ext/itsi_rb_helpers/src/lib.rs +0 -201
- data/gems/server/ext/itsi_scheduler/Cargo.toml +0 -24
- data/gems/server/ext/itsi_scheduler/extconf.rb +0 -6
- data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
- data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
- data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
- data/gems/server/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
- data/gems/server/ext/itsi_scheduler/src/lib.rs +0 -38
- data/gems/server/ext/itsi_server/Cargo.lock +0 -2956
- data/gems/server/ext/itsi_server/Cargo.toml +0 -50
- data/gems/server/ext/itsi_server/extconf.rb +0 -6
- data/gems/server/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
- data/gems/server/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
- data/gems/server/ext/itsi_server/src/body_proxy/mod.rs +0 -2
- data/gems/server/ext/itsi_server/src/env.rs +0 -43
- data/gems/server/ext/itsi_server/src/lib.rs +0 -180
- data/gems/server/ext/itsi_server/src/request/mod.rs +0 -1
- data/gems/server/ext/itsi_server/src/response/itsi_response.rs +0 -357
- data/gems/server/ext/itsi_server/src/response/mod.rs +0 -1
- data/gems/server/ext/itsi_server/src/server/bind.rs +0 -174
- data/gems/server/ext/itsi_server/src/server/bind_protocol.rs +0 -37
- data/gems/server/ext/itsi_server/src/server/io_stream.rs +0 -104
- data/gems/server/ext/itsi_server/src/server/itsi_server.rs +0 -288
- data/gems/server/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
- data/gems/server/ext/itsi_server/src/server/listener.rs +0 -318
- data/gems/server/ext/itsi_server/src/server/mod.rs +0 -11
- data/gems/server/ext/itsi_server/src/server/process_worker.rs +0 -203
- data/gems/server/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -260
- data/gems/server/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
- data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -276
- data/gems/server/ext/itsi_server/src/server/signal.rs +0 -74
- data/gems/server/ext/itsi_server/src/server/thread_worker.rs +0 -399
- data/gems/server/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
- data/gems/server/ext/itsi_server/src/server/tls.rs +0 -265
- data/gems/server/ext/itsi_tracing/Cargo.lock +0 -274
- data/gems/server/ext/itsi_tracing/Cargo.toml +0 -16
- data/gems/server/ext/itsi_tracing/src/lib.rs +0 -58
- data/gems/server/lib/itsi/server/options_dsl.rb +0 -401
- data/gems/server/lib/itsi/stream_io.rb +0 -38
- data/location_dsl.rb +0 -381
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +0 -3
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +0 -3
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +0 -14
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +0 -3
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +0 -3
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +0 -51
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +0 -47
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +0 -109
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +0 -3
- data/sandbox/itsi_sandbox_rails/.kamal/secrets +0 -17
- data/sandbox/itsi_sandbox_rails/bin/dev +0 -2
- data/sandbox/itsi_sandbox_rails/bin/jobs +0 -6
- data/sandbox/itsi_sandbox_rails/bin/kamal +0 -27
- data/sandbox/itsi_sandbox_rails/bin/thrust +0 -5
- data/sandbox/itsi_sandbox_rails/config/cache.yml +0 -16
- data/sandbox/itsi_sandbox_rails/config/deploy.yml +0 -116
- data/sandbox/itsi_sandbox_rails/config/queue.yml +0 -18
- data/sandbox/itsi_sandbox_rails/config/recurring.yml +0 -10
- data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +0 -11
- data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +0 -14
- data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +0 -129
- data/sandbox/itsi_sandbox_rails/public/400.html +0 -114
- data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +0 -9
- data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +0 -7
- /data/{sandbox/itsi_sandbox_rails/script/.keep → crates/_index.md} +0 -0
- /data/gems/server/lib/itsi/{index.html → server/default_app/index.html} +0 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
use magnus::{value::Lazy, Module, RClass, RModule};
|
2
|
+
|
3
|
+
pub mod itsi_body_proxy;
|
4
|
+
pub mod itsi_grpc_request;
|
5
|
+
pub mod itsi_grpc_response;
|
6
|
+
pub mod itsi_grpc_stream;
|
7
|
+
pub mod itsi_http_request;
|
8
|
+
pub mod itsi_http_response;
|
9
|
+
pub mod itsi_server;
|
10
|
+
|
11
|
+
pub static ITSI_MODULE: Lazy<RModule> = Lazy::new(|ruby| ruby.define_module("Itsi").unwrap());
|
12
|
+
pub static ITSI_SERVER: Lazy<RClass> = Lazy::new(|ruby| {
|
13
|
+
ruby.get_inner(&ITSI_MODULE)
|
14
|
+
.define_class("Server", ruby.class_object())
|
15
|
+
.unwrap()
|
16
|
+
});
|
17
|
+
|
18
|
+
pub static ITSI_SERVER_CONFIG: Lazy<RModule> =
|
19
|
+
Lazy::new(|ruby| ruby.get_inner(&ITSI_SERVER).const_get("Config").unwrap());
|
20
|
+
|
21
|
+
pub static ITSI_REQUEST: Lazy<RClass> = Lazy::new(|ruby| {
|
22
|
+
ruby.get_inner(&ITSI_MODULE)
|
23
|
+
.define_class("HttpRequest", ruby.class_object())
|
24
|
+
.unwrap()
|
25
|
+
});
|
26
|
+
|
27
|
+
pub static ITSI_RESPONSE: Lazy<RClass> = Lazy::new(|ruby| {
|
28
|
+
ruby.get_inner(&ITSI_MODULE)
|
29
|
+
.define_class("HttpResponse", ruby.class_object())
|
30
|
+
.unwrap()
|
31
|
+
});
|
32
|
+
|
33
|
+
pub static ITSI_BODY_PROXY: Lazy<RClass> = Lazy::new(|ruby| {
|
34
|
+
ruby.get_inner(&ITSI_MODULE)
|
35
|
+
.define_class("BodyProxy", ruby.class_object())
|
36
|
+
.unwrap()
|
37
|
+
});
|
38
|
+
|
39
|
+
pub static ITSI_GRPC_REQUEST: Lazy<RClass> = Lazy::new(|ruby| {
|
40
|
+
ruby.get_inner(&ITSI_MODULE)
|
41
|
+
.define_class("GrpcRequest", ruby.class_object())
|
42
|
+
.unwrap()
|
43
|
+
});
|
44
|
+
|
45
|
+
pub static ITSI_GRPC_STREAM: Lazy<RClass> = Lazy::new(|ruby| {
|
46
|
+
ruby.get_inner(&ITSI_MODULE)
|
47
|
+
.define_class("GrpcStream", ruby.class_object())
|
48
|
+
.unwrap()
|
49
|
+
});
|
50
|
+
|
51
|
+
pub static ITSI_GRPC_RESPONSE: Lazy<RClass> = Lazy::new(|ruby| {
|
52
|
+
ruby.get_inner(&ITSI_MODULE)
|
53
|
+
.define_class("GrpcResponse", ruby.class_object())
|
54
|
+
.unwrap()
|
55
|
+
});
|
@@ -31,13 +31,21 @@ pub struct Bind {
|
|
31
31
|
pub tls_config: Option<ItsiTlsAcceptor>,
|
32
32
|
}
|
33
33
|
|
34
|
+
impl Bind {
|
35
|
+
pub fn listener_address_string(&self) -> String {
|
36
|
+
match &self.address {
|
37
|
+
BindAddress::Ip(ip) => format!("tcp://{}:{}", ip.to_canonical(), self.port.unwrap()),
|
38
|
+
BindAddress::UnixSocket(path) => {
|
39
|
+
format!("unix://{}", path.as_path().to_str().unwrap())
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
34
45
|
impl std::fmt::Debug for Bind {
|
35
46
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
36
47
|
match &self.address {
|
37
48
|
BindAddress::Ip(ip) => match self.protocol {
|
38
|
-
BindProtocol::Unix | BindProtocol::Unixs => {
|
39
|
-
write!(f, "{}://{}", self.protocol, ip)
|
40
|
-
}
|
41
49
|
BindProtocol::Https if self.port == Some(443) => {
|
42
50
|
write!(f, "{}://{}", self.protocol, ip)
|
43
51
|
}
|
@@ -158,8 +166,8 @@ fn resolve_hostname(hostname: &str) -> Option<IpAddr> {
|
|
158
166
|
.to_socket_addrs()
|
159
167
|
.ok()?
|
160
168
|
.find_map(|addr| {
|
161
|
-
if addr.
|
162
|
-
Some(addr.ip()) // Prefer
|
169
|
+
if addr.is_ipv4() {
|
170
|
+
Some(addr.ip()) // Prefer IPv4
|
163
171
|
} else {
|
164
172
|
None
|
165
173
|
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
use std::ops::Deref;
|
2
|
+
|
3
|
+
use bytes::Bytes;
|
4
|
+
|
5
|
+
#[derive(Debug)]
|
6
|
+
pub enum ByteFrame {
|
7
|
+
Data(Bytes),
|
8
|
+
End(Bytes),
|
9
|
+
Empty,
|
10
|
+
}
|
11
|
+
|
12
|
+
impl Deref for ByteFrame {
|
13
|
+
type Target = Bytes;
|
14
|
+
|
15
|
+
fn deref(&self) -> &Self::Target {
|
16
|
+
match self {
|
17
|
+
ByteFrame::Data(data) => data,
|
18
|
+
ByteFrame::End(data) => data,
|
19
|
+
ByteFrame::Empty => unreachable!(),
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
impl From<ByteFrame> for Bytes {
|
25
|
+
fn from(frame: ByteFrame) -> Self {
|
26
|
+
match frame {
|
27
|
+
ByteFrame::Data(data) => data,
|
28
|
+
ByteFrame::End(data) => data,
|
29
|
+
ByteFrame::Empty => unreachable!(),
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,74 @@
|
|
1
|
+
use async_trait::async_trait;
|
2
|
+
use redis::aio::ConnectionManager;
|
3
|
+
use redis::{Client, RedisError, Script};
|
4
|
+
use std::sync::Arc;
|
5
|
+
use std::time::Duration;
|
6
|
+
|
7
|
+
#[derive(Debug)]
|
8
|
+
pub enum CacheError {
|
9
|
+
RedisError(RedisError),
|
10
|
+
// Other error variants as needed.
|
11
|
+
}
|
12
|
+
/// A general-purpose cache trait with an atomic “increment with timeout” operation.
|
13
|
+
#[async_trait]
|
14
|
+
pub trait CacheStore: Send + Sync + std::fmt::Debug {
|
15
|
+
/// Increments the counter associated with `key` and sets (or extends) its expiration.
|
16
|
+
/// Returns the new counter value.
|
17
|
+
async fn increment(&self, key: &str, timeout: Duration) -> Result<u64, CacheError>;
|
18
|
+
}
|
19
|
+
|
20
|
+
/// A Redis-backed cache store using an async connection manager.
|
21
|
+
/// This uses a TLS-enabled connection when the URL is prefixed with "rediss://".
|
22
|
+
#[derive(Clone)]
|
23
|
+
pub struct RedisCacheStore {
|
24
|
+
connection: Arc<ConnectionManager>,
|
25
|
+
}
|
26
|
+
|
27
|
+
impl std::fmt::Debug for RedisCacheStore {
|
28
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
29
|
+
f.debug_struct("RedisCacheStore").finish()
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
impl RedisCacheStore {
|
34
|
+
/// Constructs a new RedisCacheStore.
|
35
|
+
///
|
36
|
+
/// Use a connection URL like "rediss://host:port" to enable TLS (with rustls under the hood).
|
37
|
+
/// This constructor is async because it sets up the connection manager.
|
38
|
+
pub async fn new(connection_url: &str) -> Result<Self, CacheError> {
|
39
|
+
let client = Client::open(connection_url).map_err(CacheError::RedisError)?;
|
40
|
+
let connection_manager = ConnectionManager::new(client)
|
41
|
+
.await
|
42
|
+
.map_err(CacheError::RedisError)?;
|
43
|
+
Ok(Self {
|
44
|
+
connection: Arc::new(connection_manager),
|
45
|
+
})
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
#[async_trait]
|
50
|
+
impl CacheStore for RedisCacheStore {
|
51
|
+
async fn increment(&self, key: &str, timeout: Duration) -> Result<u64, CacheError> {
|
52
|
+
let timeout_secs = timeout.as_secs();
|
53
|
+
// Lua script to:
|
54
|
+
// 1. INCR the key.
|
55
|
+
// 2. If the key doesn't have a TTL, set it.
|
56
|
+
let script = r#"
|
57
|
+
local current = redis.call('INCR', KEYS[1])
|
58
|
+
if redis.call('TTL', KEYS[1]) < 0 then
|
59
|
+
redis.call('EXPIRE', KEYS[1], ARGV[1])
|
60
|
+
end
|
61
|
+
return current
|
62
|
+
"#;
|
63
|
+
let script = Script::new(script);
|
64
|
+
// The ConnectionManager is cloneable and can be used concurrently.
|
65
|
+
let mut connection = (*self.connection).clone();
|
66
|
+
let value: i64 = script
|
67
|
+
.key(key)
|
68
|
+
.arg(timeout_secs)
|
69
|
+
.invoke_async(&mut connection)
|
70
|
+
.await
|
71
|
+
.map_err(CacheError::RedisError)?;
|
72
|
+
Ok(value as u64)
|
73
|
+
}
|
74
|
+
}
|
@@ -0,0 +1,172 @@
|
|
1
|
+
use super::listener::ListenerInfo;
|
2
|
+
use super::middleware_stack::CompressionAlgorithm;
|
3
|
+
use super::middleware_stack::MiddlewareLayer;
|
4
|
+
use super::request_job::RequestJob;
|
5
|
+
use super::serve_strategy::single_mode::RunningPhase;
|
6
|
+
use super::types::HttpRequest;
|
7
|
+
use super::types::HttpResponse;
|
8
|
+
use crate::ruby_types::itsi_server::itsi_server_config::ServerParams;
|
9
|
+
use chrono;
|
10
|
+
use chrono::Local;
|
11
|
+
use either::Either;
|
12
|
+
use hyper::service::Service;
|
13
|
+
use itsi_error::ItsiError;
|
14
|
+
use regex::Regex;
|
15
|
+
use std::sync::OnceLock;
|
16
|
+
use std::{future::Future, ops::Deref, pin::Pin, sync::Arc};
|
17
|
+
use tokio::sync::watch::{self};
|
18
|
+
|
19
|
+
#[derive(Clone)]
|
20
|
+
pub struct ItsiService {
|
21
|
+
pub inner: Arc<IstiServiceInner>,
|
22
|
+
}
|
23
|
+
|
24
|
+
impl Deref for ItsiService {
|
25
|
+
type Target = Arc<IstiServiceInner>;
|
26
|
+
|
27
|
+
fn deref(&self) -> &Self::Target {
|
28
|
+
&self.inner
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
pub struct IstiServiceInner {
|
33
|
+
pub sender: async_channel::Sender<RequestJob>,
|
34
|
+
pub server_params: Arc<ServerParams>,
|
35
|
+
pub listener: Arc<ListenerInfo>,
|
36
|
+
pub addr: String,
|
37
|
+
pub shutdown_channel: watch::Receiver<RunningPhase>,
|
38
|
+
}
|
39
|
+
|
40
|
+
#[derive(Clone)]
|
41
|
+
pub struct RequestContext {
|
42
|
+
inner: Arc<RequestContextInner>,
|
43
|
+
}
|
44
|
+
|
45
|
+
impl Deref for RequestContext {
|
46
|
+
type Target = Arc<RequestContextInner>;
|
47
|
+
|
48
|
+
fn deref(&self) -> &Self::Target {
|
49
|
+
&self.inner
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
impl Deref for RequestContextInner {
|
54
|
+
type Target = ItsiService;
|
55
|
+
|
56
|
+
fn deref(&self) -> &Self::Target {
|
57
|
+
&self.service
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
pub struct RequestContextInner {
|
62
|
+
pub request_id: i128,
|
63
|
+
pub service: ItsiService,
|
64
|
+
pub matching_pattern: Option<Arc<Regex>>,
|
65
|
+
pub compression_method: OnceLock<CompressionAlgorithm>,
|
66
|
+
pub origin: OnceLock<Option<String>>,
|
67
|
+
pub start_time: chrono::DateTime<chrono::Utc>,
|
68
|
+
pub request: Option<Arc<HttpRequest>>,
|
69
|
+
pub request_start_time: OnceLock<chrono::DateTime<Local>>,
|
70
|
+
pub if_none_match: OnceLock<Option<String>>,
|
71
|
+
pub etag_value: OnceLock<Option<String>>,
|
72
|
+
}
|
73
|
+
|
74
|
+
impl RequestContext {
|
75
|
+
fn new(service: ItsiService, matching_pattern: Option<Arc<Regex>>) -> Self {
|
76
|
+
RequestContext {
|
77
|
+
inner: Arc::new(RequestContextInner {
|
78
|
+
request_id: rand::random::<i128>(),
|
79
|
+
service,
|
80
|
+
matching_pattern,
|
81
|
+
compression_method: OnceLock::new(),
|
82
|
+
origin: OnceLock::new(),
|
83
|
+
start_time: chrono::Utc::now(),
|
84
|
+
request: None,
|
85
|
+
request_start_time: OnceLock::new(),
|
86
|
+
if_none_match: OnceLock::new(),
|
87
|
+
etag_value: OnceLock::new(),
|
88
|
+
}),
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
pub fn set_compression_method(&self, method: CompressionAlgorithm) {
|
93
|
+
self.inner.compression_method.set(method).unwrap();
|
94
|
+
}
|
95
|
+
|
96
|
+
pub fn set_origin(&self, origin: Option<String>) {
|
97
|
+
self.inner.origin.set(origin).unwrap();
|
98
|
+
}
|
99
|
+
|
100
|
+
pub fn set_if_none_match(&self, value: Option<String>) {
|
101
|
+
self.inner.if_none_match.set(value).unwrap();
|
102
|
+
}
|
103
|
+
|
104
|
+
pub fn get_if_none_match(&self) -> Option<String> {
|
105
|
+
self.inner.if_none_match.get().cloned().flatten()
|
106
|
+
}
|
107
|
+
|
108
|
+
pub fn request_id(&self) -> String {
|
109
|
+
self.inner.request_id.to_string()
|
110
|
+
}
|
111
|
+
|
112
|
+
pub fn track_start_time(&self) {
|
113
|
+
self.inner
|
114
|
+
.request_start_time
|
115
|
+
.get_or_init(chrono::Local::now);
|
116
|
+
}
|
117
|
+
|
118
|
+
pub fn start_time(&self) -> Option<chrono::DateTime<Local>> {
|
119
|
+
self.inner.request_start_time.get().cloned()
|
120
|
+
}
|
121
|
+
|
122
|
+
pub fn get_response_time(&self) -> Option<chrono::TimeDelta> {
|
123
|
+
self.inner
|
124
|
+
.request_start_time
|
125
|
+
.get()
|
126
|
+
.map(|instant| Local::now() - instant)
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
impl Service<HttpRequest> for ItsiService {
|
131
|
+
type Response = HttpResponse;
|
132
|
+
type Error = ItsiError;
|
133
|
+
type Future = Pin<Box<dyn Future<Output = itsi_error::Result<HttpResponse>> + Send>>;
|
134
|
+
|
135
|
+
// This is called once per incoming Request.
|
136
|
+
fn call(&self, req: HttpRequest) -> Self::Future {
|
137
|
+
let params = self.server_params.clone();
|
138
|
+
let self_clone = self.clone();
|
139
|
+
Box::pin(async move {
|
140
|
+
let mut req = req;
|
141
|
+
let mut resp: Option<HttpResponse> = None;
|
142
|
+
let (stack, matching_pattern) = params.middleware.get().unwrap().stack_for(&req);
|
143
|
+
let mut context = RequestContext::new(self_clone, matching_pattern);
|
144
|
+
let mut depth = 0;
|
145
|
+
for (index, elm) in stack.iter().enumerate() {
|
146
|
+
match elm.before(req, &mut context).await {
|
147
|
+
Ok(Either::Left(r)) => req = r,
|
148
|
+
Ok(Either::Right(r)) => {
|
149
|
+
resp = Some(r);
|
150
|
+
depth = index;
|
151
|
+
break;
|
152
|
+
}
|
153
|
+
Err(e) => return Err(e.into()),
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
let mut resp = match resp {
|
158
|
+
Some(r) => r,
|
159
|
+
None => {
|
160
|
+
return Err(ItsiError::InternalServerError(
|
161
|
+
"No response returned from middleware stack".to_string(),
|
162
|
+
))
|
163
|
+
}
|
164
|
+
};
|
165
|
+
for elm in stack.iter().rev().skip(stack.len() - depth - 1) {
|
166
|
+
resp = elm.after(resp, &mut context).await;
|
167
|
+
}
|
168
|
+
|
169
|
+
Ok(resp)
|
170
|
+
})
|
171
|
+
}
|
172
|
+
}
|
@@ -6,7 +6,9 @@ use super::tls::ItsiTlsAcceptor;
|
|
6
6
|
use itsi_error::{ItsiError, Result};
|
7
7
|
use itsi_tracing::info;
|
8
8
|
use socket2::{Domain, Protocol, Socket, Type};
|
9
|
+
use std::fmt::Display;
|
9
10
|
use std::net::{IpAddr, SocketAddr, TcpListener};
|
11
|
+
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
|
10
12
|
use std::sync::Arc;
|
11
13
|
use std::{os::unix::net::UnixListener, path::PathBuf};
|
12
14
|
use tokio::net::TcpListener as TokioTcpListener;
|
@@ -241,6 +243,32 @@ impl std::fmt::Display for SockAddr {
|
|
241
243
|
}
|
242
244
|
}
|
243
245
|
}
|
246
|
+
impl Display for Listener {
|
247
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
248
|
+
match self {
|
249
|
+
Listener::Tcp(listener) | Listener::TcpTls((listener, _)) => write!(
|
250
|
+
f,
|
251
|
+
"{}",
|
252
|
+
listener
|
253
|
+
.local_addr()
|
254
|
+
.map(|addr| addr.to_string())
|
255
|
+
.unwrap_or_else(|_| "".to_string())
|
256
|
+
),
|
257
|
+
|
258
|
+
Listener::Unix(listener) | Listener::UnixTls((listener, _)) => write!(
|
259
|
+
f,
|
260
|
+
"{}",
|
261
|
+
listener
|
262
|
+
.local_addr()
|
263
|
+
.map(|addr| addr
|
264
|
+
.as_pathname()
|
265
|
+
.map(|path| path.to_str().unwrap_or("").to_owned())
|
266
|
+
.unwrap_or_default())
|
267
|
+
.unwrap_or_else(|_| "".to_string())
|
268
|
+
),
|
269
|
+
}
|
270
|
+
}
|
271
|
+
}
|
244
272
|
|
245
273
|
impl Listener {
|
246
274
|
pub fn into_tokio_listener(self) -> TokioListener {
|
@@ -261,6 +289,58 @@ impl Listener {
|
|
261
289
|
),
|
262
290
|
}
|
263
291
|
}
|
292
|
+
|
293
|
+
/// Handover information when using exec to hand over the listener to a replacement process.
|
294
|
+
pub fn handover(&self) -> Result<(String, i32)> {
|
295
|
+
match self {
|
296
|
+
Listener::Tcp(listener) => {
|
297
|
+
let addr = listener.local_addr()?;
|
298
|
+
Ok((
|
299
|
+
format!("tcp://{}:{}", addr.ip().to_canonical(), addr.port()),
|
300
|
+
listener.as_raw_fd(),
|
301
|
+
))
|
302
|
+
}
|
303
|
+
Listener::TcpTls((listener, _)) => {
|
304
|
+
let addr = listener.local_addr()?;
|
305
|
+
Ok((
|
306
|
+
format!("tcp://{}:{}", addr.ip().to_canonical(), addr.port()),
|
307
|
+
listener.as_raw_fd(),
|
308
|
+
))
|
309
|
+
}
|
310
|
+
Listener::Unix(listener) => {
|
311
|
+
let addr = listener.local_addr()?;
|
312
|
+
Ok((
|
313
|
+
format!("unix://{}", addr.as_pathname().unwrap().to_str().unwrap()),
|
314
|
+
listener.as_raw_fd(),
|
315
|
+
))
|
316
|
+
}
|
317
|
+
Listener::UnixTls((listener, _)) => {
|
318
|
+
let addr = listener.local_addr()?;
|
319
|
+
Ok((
|
320
|
+
format!("unix://{}", addr.as_pathname().unwrap().to_str().unwrap()),
|
321
|
+
listener.as_raw_fd(),
|
322
|
+
))
|
323
|
+
}
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
pub fn inherit_fd(bind: Bind, fd: RawFd) -> Result<Self> {
|
328
|
+
let bound = match bind.address {
|
329
|
+
BindAddress::Ip(_) => match bind.protocol {
|
330
|
+
BindProtocol::Http => Listener::Tcp(revive_tcp_socket(fd)?),
|
331
|
+
BindProtocol::Https => {
|
332
|
+
let tcp_listener = revive_tcp_socket(fd)?;
|
333
|
+
Listener::TcpTls((tcp_listener, bind.tls_config.unwrap()))
|
334
|
+
}
|
335
|
+
_ => unreachable!(),
|
336
|
+
},
|
337
|
+
BindAddress::UnixSocket(_) => match bind.tls_config {
|
338
|
+
Some(tls_config) => Listener::UnixTls((revive_unix_socket(fd)?, tls_config)),
|
339
|
+
None => Listener::Unix(revive_unix_socket(fd)?),
|
340
|
+
},
|
341
|
+
};
|
342
|
+
Ok(bound)
|
343
|
+
}
|
264
344
|
}
|
265
345
|
|
266
346
|
impl TryFrom<Bind> for Listener {
|
@@ -285,6 +365,27 @@ impl TryFrom<Bind> for Listener {
|
|
285
365
|
}
|
286
366
|
}
|
287
367
|
|
368
|
+
fn revive_tcp_socket(fd: RawFd) -> Result<TcpListener> {
|
369
|
+
let socket = unsafe { Socket::from_raw_fd(fd) };
|
370
|
+
socket.set_reuse_port(true).ok();
|
371
|
+
socket.set_reuse_address(true).ok();
|
372
|
+
socket.set_nonblocking(true).ok();
|
373
|
+
socket.set_nodelay(true).ok();
|
374
|
+
socket.set_recv_buffer_size(262_144).ok();
|
375
|
+
socket.set_cloexec(true)?;
|
376
|
+
socket.listen(1024)?;
|
377
|
+
Ok(socket.into())
|
378
|
+
}
|
379
|
+
|
380
|
+
fn revive_unix_socket(fd: RawFd) -> Result<UnixListener> {
|
381
|
+
let socket = unsafe { Socket::from_raw_fd(fd) };
|
382
|
+
socket.set_nonblocking(true).ok();
|
383
|
+
socket.listen(1024)?;
|
384
|
+
socket.set_cloexec(true)?;
|
385
|
+
|
386
|
+
Ok(socket.into())
|
387
|
+
}
|
388
|
+
|
288
389
|
fn connect_tcp_socket(addr: IpAddr, port: u16) -> Result<TcpListener> {
|
289
390
|
let domain = match addr {
|
290
391
|
IpAddr::V4(_) => Domain::IPV4,
|
@@ -297,7 +398,7 @@ fn connect_tcp_socket(addr: IpAddr, port: u16) -> Result<TcpListener> {
|
|
297
398
|
socket.set_nonblocking(true).ok();
|
298
399
|
socket.set_nodelay(true).ok();
|
299
400
|
socket.set_recv_buffer_size(262_144).ok();
|
300
|
-
|
401
|
+
socket.set_only_v6(false).ok();
|
301
402
|
socket.bind(&socket_address.into())?;
|
302
403
|
socket.listen(1024)?;
|
303
404
|
Ok(socket.into())
|
@@ -310,7 +411,6 @@ fn connect_unix_socket(path: &PathBuf) -> Result<UnixListener> {
|
|
310
411
|
|
311
412
|
let socket_address = socket2::SockAddr::unix(path)?;
|
312
413
|
|
313
|
-
info!("Binding to {:?}", path);
|
314
414
|
socket.bind(&socket_address)?;
|
315
415
|
socket.listen(1024)?;
|
316
416
|
|
@@ -0,0 +1,153 @@
|
|
1
|
+
use super::middlewares::*;
|
2
|
+
use crate::server::{
|
3
|
+
itsi_service::RequestContext,
|
4
|
+
types::{HttpRequest, HttpResponse},
|
5
|
+
};
|
6
|
+
use async_trait::async_trait;
|
7
|
+
use either::Either;
|
8
|
+
use magnus::error::Result;
|
9
|
+
use std::cmp::Ordering;
|
10
|
+
|
11
|
+
#[derive(Debug)]
|
12
|
+
pub enum Middleware {
|
13
|
+
AllowList(AllowList),
|
14
|
+
AuthAPIKey(AuthAPIKey),
|
15
|
+
AuthBasic(AuthBasic),
|
16
|
+
AuthJwt(Box<AuthJwt>),
|
17
|
+
CacheControl(CacheControl),
|
18
|
+
Compression(Compression),
|
19
|
+
Cors(Box<Cors>),
|
20
|
+
DenyList(DenyList),
|
21
|
+
ETag(ETag),
|
22
|
+
IntrusionProtection(IntrusionProtection),
|
23
|
+
LogRequests(LogRequests),
|
24
|
+
Proxy(Proxy),
|
25
|
+
RateLimit(RateLimit),
|
26
|
+
Redirect(Redirect),
|
27
|
+
RequestHeaders(RequestHeaders),
|
28
|
+
ResponseHeaders(ResponseHeaders),
|
29
|
+
RubyApp(RubyApp),
|
30
|
+
StaticAssets(StaticAssets),
|
31
|
+
}
|
32
|
+
|
33
|
+
#[async_trait]
|
34
|
+
impl MiddlewareLayer for Middleware {
|
35
|
+
/// Called just once, to initialize the middleware state.
|
36
|
+
async fn initialize(&self) -> Result<()> {
|
37
|
+
match self {
|
38
|
+
Middleware::DenyList(filter) => filter.initialize().await,
|
39
|
+
Middleware::AllowList(filter) => filter.initialize().await,
|
40
|
+
Middleware::AuthBasic(filter) => filter.initialize().await,
|
41
|
+
Middleware::AuthJwt(filter) => filter.initialize().await,
|
42
|
+
Middleware::AuthAPIKey(filter) => filter.initialize().await,
|
43
|
+
Middleware::IntrusionProtection(filter) => filter.initialize().await,
|
44
|
+
Middleware::RateLimit(filter) => filter.initialize().await,
|
45
|
+
Middleware::RequestHeaders(filter) => filter.initialize().await,
|
46
|
+
Middleware::ResponseHeaders(filter) => filter.initialize().await,
|
47
|
+
Middleware::CacheControl(filter) => filter.initialize().await,
|
48
|
+
Middleware::Cors(filter) => filter.initialize().await,
|
49
|
+
Middleware::ETag(filter) => filter.initialize().await,
|
50
|
+
Middleware::StaticAssets(filter) => filter.initialize().await,
|
51
|
+
Middleware::Compression(filter) => filter.initialize().await,
|
52
|
+
Middleware::LogRequests(filter) => filter.initialize().await,
|
53
|
+
Middleware::Redirect(filter) => filter.initialize().await,
|
54
|
+
Middleware::Proxy(filter) => filter.initialize().await,
|
55
|
+
Middleware::RubyApp(filter) => filter.initialize().await,
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
async fn before(
|
60
|
+
&self,
|
61
|
+
req: HttpRequest,
|
62
|
+
context: &mut RequestContext,
|
63
|
+
) -> Result<Either<HttpRequest, HttpResponse>> {
|
64
|
+
match self {
|
65
|
+
Middleware::DenyList(filter) => filter.before(req, context).await,
|
66
|
+
Middleware::AllowList(filter) => filter.before(req, context).await,
|
67
|
+
Middleware::AuthBasic(filter) => filter.before(req, context).await,
|
68
|
+
Middleware::AuthJwt(filter) => filter.before(req, context).await,
|
69
|
+
Middleware::AuthAPIKey(filter) => filter.before(req, context).await,
|
70
|
+
Middleware::IntrusionProtection(filter) => filter.before(req, context).await,
|
71
|
+
Middleware::RequestHeaders(filter) => filter.before(req, context).await,
|
72
|
+
Middleware::ResponseHeaders(filter) => filter.before(req, context).await,
|
73
|
+
Middleware::RateLimit(filter) => filter.before(req, context).await,
|
74
|
+
Middleware::CacheControl(filter) => filter.before(req, context).await,
|
75
|
+
Middleware::Cors(filter) => filter.before(req, context).await,
|
76
|
+
Middleware::ETag(filter) => filter.before(req, context).await,
|
77
|
+
Middleware::StaticAssets(filter) => filter.before(req, context).await,
|
78
|
+
Middleware::Compression(filter) => filter.before(req, context).await,
|
79
|
+
Middleware::LogRequests(filter) => filter.before(req, context).await,
|
80
|
+
Middleware::Redirect(filter) => filter.before(req, context).await,
|
81
|
+
Middleware::Proxy(filter) => filter.before(req, context).await,
|
82
|
+
Middleware::RubyApp(filter) => filter.before(req, context).await,
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
async fn after(&self, res: HttpResponse, context: &mut RequestContext) -> HttpResponse {
|
87
|
+
match self {
|
88
|
+
Middleware::DenyList(filter) => filter.after(res, context).await,
|
89
|
+
Middleware::AllowList(filter) => filter.after(res, context).await,
|
90
|
+
Middleware::AuthBasic(filter) => filter.after(res, context).await,
|
91
|
+
Middleware::AuthJwt(filter) => filter.after(res, context).await,
|
92
|
+
Middleware::AuthAPIKey(filter) => filter.after(res, context).await,
|
93
|
+
Middleware::IntrusionProtection(filter) => filter.after(res, context).await,
|
94
|
+
Middleware::RateLimit(filter) => filter.after(res, context).await,
|
95
|
+
Middleware::RequestHeaders(filter) => filter.after(res, context).await,
|
96
|
+
Middleware::ResponseHeaders(filter) => filter.after(res, context).await,
|
97
|
+
Middleware::CacheControl(filter) => filter.after(res, context).await,
|
98
|
+
Middleware::Cors(filter) => filter.after(res, context).await,
|
99
|
+
Middleware::ETag(filter) => filter.after(res, context).await,
|
100
|
+
Middleware::StaticAssets(filter) => filter.after(res, context).await,
|
101
|
+
Middleware::Compression(filter) => filter.after(res, context).await,
|
102
|
+
Middleware::LogRequests(filter) => filter.after(res, context).await,
|
103
|
+
Middleware::Redirect(filter) => filter.after(res, context).await,
|
104
|
+
Middleware::Proxy(filter) => filter.after(res, context).await,
|
105
|
+
Middleware::RubyApp(filter) => filter.after(res, context).await,
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
impl Middleware {
|
111
|
+
fn variant_order(&self) -> usize {
|
112
|
+
match self {
|
113
|
+
Middleware::DenyList(_) => 0,
|
114
|
+
Middleware::AllowList(_) => 1,
|
115
|
+
Middleware::IntrusionProtection(_) => 2,
|
116
|
+
Middleware::Redirect(_) => 3,
|
117
|
+
Middleware::LogRequests(_) => 4,
|
118
|
+
Middleware::CacheControl(_) => 5,
|
119
|
+
Middleware::RequestHeaders(_) => 6,
|
120
|
+
Middleware::ResponseHeaders(_) => 7,
|
121
|
+
Middleware::AuthBasic(_) => 8,
|
122
|
+
Middleware::AuthJwt(_) => 9,
|
123
|
+
Middleware::AuthAPIKey(_) => 10,
|
124
|
+
Middleware::RateLimit(_) => 11,
|
125
|
+
Middleware::ETag(_) => 12,
|
126
|
+
Middleware::Compression(_) => 13,
|
127
|
+
Middleware::Proxy(_) => 14,
|
128
|
+
Middleware::Cors(_) => 15,
|
129
|
+
Middleware::StaticAssets(_) => 16,
|
130
|
+
Middleware::RubyApp(_) => 17,
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
impl PartialEq for Middleware {
|
136
|
+
fn eq(&self, other: &Self) -> bool {
|
137
|
+
self.variant_order() == other.variant_order()
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
impl Eq for Middleware {}
|
142
|
+
|
143
|
+
impl PartialOrd for Middleware {
|
144
|
+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
145
|
+
Some(self.variant_order().cmp(&other.variant_order()))
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
impl Ord for Middleware {
|
150
|
+
fn cmp(&self, other: &Self) -> Ordering {
|
151
|
+
self.variant_order().cmp(&other.variant_order())
|
152
|
+
}
|
153
|
+
}
|