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
@@ -1,58 +1,49 @@
|
|
1
|
-
use crate::{
|
2
|
-
body_proxy::{
|
3
|
-
big_bytes::BigBytes,
|
4
|
-
itsi_body_proxy::{ItsiBody, ItsiBodyProxy},
|
5
|
-
},
|
6
|
-
response::itsi_response::ItsiResponse,
|
7
|
-
server::{
|
8
|
-
itsi_server::{RequestJob, Server},
|
9
|
-
listener::{ListenerInfo, SockAddr},
|
10
|
-
serve_strategy::single_mode::RunningPhase,
|
11
|
-
},
|
12
|
-
};
|
13
|
-
use bytes::Bytes;
|
14
1
|
use derive_more::Debug;
|
15
2
|
use futures::StreamExt;
|
16
|
-
use http::{request::Parts,
|
3
|
+
use http::{request::Parts, Response, StatusCode, Version};
|
17
4
|
use http_body_util::{combinators::BoxBody, BodyExt, Empty};
|
18
|
-
use hyper::{body::Incoming, Request};
|
19
5
|
use itsi_error::from::CLIENT_CONNECTION_CLOSED;
|
20
|
-
use itsi_rb_helpers::print_rb_backtrace;
|
6
|
+
use itsi_rb_helpers::{print_rb_backtrace, HeapValue};
|
21
7
|
use itsi_tracing::{debug, error};
|
22
8
|
use magnus::{
|
9
|
+
block::Proc,
|
23
10
|
error::{ErrorType, Result as MagnusResult},
|
24
11
|
Error,
|
25
12
|
};
|
26
13
|
use magnus::{
|
27
|
-
value::{LazyId,
|
28
|
-
|
14
|
+
value::{LazyId, ReprValue},
|
15
|
+
Ruby, Value,
|
16
|
+
};
|
17
|
+
use std::{fmt, io::Write, sync::Arc, time::Instant};
|
18
|
+
use tokio::sync::mpsc::{self};
|
19
|
+
|
20
|
+
use super::{
|
21
|
+
itsi_body_proxy::{big_bytes::BigBytes, ItsiBody, ItsiBodyProxy},
|
22
|
+
itsi_http_response::ItsiHttpResponse,
|
29
23
|
};
|
30
|
-
use
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
use crate::server::{
|
25
|
+
byte_frame::ByteFrame,
|
26
|
+
itsi_service::RequestContext,
|
27
|
+
request_job::RequestJob,
|
28
|
+
types::{HttpRequest, HttpResponse},
|
34
29
|
};
|
35
|
-
|
30
|
+
|
36
31
|
static ID_MESSAGE: LazyId = LazyId::new("message");
|
37
32
|
|
38
33
|
#[derive(Debug)]
|
39
|
-
#[magnus::wrap(class = "Itsi::
|
40
|
-
pub struct
|
34
|
+
#[magnus::wrap(class = "Itsi::HttpRequest", free_immediately, size)]
|
35
|
+
pub struct ItsiHttpRequest {
|
41
36
|
pub parts: Parts,
|
42
37
|
#[debug(skip)]
|
43
38
|
pub body: ItsiBody,
|
44
|
-
pub
|
45
|
-
pub
|
46
|
-
#[debug(skip)]
|
47
|
-
pub(crate) listener: Arc<ListenerInfo>,
|
48
|
-
#[debug(skip)]
|
49
|
-
pub server: Arc<Server>,
|
50
|
-
pub response: ItsiResponse,
|
39
|
+
pub version: Version,
|
40
|
+
pub response: ItsiHttpResponse,
|
51
41
|
pub start: Instant,
|
52
|
-
|
42
|
+
#[debug(skip)]
|
43
|
+
pub context: RequestContext,
|
53
44
|
}
|
54
45
|
|
55
|
-
impl fmt::Display for
|
46
|
+
impl fmt::Display for ItsiHttpRequest {
|
56
47
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
57
48
|
write!(
|
58
49
|
f,
|
@@ -64,7 +55,7 @@ impl fmt::Display for ItsiRequest {
|
|
64
55
|
}
|
65
56
|
}
|
66
57
|
|
67
|
-
impl
|
58
|
+
impl ItsiHttpRequest {
|
68
59
|
pub fn is_connection_closed_err(ruby: &Ruby, err: &Error) -> bool {
|
69
60
|
match err.error_type() {
|
70
61
|
ErrorType::Jump(_) => false,
|
@@ -82,35 +73,32 @@ impl ItsiRequest {
|
|
82
73
|
}
|
83
74
|
}
|
84
75
|
}
|
76
|
+
fn content_type_str(&self) -> &str {
|
77
|
+
self.parts
|
78
|
+
.headers
|
79
|
+
.get("Content-Type")
|
80
|
+
.and_then(|hv| hv.to_str().ok())
|
81
|
+
.unwrap_or("application/x-www-form-urlencoded")
|
82
|
+
}
|
85
83
|
|
86
84
|
pub fn is_json(&self) -> bool {
|
87
|
-
self.
|
85
|
+
self.content_type_str() == "application/json"
|
88
86
|
}
|
89
87
|
|
90
88
|
pub fn is_html(&self) -> bool {
|
91
|
-
self.
|
89
|
+
self.content_type_str() == "text/html"
|
92
90
|
}
|
93
91
|
|
94
|
-
pub fn process(
|
95
|
-
self,
|
96
|
-
ruby: &Ruby,
|
97
|
-
server: RClass,
|
98
|
-
app: Opaque<Value>,
|
99
|
-
) -> magnus::error::Result<()> {
|
100
|
-
let req = format!("{}", self);
|
92
|
+
pub fn process(self, ruby: &Ruby, app_proc: Arc<HeapValue<Proc>>) -> magnus::error::Result<()> {
|
101
93
|
let response = self.response.clone();
|
102
|
-
let
|
103
|
-
debug!("{} Started", req);
|
104
|
-
let result = server.funcall::<_, _, Value>(*ID_CALL, (app, self));
|
94
|
+
let result = app_proc.call::<_, Value>((self,));
|
105
95
|
if let Err(err) = result {
|
106
96
|
Self::internal_error(ruby, response, err);
|
107
97
|
}
|
108
|
-
debug!("{} Finished in {:?}", req, start.elapsed());
|
109
|
-
|
110
98
|
Ok(())
|
111
99
|
}
|
112
100
|
|
113
|
-
pub fn internal_error(ruby: &Ruby, response:
|
101
|
+
pub fn internal_error(ruby: &Ruby, response: ItsiHttpResponse, err: Error) {
|
114
102
|
if Self::is_connection_closed_err(ruby, &err) {
|
115
103
|
debug!("Connection closed by client");
|
116
104
|
response.close();
|
@@ -127,17 +115,18 @@ impl ItsiRequest {
|
|
127
115
|
}
|
128
116
|
|
129
117
|
pub(crate) async fn process_request(
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
) -> itsi_error::Result<Response<BoxBody<Bytes, Infallible>>> {
|
137
|
-
let (request, mut receiver) = ItsiRequest::new(hyper_request, addr, server, listener).await;
|
138
|
-
|
118
|
+
app: Arc<HeapValue<Proc>>,
|
119
|
+
hyper_request: HttpRequest,
|
120
|
+
context: &RequestContext,
|
121
|
+
) -> itsi_error::Result<HttpResponse> {
|
122
|
+
let (request, mut receiver) = ItsiHttpRequest::new(hyper_request, context).await;
|
123
|
+
let shutdown_channel = context.service.shutdown_channel.clone();
|
139
124
|
let response = request.response.clone();
|
140
|
-
match
|
125
|
+
match context
|
126
|
+
.sender
|
127
|
+
.send(RequestJob::ProcessHttpRequest(request, app))
|
128
|
+
.await
|
129
|
+
{
|
141
130
|
Err(err) => {
|
142
131
|
error!("Error occurred: {}", err);
|
143
132
|
let mut response = Response::new(BoxBody::new(Empty::new()));
|
@@ -145,20 +134,22 @@ impl ItsiRequest {
|
|
145
134
|
Ok(response)
|
146
135
|
}
|
147
136
|
_ => match receiver.recv().await {
|
148
|
-
Some(first_frame) => Ok(response
|
149
|
-
|
137
|
+
Some(first_frame) => Ok(response
|
138
|
+
.build(first_frame, receiver, shutdown_channel)
|
139
|
+
.await),
|
140
|
+
None => Ok(response
|
141
|
+
.build(ByteFrame::Empty, receiver, shutdown_channel)
|
142
|
+
.await),
|
150
143
|
},
|
151
144
|
}
|
152
145
|
}
|
153
146
|
|
154
147
|
pub(crate) async fn new(
|
155
|
-
request:
|
156
|
-
|
157
|
-
|
158
|
-
listener: Arc<ListenerInfo>,
|
159
|
-
) -> (ItsiRequest, mpsc::Receiver<Option<Bytes>>) {
|
148
|
+
request: HttpRequest,
|
149
|
+
context: &RequestContext,
|
150
|
+
) -> (ItsiHttpRequest, mpsc::Receiver<ByteFrame>) {
|
160
151
|
let (parts, body) = request.into_parts();
|
161
|
-
let body = if
|
152
|
+
let body = if context.server_params.streamable_body {
|
162
153
|
ItsiBody::Stream(ItsiBodyProxy::new(body))
|
163
154
|
} else {
|
164
155
|
let mut body_bytes = BigBytes::new();
|
@@ -169,35 +160,14 @@ impl ItsiRequest {
|
|
169
160
|
}
|
170
161
|
ItsiBody::Buffered(body_bytes)
|
171
162
|
};
|
172
|
-
let response_channel = mpsc::channel::<
|
163
|
+
let response_channel = mpsc::channel::<ByteFrame>(100);
|
173
164
|
(
|
174
165
|
Self {
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
listener,
|
179
|
-
version: format!("{:?}", &parts.version),
|
180
|
-
response: ItsiResponse::new(
|
181
|
-
parts.clone(),
|
182
|
-
response_channel.0,
|
183
|
-
parts
|
184
|
-
.headers
|
185
|
-
.get("Accept")
|
186
|
-
.unwrap_or(&HeaderValue::from_static("text/html"))
|
187
|
-
.to_str()
|
188
|
-
.unwrap()
|
189
|
-
.to_string(),
|
190
|
-
),
|
166
|
+
context: context.clone(),
|
167
|
+
version: parts.version,
|
168
|
+
response: ItsiHttpResponse::new(parts.clone(), response_channel.0),
|
191
169
|
start: Instant::now(),
|
192
|
-
|
193
|
-
.headers
|
194
|
-
.get("Content-Type")
|
195
|
-
.unwrap_or(&HeaderValue::from_static(
|
196
|
-
"application/x-www-form-urlencoded",
|
197
|
-
))
|
198
|
-
.to_str()
|
199
|
-
.unwrap()
|
200
|
-
.to_string(),
|
170
|
+
body,
|
201
171
|
parts,
|
202
172
|
},
|
203
173
|
response_channel.1,
|
@@ -209,12 +179,12 @@ impl ItsiRequest {
|
|
209
179
|
.parts
|
210
180
|
.uri
|
211
181
|
.path()
|
212
|
-
.strip_prefix(&self.
|
182
|
+
.strip_prefix(&self.context.server_params.script_name)
|
213
183
|
.unwrap_or(self.parts.uri.path()))
|
214
184
|
}
|
215
185
|
|
216
186
|
pub(crate) fn script_name(&self) -> MagnusResult<&str> {
|
217
|
-
Ok(&self.
|
187
|
+
Ok(&self.context.server_params.script_name)
|
218
188
|
}
|
219
189
|
|
220
190
|
pub(crate) fn query_string(&self) -> MagnusResult<&str> {
|
@@ -226,7 +196,14 @@ impl ItsiRequest {
|
|
226
196
|
}
|
227
197
|
|
228
198
|
pub(crate) fn version(&self) -> MagnusResult<&str> {
|
229
|
-
Ok(
|
199
|
+
Ok(match self.version {
|
200
|
+
Version::HTTP_09 => "HTTP/0.9",
|
201
|
+
Version::HTTP_10 => "HTTP/1.0",
|
202
|
+
Version::HTTP_11 => "HTTP/1.1",
|
203
|
+
Version::HTTP_2 => "HTTP/2.0",
|
204
|
+
Version::HTTP_3 => "HTTP/3.0",
|
205
|
+
_ => "HTTP/Unknown",
|
206
|
+
})
|
230
207
|
}
|
231
208
|
|
232
209
|
pub(crate) fn rack_protocol(&self) -> MagnusResult<Vec<&str>> {
|
@@ -246,53 +223,60 @@ impl ItsiRequest {
|
|
246
223
|
.unwrap_or_else(|| vec!["http"]))
|
247
224
|
}
|
248
225
|
|
249
|
-
pub(crate) fn host(&self) -> MagnusResult
|
226
|
+
pub(crate) fn host(&self) -> MagnusResult<&str> {
|
250
227
|
Ok(self
|
251
228
|
.parts
|
252
229
|
.uri
|
253
230
|
.host()
|
254
|
-
.
|
255
|
-
.unwrap_or_else(|| self.listener.host.clone()))
|
231
|
+
.unwrap_or_else(|| &self.context.listener.host))
|
256
232
|
}
|
257
233
|
|
258
|
-
pub(crate) fn scheme(&self) -> MagnusResult
|
234
|
+
pub(crate) fn scheme(&self) -> MagnusResult<&str> {
|
259
235
|
Ok(self
|
260
236
|
.parts
|
261
237
|
.uri
|
262
238
|
.scheme()
|
263
|
-
.map(|scheme| scheme.
|
264
|
-
.unwrap_or_else(|| self.listener.scheme
|
239
|
+
.map(|scheme| scheme.as_str())
|
240
|
+
.unwrap_or_else(|| &self.context.listener.scheme))
|
265
241
|
}
|
266
242
|
|
267
|
-
pub(crate) fn headers(&self) -> MagnusResult<Vec<(
|
243
|
+
pub(crate) fn headers(&self) -> MagnusResult<Vec<(&str, &str)>> {
|
268
244
|
Ok(self
|
269
245
|
.parts
|
270
246
|
.headers
|
271
247
|
.iter()
|
272
|
-
.map(|(hn, hv)|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
.
|
248
|
+
.map(|(hn, hv)| (hn.as_str(), hv.to_str().unwrap_or("")))
|
249
|
+
.collect::<Vec<(&str, &str)>>())
|
250
|
+
}
|
251
|
+
|
252
|
+
pub fn header(&self, name: String) -> MagnusResult<Option<Vec<&str>>> {
|
253
|
+
let result: Vec<&str> = self
|
254
|
+
.parts
|
255
|
+
.headers
|
256
|
+
.get_all(&name)
|
257
|
+
.iter()
|
258
|
+
.filter_map(|value| value.to_str().ok())
|
259
|
+
.collect();
|
260
|
+
Ok(Some(result))
|
281
261
|
}
|
282
262
|
|
283
263
|
pub(crate) fn remote_addr(&self) -> MagnusResult<&str> {
|
284
|
-
Ok(&self.
|
264
|
+
Ok(&self.context.addr)
|
285
265
|
}
|
286
266
|
|
287
267
|
pub(crate) fn port(&self) -> MagnusResult<u16> {
|
288
|
-
Ok(self
|
268
|
+
Ok(self
|
269
|
+
.parts
|
270
|
+
.uri
|
271
|
+
.port_u16()
|
272
|
+
.unwrap_or(self.context.listener.port))
|
289
273
|
}
|
290
274
|
|
291
|
-
pub(crate) fn body(&self) -> MagnusResult<Value
|
275
|
+
pub(crate) fn body(&self) -> MagnusResult<Option<Value>> {
|
292
276
|
Ok(self.body.into_value())
|
293
277
|
}
|
294
278
|
|
295
|
-
pub(crate) fn response(&self) -> MagnusResult<
|
279
|
+
pub(crate) fn response(&self) -> MagnusResult<ItsiHttpResponse> {
|
296
280
|
Ok(self.response.clone())
|
297
281
|
}
|
298
282
|
}
|
@@ -13,7 +13,7 @@ use itsi_tracing::error;
|
|
13
13
|
use magnus::error::Result as MagnusResult;
|
14
14
|
use parking_lot::RwLock;
|
15
15
|
use std::{
|
16
|
-
|
16
|
+
collections::HashMap,
|
17
17
|
io,
|
18
18
|
os::{fd::FromRawFd, unix::net::UnixStream},
|
19
19
|
str::FromStr,
|
@@ -31,31 +31,32 @@ use tokio_stream::wrappers::ReceiverStream;
|
|
31
31
|
use tokio_util::io::ReaderStream;
|
32
32
|
use tracing::warn;
|
33
33
|
|
34
|
-
use crate::server::
|
34
|
+
use crate::server::{
|
35
|
+
byte_frame::ByteFrame, serve_strategy::single_mode::RunningPhase, types::HttpResponse,
|
36
|
+
};
|
35
37
|
|
36
|
-
#[magnus::wrap(class = "Itsi::
|
38
|
+
#[magnus::wrap(class = "Itsi::HttpResponse", free_immediately, size)]
|
37
39
|
#[derive(Debug, Clone)]
|
38
|
-
pub struct
|
40
|
+
pub struct ItsiHttpResponse {
|
39
41
|
pub data: Arc<ResponseData>,
|
40
|
-
pub accept: String,
|
41
42
|
}
|
42
43
|
|
43
44
|
#[derive(Debug)]
|
44
45
|
pub struct ResponseData {
|
45
|
-
pub response: RwLock<Option<
|
46
|
-
pub response_writer: RwLock<Option<mpsc::Sender<
|
46
|
+
pub response: RwLock<Option<HttpResponse>>,
|
47
|
+
pub response_writer: RwLock<Option<mpsc::Sender<ByteFrame>>>,
|
47
48
|
pub response_buffer: RwLock<BytesMut>,
|
48
49
|
pub hijacked_socket: RwLock<Option<UnixStream>>,
|
49
50
|
pub parts: Parts,
|
50
51
|
}
|
51
52
|
|
52
|
-
impl
|
53
|
+
impl ItsiHttpResponse {
|
53
54
|
pub async fn build(
|
54
55
|
&self,
|
55
|
-
first_frame:
|
56
|
-
receiver: mpsc::Receiver<
|
56
|
+
first_frame: ByteFrame,
|
57
|
+
receiver: mpsc::Receiver<ByteFrame>,
|
57
58
|
shutdown_rx: watch::Receiver<RunningPhase>,
|
58
|
-
) ->
|
59
|
+
) -> HttpResponse {
|
59
60
|
if self.is_hijacked() {
|
60
61
|
return match self.process_hijacked_response().await {
|
61
62
|
Ok(result) => result,
|
@@ -65,14 +66,13 @@ impl ItsiResponse {
|
|
65
66
|
}
|
66
67
|
};
|
67
68
|
}
|
68
|
-
|
69
69
|
let mut response = self.data.response.write().take().unwrap();
|
70
|
-
*response.body_mut() = if first_frame
|
70
|
+
*response.body_mut() = if matches!(first_frame, ByteFrame::Empty) {
|
71
71
|
BoxBody::new(Empty::new())
|
72
|
-
} else if
|
73
|
-
BoxBody::new(Full::new(first_frame.
|
72
|
+
} else if matches!(first_frame, ByteFrame::End(_)) {
|
73
|
+
BoxBody::new(Full::new(first_frame.into()))
|
74
74
|
} else {
|
75
|
-
let initial_frame = tokio_stream::once(Ok(Frame::data(first_frame
|
75
|
+
let initial_frame = tokio_stream::once(Ok(Frame::data(Bytes::from(first_frame))));
|
76
76
|
let frame_stream = unfold(
|
77
77
|
(ReceiverStream::new(receiver), shutdown_rx),
|
78
78
|
|(mut receiver, mut shutdown_rx)| async move {
|
@@ -82,13 +82,14 @@ impl ItsiResponse {
|
|
82
82
|
loop {
|
83
83
|
tokio::select! {
|
84
84
|
maybe_bytes = receiver.next() => {
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
} else {
|
89
|
-
// Receiver closed, end the stream.
|
90
|
-
return None;
|
85
|
+
match maybe_bytes {
|
86
|
+
Some(ByteFrame::Data(bytes)) | Some(ByteFrame::End(bytes)) => {
|
87
|
+
return Some((Ok(Frame::data(bytes)), (receiver, shutdown_rx)));
|
91
88
|
}
|
89
|
+
_ => {
|
90
|
+
return None;
|
91
|
+
}
|
92
|
+
}
|
92
93
|
},
|
93
94
|
_ = shutdown_rx.changed() => {
|
94
95
|
match *shutdown_rx.borrow() {
|
@@ -184,7 +185,7 @@ impl ItsiResponse {
|
|
184
185
|
Ok((headers, status, requires_upgrade, reader))
|
185
186
|
}
|
186
187
|
|
187
|
-
pub async fn process_hijacked_response(&self) -> Result<
|
188
|
+
pub async fn process_hijacked_response(&self) -> Result<HttpResponse> {
|
188
189
|
let (headers, status, requires_upgrade, reader) = self.read_hijacked_headers().await?;
|
189
190
|
let mut response = if requires_upgrade {
|
190
191
|
let parts = self.data.parts.clone();
|
@@ -261,28 +262,31 @@ impl ItsiResponse {
|
|
261
262
|
}
|
262
263
|
}
|
263
264
|
|
264
|
-
pub fn send_frame(&self, frame: Bytes) -> MagnusResult<
|
265
|
-
self.send_frame_into(frame, &self.data.response_writer)
|
265
|
+
pub fn send_frame(&self, frame: Bytes) -> MagnusResult<()> {
|
266
|
+
self.send_frame_into(ByteFrame::Data(frame), &self.data.response_writer)
|
266
267
|
}
|
267
268
|
|
268
|
-
pub fn
|
269
|
-
|
269
|
+
pub fn recv_frame(&self) {
|
270
|
+
// not implemented
|
271
|
+
}
|
272
|
+
|
273
|
+
pub fn send_and_close(&self, frame: Bytes) -> MagnusResult<()> {
|
274
|
+
let result = self.send_frame_into(ByteFrame::End(frame), &self.data.response_writer);
|
270
275
|
self.data.response_writer.write().take();
|
271
276
|
result
|
272
277
|
}
|
273
278
|
|
274
279
|
pub fn send_frame_into(
|
275
280
|
&self,
|
276
|
-
frame:
|
277
|
-
writer: &RwLock<Option<mpsc::Sender<
|
278
|
-
) -> MagnusResult<
|
281
|
+
frame: ByteFrame,
|
282
|
+
writer: &RwLock<Option<mpsc::Sender<ByteFrame>>>,
|
283
|
+
) -> MagnusResult<()> {
|
279
284
|
if let Some(writer) = writer.write().as_ref() {
|
280
|
-
writer
|
281
|
-
.blocking_send(
|
282
|
-
.map_err(|_| itsi_error::ItsiError::ClientConnectionClosed)
|
283
|
-
.ok();
|
285
|
+
return Ok(writer
|
286
|
+
.blocking_send(frame)
|
287
|
+
.map_err(|_| itsi_error::ItsiError::ClientConnectionClosed)?);
|
284
288
|
}
|
285
|
-
Ok(
|
289
|
+
Ok(())
|
286
290
|
}
|
287
291
|
|
288
292
|
pub fn is_hijacked(&self) -> bool {
|
@@ -293,20 +297,28 @@ impl ItsiResponse {
|
|
293
297
|
self.data.response_writer.write().take();
|
294
298
|
Ok(true)
|
295
299
|
}
|
300
|
+
fn accept_str(&self) -> &str {
|
301
|
+
self.data
|
302
|
+
.parts
|
303
|
+
.headers
|
304
|
+
.get("Content-Type")
|
305
|
+
.and_then(|hv| hv.to_str().ok()) // handle invalid utf-8
|
306
|
+
.unwrap_or("application/x-www-form-urlencoded")
|
307
|
+
}
|
296
308
|
|
297
309
|
pub fn is_html(&self) -> bool {
|
298
|
-
self.
|
310
|
+
self.accept_str().starts_with("text/html")
|
299
311
|
}
|
300
312
|
|
301
313
|
pub fn is_json(&self) -> bool {
|
302
|
-
self.
|
314
|
+
self.accept_str().starts_with("application/json")
|
303
315
|
}
|
304
316
|
|
305
317
|
pub fn close_read(&self) -> MagnusResult<bool> {
|
306
318
|
Ok(true)
|
307
319
|
}
|
308
320
|
|
309
|
-
pub fn new(parts: Parts, response_writer: mpsc::Sender<
|
321
|
+
pub fn new(parts: Parts, response_writer: mpsc::Sender<ByteFrame>) -> Self {
|
310
322
|
Self {
|
311
323
|
data: Arc::new(ResponseData {
|
312
324
|
response: RwLock::new(Some(Response::new(BoxBody::new(Empty::new())))),
|
@@ -315,7 +327,6 @@ impl ItsiResponse {
|
|
315
327
|
hijacked_socket: RwLock::new(None),
|
316
328
|
parts,
|
317
329
|
}),
|
318
|
-
accept,
|
319
330
|
}
|
320
331
|
}
|
321
332
|
|
@@ -330,6 +341,26 @@ impl ItsiResponse {
|
|
330
341
|
Ok(())
|
331
342
|
}
|
332
343
|
|
344
|
+
pub fn add_headers(&self, headers: HashMap<Bytes, Vec<Bytes>>) -> MagnusResult<()> {
|
345
|
+
if let Some(ref mut resp) = *self.data.response.write() {
|
346
|
+
let headers_mut = resp.headers_mut();
|
347
|
+
for (name, values) in headers {
|
348
|
+
let header_name = HeaderName::from_bytes(&name).map_err(|e| {
|
349
|
+
itsi_error::ItsiError::InvalidInput(format!(
|
350
|
+
"Invalid header name {:?}: {:?}",
|
351
|
+
name, e
|
352
|
+
))
|
353
|
+
})?;
|
354
|
+
for value in values {
|
355
|
+
let header_value = unsafe { HeaderValue::from_maybe_shared_unchecked(value) };
|
356
|
+
headers_mut.insert(&header_name, header_value);
|
357
|
+
}
|
358
|
+
}
|
359
|
+
}
|
360
|
+
|
361
|
+
Ok(())
|
362
|
+
}
|
363
|
+
|
333
364
|
pub fn set_status(&self, status: u16) -> MagnusResult<()> {
|
334
365
|
if let Some(ref mut resp) = *self.data.response.write() {
|
335
366
|
*resp.status_mut() = StatusCode::from_u16(status).map_err(|e| {
|
@@ -348,8 +379,8 @@ impl ItsiResponse {
|
|
348
379
|
*self.data.hijacked_socket.write() = Some(stream);
|
349
380
|
if let Some(writer) = self.data.response_writer.write().as_ref() {
|
350
381
|
writer
|
351
|
-
.blocking_send(
|
352
|
-
.map_err(|_| itsi_error::ItsiError::ClientConnectionClosed)
|
382
|
+
.blocking_send(ByteFrame::Empty)
|
383
|
+
.map_err(|_| itsi_error::ItsiError::ClientConnectionClosed)?
|
353
384
|
}
|
354
385
|
self.close();
|
355
386
|
Ok(())
|