itsi 0.1.7 → 0.1.9
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/Rakefile +21 -0
- data/crates/itsi_error/src/from.rs +26 -29
- data/crates/itsi_server/Cargo.lock +2956 -0
- data/crates/itsi_server/Cargo.toml +1 -1
- data/crates/itsi_server/src/lib.rs +5 -0
- data/crates/itsi_server/src/request/itsi_request.rs +37 -9
- data/crates/itsi_server/src/response/itsi_response.rs +12 -2
- data/crates/itsi_server/src/server/bind.rs +4 -3
- data/crates/itsi_server/src/server/itsi_server.rs +128 -78
- data/crates/itsi_server/src/server/listener.rs +98 -107
- data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +40 -24
- data/crates/itsi_server/src/server/signal.rs +7 -0
- data/crates/itsi_server/src/server/thread_worker.rs +3 -4
- data/crates/itsi_server/src/server/tls.rs +20 -13
- data/crates/itsi_tracing/src/lib.rs +18 -1
- data/gems/scheduler/Cargo.lock +12 -12
- data/gems/scheduler/ext/itsi_error/src/from.rs +26 -29
- data/gems/scheduler/ext/itsi_server/Cargo.lock +2956 -0
- data/gems/scheduler/ext/itsi_server/Cargo.toml +1 -1
- data/gems/scheduler/ext/itsi_server/src/lib.rs +5 -0
- data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +37 -9
- data/gems/scheduler/ext/itsi_server/src/response/itsi_response.rs +12 -2
- data/gems/scheduler/ext/itsi_server/src/server/bind.rs +4 -3
- data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +128 -78
- data/gems/scheduler/ext/itsi_server/src/server/listener.rs +98 -107
- data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +40 -24
- data/gems/scheduler/ext/itsi_server/src/server/signal.rs +7 -0
- data/gems/scheduler/ext/itsi_server/src/server/thread_worker.rs +3 -4
- data/gems/scheduler/ext/itsi_server/src/server/tls.rs +20 -13
- data/gems/scheduler/ext/itsi_tracing/src/lib.rs +18 -1
- data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
- data/gems/scheduler/test/test_address_resolve.rb +0 -1
- data/gems/scheduler/test/test_file_io.rb +0 -1
- data/gems/scheduler/test/test_kernel_sleep.rb +3 -4
- data/gems/server/Cargo.lock +2917 -0
- data/gems/server/Cargo.toml +7 -0
- data/gems/server/Rakefile +8 -1
- data/gems/server/ext/itsi_error/src/from.rs +26 -29
- data/gems/server/ext/itsi_server/Cargo.lock +2956 -0
- data/gems/server/ext/itsi_server/Cargo.toml +1 -1
- data/gems/server/ext/itsi_server/src/lib.rs +5 -0
- data/gems/server/ext/itsi_server/src/request/itsi_request.rs +37 -9
- data/gems/server/ext/itsi_server/src/response/itsi_response.rs +12 -2
- data/gems/server/ext/itsi_server/src/server/bind.rs +4 -3
- data/gems/server/ext/itsi_server/src/server/itsi_server.rs +128 -78
- data/gems/server/ext/itsi_server/src/server/listener.rs +98 -107
- data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +40 -24
- data/gems/server/ext/itsi_server/src/server/signal.rs +7 -0
- data/gems/server/ext/itsi_server/src/server/thread_worker.rs +3 -4
- data/gems/server/ext/itsi_server/src/server/tls.rs +20 -13
- data/gems/server/ext/itsi_tracing/src/lib.rs +18 -1
- data/gems/server/lib/itsi/index.html +91 -0
- data/gems/server/lib/itsi/request.rb +29 -21
- data/gems/server/lib/itsi/server/rack/handler/itsi.rb +3 -4
- data/gems/server/lib/itsi/server/rack_interface.rb +79 -0
- data/gems/server/lib/itsi/server/scheduler_interface.rb +21 -0
- data/gems/server/lib/itsi/server/scheduler_mode.rb +1 -1
- data/gems/server/lib/itsi/server/signal_trap.rb +24 -0
- data/gems/server/lib/itsi/server/version.rb +1 -1
- data/gems/server/lib/itsi/server.rb +68 -82
- data/gems/server/test/helpers/test_helper.rb +28 -0
- data/gems/server/test/test_itsi_server.rb +275 -3
- data/lib/itsi/version.rb +1 -1
- data/sandbox/deploy/main.tf +238 -0
- data/sandbox/deploy/outputs.tf +4 -0
- data/sandbox/deploy/vars.tf +11 -0
- data/sandbox/falcon_benchmark/Gemfile +10 -0
- data/sandbox/falcon_benchmark/Gemfile.lock +140 -0
- data/sandbox/falcon_benchmark/config.ru +54 -0
- data/sandbox/itsi_sandbox_async/Gemfile +10 -0
- data/sandbox/itsi_sandbox_async/Gemfile.lock +69 -0
- data/sandbox/itsi_sandbox_async/config.ru +10 -0
- data/sandbox/itsi_sandbox_hanami/.env +2 -0
- data/sandbox/itsi_sandbox_hanami/.gitignore +6 -0
- data/sandbox/itsi_sandbox_hanami/.rspec +1 -0
- data/sandbox/itsi_sandbox_hanami/Gemfile +49 -0
- data/sandbox/itsi_sandbox_hanami/Gemfile.lock +440 -0
- data/sandbox/itsi_sandbox_hanami/Guardfile +9 -0
- data/sandbox/itsi_sandbox_hanami/Procfile.dev +2 -0
- data/sandbox/itsi_sandbox_hanami/README.md +1 -0
- data/sandbox/itsi_sandbox_hanami/Rakefile +3 -0
- data/sandbox/itsi_sandbox_hanami/app/action.rb +12 -0
- data/sandbox/itsi_sandbox_hanami/app/actions/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/app/assets/css/app.css +5 -0
- data/sandbox/itsi_sandbox_hanami/app/assets/images/favicon.ico +0 -0
- data/sandbox/itsi_sandbox_hanami/app/assets/js/app.js +1 -0
- data/sandbox/itsi_sandbox_hanami/app/db/relation.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/app/db/repo.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/app/db/struct.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/app/operation.rb +9 -0
- data/sandbox/itsi_sandbox_hanami/app/relations/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/app/repos/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/app/structs/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/app/templates/layouts/app.html.erb +14 -0
- data/sandbox/itsi_sandbox_hanami/app/view.rb +9 -0
- data/sandbox/itsi_sandbox_hanami/app/views/helpers.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/bin/dev +8 -0
- data/sandbox/itsi_sandbox_hanami/config/app.rb +8 -0
- data/sandbox/itsi_sandbox_hanami/config/assets.js +16 -0
- data/sandbox/itsi_sandbox_hanami/config/db/migrate/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/config/db/seeds.rb +15 -0
- data/sandbox/itsi_sandbox_hanami/config/puma.rb +47 -0
- data/sandbox/itsi_sandbox_hanami/config/routes.rb +7 -0
- data/sandbox/itsi_sandbox_hanami/config/settings.rb +9 -0
- data/sandbox/itsi_sandbox_hanami/config.ru +5 -0
- data/sandbox/itsi_sandbox_hanami/db/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/lib/itsi_hanami/types.rb +11 -0
- data/sandbox/itsi_sandbox_hanami/lib/tasks/.keep +0 -0
- data/sandbox/itsi_sandbox_hanami/package-lock.json +946 -0
- data/sandbox/itsi_sandbox_hanami/package.json +8 -0
- data/sandbox/itsi_sandbox_hanami/spec/requests/root_spec.rb +11 -0
- data/sandbox/itsi_sandbox_hanami/spec/spec_helper.rb +9 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/db/cleaning.rb +42 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/db.rb +10 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/features.rb +5 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/operations.rb +8 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/requests.rb +13 -0
- data/sandbox/itsi_sandbox_hanami/spec/support/rspec.rb +61 -0
- data/sandbox/itsi_sandbox_rack/Gemfile +17 -0
- data/sandbox/itsi_sandbox_rack/Gemfile.lock +153 -0
- data/sandbox/itsi_sandbox_rack/config.ru +18 -0
- data/sandbox/itsi_sandbox_rack_lint/Gemfile +7 -0
- data/sandbox/itsi_sandbox_rack_lint/Gemfile.lock +27 -0
- data/sandbox/itsi_sandbox_rack_lint/config.ru +3 -0
- data/sandbox/itsi_sandbox_rails/.dockerignore +51 -0
- data/sandbox/itsi_sandbox_rails/.gitattributes +9 -0
- data/sandbox/itsi_sandbox_rails/.github/dependabot.yml +12 -0
- data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +90 -0
- data/sandbox/itsi_sandbox_rails/.gitignore +34 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +14 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +51 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +47 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +109 -0
- data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +3 -0
- data/sandbox/itsi_sandbox_rails/.kamal/secrets +17 -0
- data/sandbox/itsi_sandbox_rails/.rubocop.yml +8 -0
- data/sandbox/itsi_sandbox_rails/.ruby-version +1 -0
- data/sandbox/itsi_sandbox_rails/Dockerfile +72 -0
- data/sandbox/itsi_sandbox_rails/Gemfile +72 -0
- data/sandbox/itsi_sandbox_rails/Gemfile.lock +480 -0
- data/sandbox/itsi_sandbox_rails/README.md +24 -0
- data/sandbox/itsi_sandbox_rails/Rakefile +6 -0
- data/sandbox/itsi_sandbox_rails/app/assets/images/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +10 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/application_controller.rb +4 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/concerns/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/home_controller.rb +51 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +41 -0
- data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +32 -0
- data/sandbox/itsi_sandbox_rails/app/helpers/application_helper.rb +2 -0
- data/sandbox/itsi_sandbox_rails/app/javascript/application.js +3 -0
- data/sandbox/itsi_sandbox_rails/app/javascript/controllers/application.js +9 -0
- data/sandbox/itsi_sandbox_rails/app/javascript/controllers/hello_controller.js +7 -0
- data/sandbox/itsi_sandbox_rails/app/javascript/controllers/index.js +4 -0
- data/sandbox/itsi_sandbox_rails/app/jobs/application_job.rb +7 -0
- data/sandbox/itsi_sandbox_rails/app/mailers/application_mailer.rb +4 -0
- data/sandbox/itsi_sandbox_rails/app/models/application_record.rb +3 -0
- data/sandbox/itsi_sandbox_rails/app/models/concerns/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/app/models/post.rb +2 -0
- data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +28 -0
- data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.html.erb +13 -0
- data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.text.erb +1 -0
- data/sandbox/itsi_sandbox_rails/app/views/pwa/manifest.json.erb +22 -0
- data/sandbox/itsi_sandbox_rails/app/views/pwa/service-worker.js +26 -0
- data/sandbox/itsi_sandbox_rails/bin/brakeman +7 -0
- data/sandbox/itsi_sandbox_rails/bin/bundle +109 -0
- data/sandbox/itsi_sandbox_rails/bin/dev +2 -0
- data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +14 -0
- data/sandbox/itsi_sandbox_rails/bin/importmap +4 -0
- data/sandbox/itsi_sandbox_rails/bin/jobs +6 -0
- data/sandbox/itsi_sandbox_rails/bin/kamal +27 -0
- data/sandbox/itsi_sandbox_rails/bin/rails +4 -0
- data/sandbox/itsi_sandbox_rails/bin/rake +4 -0
- data/sandbox/itsi_sandbox_rails/bin/rubocop +8 -0
- data/sandbox/itsi_sandbox_rails/bin/setup +34 -0
- data/sandbox/itsi_sandbox_rails/bin/thrust +5 -0
- data/sandbox/itsi_sandbox_rails/config/application.rb +61 -0
- data/sandbox/itsi_sandbox_rails/config/boot.rb +4 -0
- data/sandbox/itsi_sandbox_rails/config/cable.yml +17 -0
- data/sandbox/itsi_sandbox_rails/config/cache.yml +16 -0
- data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -0
- data/sandbox/itsi_sandbox_rails/config/database.yml +40 -0
- data/sandbox/itsi_sandbox_rails/config/deploy.yml +116 -0
- data/sandbox/itsi_sandbox_rails/config/environment.rb +5 -0
- data/sandbox/itsi_sandbox_rails/config/environments/development.rb +72 -0
- data/sandbox/itsi_sandbox_rails/config/environments/production.rb +90 -0
- data/sandbox/itsi_sandbox_rails/config/environments/test.rb +53 -0
- data/sandbox/itsi_sandbox_rails/config/importmap.rb +7 -0
- data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +7 -0
- data/sandbox/itsi_sandbox_rails/config/initializers/content_security_policy.rb +25 -0
- data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +8 -0
- data/sandbox/itsi_sandbox_rails/config/initializers/inflections.rb +16 -0
- data/sandbox/itsi_sandbox_rails/config/locales/en.yml +31 -0
- data/sandbox/itsi_sandbox_rails/config/puma.rb +41 -0
- data/sandbox/itsi_sandbox_rails/config/queue.yml +18 -0
- data/sandbox/itsi_sandbox_rails/config/recurring.yml +10 -0
- data/sandbox/itsi_sandbox_rails/config/routes.rb +21 -0
- data/sandbox/itsi_sandbox_rails/config/storage.yml +34 -0
- data/sandbox/itsi_sandbox_rails/config.ru +7 -0
- data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +11 -0
- data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +14 -0
- data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +10 -0
- data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +129 -0
- data/sandbox/itsi_sandbox_rails/db/schema.rb +23 -0
- data/sandbox/itsi_sandbox_rails/db/seeds.rb +9 -0
- data/sandbox/itsi_sandbox_rails/lib/tasks/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/log/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/public/400.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/404.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/422.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/500.html +114 -0
- data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
- data/sandbox/itsi_sandbox_rails/public/icon.svg +3 -0
- data/sandbox/itsi_sandbox_rails/public/robots.txt +1 -0
- data/sandbox/itsi_sandbox_rails/script/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/storage/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/application_system_test_case.rb +5 -0
- data/sandbox/itsi_sandbox_rails/test/controllers/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/fixtures/files/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +9 -0
- data/sandbox/itsi_sandbox_rails/test/helpers/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/integration/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/mailers/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/models/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +7 -0
- data/sandbox/itsi_sandbox_rails/test/system/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/test/test_helper.rb +15 -0
- data/sandbox/itsi_sandbox_rails/tmp/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/tmp/pids/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/tmp/storage/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/vendor/.keep +0 -0
- data/sandbox/itsi_sandbox_rails/vendor/javascript/.keep +0 -0
- data/sandbox/itsi_sandbox_roda/Gemfile +5 -0
- data/sandbox/itsi_sandbox_roda/Gemfile.lock +44 -0
- data/sandbox/itsi_sandbox_roda/config.ru +39 -0
- data/sandbox/itsi_sinatra/Gemfile +9 -0
- data/sandbox/itsi_sinatra/Gemfile.lock +81 -0
- data/sandbox/itsi_sinatra/app.rb +9 -0
- data/sandbox/pebble/docker-compose.yml +11 -0
- data/tasks.txt +4 -4
- metadata +199 -10
- data/gems/server/lib/itsi/signals.rb +0 -23
- data/gems/server/test/test_helper.rb +0 -7
@@ -19,6 +19,7 @@ parking_lot = "0.12.3"
|
|
19
19
|
rustls-pemfile = "2.2.0"
|
20
20
|
tokio-rustls = "0.26.2"
|
21
21
|
bytes = "1.3"
|
22
|
+
tokio-rustls-acme = "0.6.0"
|
22
23
|
rcgen = { version = "0.13.2", features = ["x509-parser", "pem"] }
|
23
24
|
base64 = "0.22.1"
|
24
25
|
http-body-util = "0.1.2"
|
@@ -39,7 +40,6 @@ httparse = "1.10.1"
|
|
39
40
|
async-channel = "2.3.1"
|
40
41
|
tempfile = "3.18.0"
|
41
42
|
sysinfo = "0.33.1"
|
42
|
-
tokio-rustls-acme = "0.6.0"
|
43
43
|
rustls = "0.23.23"
|
44
44
|
fs2 = "0.4.3"
|
45
45
|
ring = "0.17.14"
|
@@ -71,6 +71,7 @@ fn init(ruby: &Ruby) -> Result<()> {
|
|
71
71
|
server.define_singleton_method("new", function!(Server::new, -1))?;
|
72
72
|
server.define_singleton_method("reset_signal_handlers", function!(reset_signal_handlers, 0))?;
|
73
73
|
server.define_method("start", method!(Server::start, 0))?;
|
74
|
+
server.define_method("stop", method!(Server::stop, 0))?;
|
74
75
|
|
75
76
|
let request = ruby.get_inner(&ITSI_REQUEST);
|
76
77
|
request.define_method("path", method!(ItsiRequest::path, 0))?;
|
@@ -86,6 +87,8 @@ fn init(ruby: &Ruby) -> Result<()> {
|
|
86
87
|
request.define_method("port", method!(ItsiRequest::port, 0))?;
|
87
88
|
request.define_method("body", method!(ItsiRequest::body, 0))?;
|
88
89
|
request.define_method("response", method!(ItsiRequest::response, 0))?;
|
90
|
+
request.define_method("json?", method!(ItsiRequest::is_json, 0))?;
|
91
|
+
request.define_method("html?", method!(ItsiRequest::is_html, 0))?;
|
89
92
|
|
90
93
|
let body_proxy = ruby.get_inner(&ITSI_BODY_PROXY);
|
91
94
|
body_proxy.define_method("gets", method!(ItsiBodyProxy::gets, 0))?;
|
@@ -102,6 +105,8 @@ fn init(ruby: &Ruby) -> Result<()> {
|
|
102
105
|
response.define_method("close_read", method!(ItsiResponse::close_read, 0))?;
|
103
106
|
response.define_method("close", method!(ItsiResponse::close, 0))?;
|
104
107
|
response.define_method("hijack", method!(ItsiResponse::hijack, 1))?;
|
108
|
+
response.define_method("json?", method!(ItsiResponse::is_json, 0))?;
|
109
|
+
response.define_method("html?", method!(ItsiResponse::is_html, 0))?;
|
105
110
|
|
106
111
|
Ok(())
|
107
112
|
}
|
@@ -6,14 +6,14 @@ use crate::{
|
|
6
6
|
response::itsi_response::ItsiResponse,
|
7
7
|
server::{
|
8
8
|
itsi_server::{RequestJob, Server},
|
9
|
-
listener::{
|
9
|
+
listener::{ListenerInfo, SockAddr},
|
10
10
|
serve_strategy::single_mode::RunningPhase,
|
11
11
|
},
|
12
12
|
};
|
13
13
|
use bytes::Bytes;
|
14
14
|
use derive_more::Debug;
|
15
15
|
use futures::StreamExt;
|
16
|
-
use http::{request::Parts, Response, StatusCode};
|
16
|
+
use http::{request::Parts, HeaderValue, Response, StatusCode};
|
17
17
|
use http_body_util::{combinators::BoxBody, BodyExt, Empty};
|
18
18
|
use hyper::{body::Incoming, Request};
|
19
19
|
use itsi_error::from::CLIENT_CONNECTION_CLOSED;
|
@@ -44,11 +44,12 @@ pub struct ItsiRequest {
|
|
44
44
|
pub remote_addr: String,
|
45
45
|
pub version: String,
|
46
46
|
#[debug(skip)]
|
47
|
-
pub(crate) listener: Arc<
|
47
|
+
pub(crate) listener: Arc<ListenerInfo>,
|
48
48
|
#[debug(skip)]
|
49
49
|
pub server: Arc<Server>,
|
50
50
|
pub response: ItsiResponse,
|
51
51
|
pub start: Instant,
|
52
|
+
pub content_type: String,
|
52
53
|
}
|
53
54
|
|
54
55
|
impl fmt::Display for ItsiRequest {
|
@@ -82,6 +83,14 @@ impl ItsiRequest {
|
|
82
83
|
}
|
83
84
|
}
|
84
85
|
|
86
|
+
pub fn is_json(&self) -> bool {
|
87
|
+
self.content_type.eq("application/json")
|
88
|
+
}
|
89
|
+
|
90
|
+
pub fn is_html(&self) -> bool {
|
91
|
+
self.content_type.eq("text/html")
|
92
|
+
}
|
93
|
+
|
85
94
|
pub fn process(
|
86
95
|
self,
|
87
96
|
ruby: &Ruby,
|
@@ -128,7 +137,7 @@ impl ItsiRequest {
|
|
128
137
|
hyper_request: Request<Incoming>,
|
129
138
|
sender: async_channel::Sender<RequestJob>,
|
130
139
|
server: Arc<Server>,
|
131
|
-
listener: Arc<
|
140
|
+
listener: Arc<ListenerInfo>,
|
132
141
|
addr: SockAddr,
|
133
142
|
shutdown_rx: watch::Receiver<RunningPhase>,
|
134
143
|
) -> itsi_error::Result<Response<BoxBody<Bytes, Infallible>>> {
|
@@ -153,7 +162,7 @@ impl ItsiRequest {
|
|
153
162
|
request: Request<Incoming>,
|
154
163
|
sock_addr: SockAddr,
|
155
164
|
server: Arc<Server>,
|
156
|
-
listener: Arc<
|
165
|
+
listener: Arc<ListenerInfo>,
|
157
166
|
) -> (ItsiRequest, mpsc::Receiver<Option<Bytes>>) {
|
158
167
|
let (parts, body) = request.into_parts();
|
159
168
|
let body = if server.stream_body.is_some_and(|f| f) {
|
@@ -175,8 +184,27 @@ impl ItsiRequest {
|
|
175
184
|
server,
|
176
185
|
listener,
|
177
186
|
version: format!("{:?}", &parts.version),
|
178
|
-
response: ItsiResponse::new(
|
187
|
+
response: ItsiResponse::new(
|
188
|
+
parts.clone(),
|
189
|
+
response_channel.0,
|
190
|
+
parts
|
191
|
+
.headers
|
192
|
+
.get("Accept")
|
193
|
+
.unwrap_or(&HeaderValue::from_static("text/html"))
|
194
|
+
.to_str()
|
195
|
+
.unwrap()
|
196
|
+
.to_string(),
|
197
|
+
),
|
179
198
|
start: Instant::now(),
|
199
|
+
content_type: parts
|
200
|
+
.headers
|
201
|
+
.get("Content-Type")
|
202
|
+
.unwrap_or(&HeaderValue::from_static(
|
203
|
+
"application/x-www-form-urlencoded",
|
204
|
+
))
|
205
|
+
.to_str()
|
206
|
+
.unwrap()
|
207
|
+
.to_string(),
|
180
208
|
parts,
|
181
209
|
},
|
182
210
|
response_channel.1,
|
@@ -231,7 +259,7 @@ impl ItsiRequest {
|
|
231
259
|
.uri
|
232
260
|
.host()
|
233
261
|
.map(|host| host.to_string())
|
234
|
-
.unwrap_or_else(|| self.listener.host()))
|
262
|
+
.unwrap_or_else(|| self.listener.host.clone()))
|
235
263
|
}
|
236
264
|
|
237
265
|
pub(crate) fn scheme(&self) -> MagnusResult<String> {
|
@@ -240,7 +268,7 @@ impl ItsiRequest {
|
|
240
268
|
.uri
|
241
269
|
.scheme()
|
242
270
|
.map(|scheme| scheme.to_string())
|
243
|
-
.unwrap_or_else(|| self.listener.scheme()))
|
271
|
+
.unwrap_or_else(|| self.listener.scheme.clone()))
|
244
272
|
}
|
245
273
|
|
246
274
|
pub(crate) fn headers(&self) -> MagnusResult<Vec<(String, &str)>> {
|
@@ -264,7 +292,7 @@ impl ItsiRequest {
|
|
264
292
|
}
|
265
293
|
|
266
294
|
pub(crate) fn port(&self) -> MagnusResult<u16> {
|
267
|
-
Ok(self.parts.uri.port_u16().unwrap_or(self.listener.port
|
295
|
+
Ok(self.parts.uri.port_u16().unwrap_or(self.listener.port))
|
268
296
|
}
|
269
297
|
|
270
298
|
pub(crate) fn body(&self) -> MagnusResult<Value> {
|
@@ -37,6 +37,7 @@ use crate::server::serve_strategy::single_mode::RunningPhase;
|
|
37
37
|
#[derive(Debug, Clone)]
|
38
38
|
pub struct ItsiResponse {
|
39
39
|
pub data: Arc<ResponseData>,
|
40
|
+
pub accept: String,
|
40
41
|
}
|
41
42
|
|
42
43
|
#[derive(Debug)]
|
@@ -293,11 +294,19 @@ impl ItsiResponse {
|
|
293
294
|
Ok(true)
|
294
295
|
}
|
295
296
|
|
297
|
+
pub fn is_html(&self) -> bool {
|
298
|
+
self.accept.starts_with("text/html")
|
299
|
+
}
|
300
|
+
|
301
|
+
pub fn is_json(&self) -> bool {
|
302
|
+
self.accept.starts_with("application/json")
|
303
|
+
}
|
304
|
+
|
296
305
|
pub fn close_read(&self) -> MagnusResult<bool> {
|
297
|
-
|
306
|
+
Ok(true)
|
298
307
|
}
|
299
308
|
|
300
|
-
pub fn new(parts: Parts, response_writer: mpsc::Sender<Option<Bytes
|
309
|
+
pub fn new(parts: Parts, response_writer: mpsc::Sender<Option<Bytes>>, accept: String) -> Self {
|
301
310
|
Self {
|
302
311
|
data: Arc::new(ResponseData {
|
303
312
|
response: RwLock::new(Some(Response::new(BoxBody::new(Empty::new())))),
|
@@ -306,6 +315,7 @@ impl ItsiResponse {
|
|
306
315
|
hijacked_socket: RwLock::new(None),
|
307
316
|
parts,
|
308
317
|
}),
|
318
|
+
accept,
|
309
319
|
}
|
310
320
|
}
|
311
321
|
|
@@ -9,6 +9,7 @@ use std::{
|
|
9
9
|
path::PathBuf,
|
10
10
|
str::FromStr,
|
11
11
|
};
|
12
|
+
|
12
13
|
#[derive(Debug, Clone)]
|
13
14
|
pub enum BindAddress {
|
14
15
|
Ip(IpAddr),
|
@@ -129,13 +130,13 @@ impl FromStr for Bind {
|
|
129
130
|
BindProtocol::Unix => None,
|
130
131
|
BindProtocol::Unixs => Some(configure_tls(host, &options)?),
|
131
132
|
};
|
132
|
-
|
133
|
-
Ok(Self {
|
133
|
+
let bind = Self {
|
134
134
|
address,
|
135
135
|
port,
|
136
136
|
protocol,
|
137
137
|
tls_config,
|
138
|
-
}
|
138
|
+
};
|
139
|
+
Ok(bind)
|
139
140
|
}
|
140
141
|
}
|
141
142
|
|
@@ -2,24 +2,26 @@ use super::{
|
|
2
2
|
bind::Bind,
|
3
3
|
listener::Listener,
|
4
4
|
serve_strategy::{cluster_mode::ClusterMode, single_mode::SingleMode},
|
5
|
-
signal::{
|
5
|
+
signal::{
|
6
|
+
clear_signal_handlers, reset_signal_handlers, send_shutdown_event, SIGNAL_HANDLER_CHANNEL,
|
7
|
+
},
|
6
8
|
};
|
7
9
|
use crate::{request::itsi_request::ItsiRequest, server::serve_strategy::ServeStrategy};
|
8
10
|
use derive_more::Debug;
|
9
|
-
use itsi_rb_helpers::call_without_gvl;
|
10
|
-
use itsi_tracing::error;
|
11
|
+
use itsi_rb_helpers::{call_without_gvl, HeapVal};
|
12
|
+
use itsi_tracing::{error, run_silently};
|
11
13
|
use magnus::{
|
12
14
|
block::Proc,
|
13
15
|
error::Result,
|
14
|
-
scan_args::{get_kwargs, scan_args, Args, KwArgs},
|
16
|
+
scan_args::{get_kwargs, scan_args, Args, KwArgs, ScanArgsKw, ScanArgsOpt, ScanArgsRequired},
|
15
17
|
value::{InnerValue, Opaque, ReprValue},
|
16
|
-
RHash, Ruby, Symbol, Value,
|
18
|
+
ArgList, RHash, Ruby, Symbol, Value,
|
17
19
|
};
|
18
|
-
use parking_lot::Mutex;
|
20
|
+
use parking_lot::{Mutex, RwLock};
|
19
21
|
use std::{cmp::max, ops::Deref, sync::Arc};
|
20
22
|
use tracing::{info, instrument};
|
21
23
|
|
22
|
-
static DEFAULT_BIND: &str = "localhost:3000";
|
24
|
+
static DEFAULT_BIND: &str = "http://localhost:3000";
|
23
25
|
|
24
26
|
#[magnus::wrap(class = "Itsi::Server", free_immediately, size)]
|
25
27
|
#[derive(Clone)]
|
@@ -39,7 +41,7 @@ type AfterFork = Mutex<Arc<Option<Box<dyn Fn() + Send + Sync>>>>;
|
|
39
41
|
#[derive(Debug)]
|
40
42
|
pub struct ServerConfig {
|
41
43
|
#[debug(skip)]
|
42
|
-
pub app:
|
44
|
+
pub app: HeapVal,
|
43
45
|
#[allow(unused)]
|
44
46
|
pub workers: u8,
|
45
47
|
#[allow(unused)]
|
@@ -55,6 +57,9 @@ pub struct ServerConfig {
|
|
55
57
|
pub scheduler_class: Option<String>,
|
56
58
|
pub stream_body: Option<bool>,
|
57
59
|
pub worker_memory_limit: Option<u64>,
|
60
|
+
#[debug(skip)]
|
61
|
+
pub(crate) strategy: RwLock<Option<ServeStrategy>>,
|
62
|
+
pub silence: bool,
|
58
63
|
}
|
59
64
|
|
60
65
|
#[derive(Debug)]
|
@@ -63,6 +68,35 @@ pub enum RequestJob {
|
|
63
68
|
Shutdown,
|
64
69
|
}
|
65
70
|
|
71
|
+
// Define your helper function.
|
72
|
+
// Here P, A, C correspond to the types for the first tuple, second tuple, and extra parameters respectively.
|
73
|
+
fn extract_args<Req, Opt, Splat>(
|
74
|
+
scan_args: &Args<(), (), (), (), RHash, ()>,
|
75
|
+
primaries: &[&str],
|
76
|
+
rest: &[&str],
|
77
|
+
) -> Result<KwArgs<Req, Opt, Splat>>
|
78
|
+
where
|
79
|
+
Req: ScanArgsRequired,
|
80
|
+
Opt: ScanArgsOpt,
|
81
|
+
Splat: ScanArgsKw,
|
82
|
+
{
|
83
|
+
// Combine the primary and rest names into one Vec of Symbols.
|
84
|
+
let symbols: Vec<Symbol> = primaries
|
85
|
+
.iter()
|
86
|
+
.chain(rest.iter())
|
87
|
+
.map(|&name| Symbol::new(name))
|
88
|
+
.collect();
|
89
|
+
|
90
|
+
// Call the "slice" function with the combined symbols.
|
91
|
+
let hash = scan_args
|
92
|
+
.keywords
|
93
|
+
.funcall::<_, _, RHash>("slice", symbols.into_arg_list_with(&Ruby::get().unwrap()))
|
94
|
+
.unwrap();
|
95
|
+
|
96
|
+
// Finally, call get_kwargs with the original name slices.
|
97
|
+
get_kwargs(hash, primaries, rest)
|
98
|
+
}
|
99
|
+
|
66
100
|
impl Server {
|
67
101
|
#[instrument(
|
68
102
|
name = "Itsi",
|
@@ -73,39 +107,44 @@ impl Server {
|
|
73
107
|
pub fn new(args: &[Value]) -> Result<Self> {
|
74
108
|
let scan_args: Args<(), (), (), (), RHash, ()> = scan_args(args)?;
|
75
109
|
|
76
|
-
type
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
110
|
+
type Args1 = KwArgs<
|
111
|
+
(Value,),
|
112
|
+
(
|
113
|
+
// Workers
|
114
|
+
Option<u8>,
|
115
|
+
// Threads
|
116
|
+
Option<u8>,
|
117
|
+
// Shutdown Timeout
|
118
|
+
Option<f64>,
|
119
|
+
// Script Name
|
120
|
+
Option<String>,
|
121
|
+
// Binds
|
122
|
+
Option<Vec<String>>,
|
123
|
+
// Stream Body
|
124
|
+
Option<bool>,
|
125
|
+
),
|
126
|
+
(),
|
127
|
+
>;
|
128
|
+
|
129
|
+
type Args2 = KwArgs<
|
130
|
+
(),
|
131
|
+
(
|
132
|
+
// Before Fork
|
133
|
+
Option<Proc>,
|
134
|
+
// After Fork
|
135
|
+
Option<Proc>,
|
136
|
+
// Scheduler Class
|
137
|
+
Option<String>,
|
138
|
+
// Worker Memory Limit
|
139
|
+
Option<u64>,
|
140
|
+
// Silence
|
141
|
+
Option<bool>,
|
142
|
+
),
|
143
|
+
(),
|
144
|
+
>;
|
145
|
+
|
146
|
+
let args1: Args1 = extract_args(
|
147
|
+
&scan_args,
|
109
148
|
&["app"],
|
110
149
|
&[
|
111
150
|
"workers",
|
@@ -113,24 +152,24 @@ impl Server {
|
|
113
152
|
"shutdown_timeout",
|
114
153
|
"script_name",
|
115
154
|
"binds",
|
116
|
-
"before_fork",
|
117
|
-
"after_fork",
|
118
|
-
"scheduler_class",
|
119
155
|
"stream_body",
|
120
156
|
],
|
121
157
|
)?;
|
122
158
|
|
123
|
-
let args2:
|
124
|
-
scan_args
|
125
|
-
.keywords
|
126
|
-
.funcall::<_, _, RHash>("slice", (Symbol::new("worker_memory_limit"),))
|
127
|
-
.unwrap(),
|
159
|
+
let args2: Args2 = extract_args(
|
160
|
+
&scan_args,
|
128
161
|
&[],
|
129
|
-
&[
|
162
|
+
&[
|
163
|
+
"before_fork",
|
164
|
+
"after_fork",
|
165
|
+
"scheduler_class",
|
166
|
+
"worker_memory_limit",
|
167
|
+
"silence",
|
168
|
+
],
|
130
169
|
)?;
|
131
170
|
|
132
171
|
let config = ServerConfig {
|
133
|
-
app:
|
172
|
+
app: HeapVal::from(args1.required.0),
|
134
173
|
workers: max(args1.optional.0.unwrap_or(1), 1),
|
135
174
|
threads: max(args1.optional.1.unwrap_or(1), 1),
|
136
175
|
shutdown_timeout: args1.optional.2.unwrap_or(5.0),
|
@@ -144,7 +183,8 @@ impl Server {
|
|
144
183
|
.map(|s| s.parse())
|
145
184
|
.collect::<itsi_error::Result<Vec<Bind>>>()?,
|
146
185
|
),
|
147
|
-
|
186
|
+
stream_body: args1.optional.5,
|
187
|
+
before_fork: Mutex::new(args2.optional.0.map(|p| {
|
148
188
|
let opaque_proc = Opaque::from(p);
|
149
189
|
Box::new(move || {
|
150
190
|
opaque_proc
|
@@ -153,7 +193,7 @@ impl Server {
|
|
153
193
|
.unwrap();
|
154
194
|
}) as Box<dyn FnOnce() + Send + Sync>
|
155
195
|
})),
|
156
|
-
after_fork: Mutex::new(Arc::new(
|
196
|
+
after_fork: Mutex::new(Arc::new(args2.optional.1.map(|p| {
|
157
197
|
let opaque_proc = Opaque::from(p);
|
158
198
|
Box::new(move || {
|
159
199
|
opaque_proc
|
@@ -162,15 +202,18 @@ impl Server {
|
|
162
202
|
.unwrap();
|
163
203
|
}) as Box<dyn Fn() + Send + Sync>
|
164
204
|
}))),
|
165
|
-
scheduler_class:
|
166
|
-
|
167
|
-
|
205
|
+
scheduler_class: args2.optional.2.clone(),
|
206
|
+
worker_memory_limit: args2.optional.3,
|
207
|
+
silence: args2.optional.4.is_some_and(|s| s),
|
208
|
+
strategy: RwLock::new(None),
|
168
209
|
};
|
169
210
|
|
170
|
-
if
|
171
|
-
|
172
|
-
|
173
|
-
|
211
|
+
if !config.silence {
|
212
|
+
if let Some(scheduler_class) = args2.optional.2 {
|
213
|
+
info!(scheduler_class, fiber_scheduler = true);
|
214
|
+
} else {
|
215
|
+
info!(fiber_scheduler = false);
|
216
|
+
}
|
174
217
|
}
|
175
218
|
|
176
219
|
Ok(Server {
|
@@ -179,7 +222,7 @@ impl Server {
|
|
179
222
|
}
|
180
223
|
|
181
224
|
#[instrument(name = "Bind", skip_all, fields(binds=format!("{:?}", self.config.binds.lock())))]
|
182
|
-
pub(crate) fn
|
225
|
+
pub(crate) fn build_listeners(&self) -> Result<Arc<Vec<Arc<Listener>>>> {
|
183
226
|
let listeners = self
|
184
227
|
.config
|
185
228
|
.binds
|
@@ -195,11 +238,9 @@ impl Server {
|
|
195
238
|
Ok(Arc::new(listeners))
|
196
239
|
}
|
197
240
|
|
198
|
-
pub(crate) fn build_strategy(
|
199
|
-
self,
|
200
|
-
listeners: Arc<Vec<Arc<Listener>>>,
|
201
|
-
) -> Result<ServeStrategy> {
|
241
|
+
pub(crate) fn build_strategy(self, listeners: Arc<Vec<Arc<Listener>>>) -> Result<()> {
|
202
242
|
let server = Arc::new(self);
|
243
|
+
let server_clone = server.clone();
|
203
244
|
|
204
245
|
let strategy = if server.config.workers == 1 {
|
205
246
|
ServeStrategy::Single(Arc::new(SingleMode::new(
|
@@ -214,31 +255,40 @@ impl Server {
|
|
214
255
|
SIGNAL_HANDLER_CHANNEL.0.clone(),
|
215
256
|
)))
|
216
257
|
};
|
217
|
-
|
258
|
+
|
259
|
+
*server_clone.strategy.write() = Some(strategy);
|
260
|
+
Ok(())
|
261
|
+
}
|
262
|
+
|
263
|
+
pub fn stop(&self) -> Result<()> {
|
264
|
+
send_shutdown_event();
|
265
|
+
Ok(())
|
218
266
|
}
|
219
267
|
|
220
268
|
pub fn start(&self) -> Result<()> {
|
269
|
+
if self.silence {
|
270
|
+
run_silently(|| self.build_and_run_strategy())
|
271
|
+
} else {
|
272
|
+
self.build_and_run_strategy()
|
273
|
+
}
|
274
|
+
}
|
275
|
+
|
276
|
+
fn build_and_run_strategy(&self) -> Result<()> {
|
221
277
|
reset_signal_handlers();
|
222
278
|
let rself = self.clone();
|
223
|
-
let listeners = self.
|
279
|
+
let listeners = self.build_listeners()?;
|
224
280
|
let listeners_clone = listeners.clone();
|
225
281
|
call_without_gvl(move || -> Result<()> {
|
226
|
-
|
227
|
-
if let Err(e) = strategy.run() {
|
282
|
+
rself.clone().build_strategy(listeners_clone)?;
|
283
|
+
if let Err(e) = rself.clone().strategy.read().as_ref().unwrap().run() {
|
228
284
|
error!("Error running server: {}", e);
|
229
|
-
strategy.stop()?;
|
285
|
+
rself.strategy.read().as_ref().unwrap().stop()?;
|
230
286
|
}
|
231
|
-
drop(strategy);
|
232
287
|
Ok(())
|
233
288
|
})?;
|
234
|
-
if let Ok(listeners) = Arc::try_unwrap(listeners) {
|
235
|
-
listeners.into_iter().for_each(|listener| {
|
236
|
-
if let Ok(listener) = Arc::try_unwrap(listener) {
|
237
|
-
listener.unbind()
|
238
|
-
};
|
239
|
-
});
|
240
|
-
}
|
241
289
|
clear_signal_handlers();
|
290
|
+
self.strategy.write().take();
|
291
|
+
info!("Server stopped");
|
242
292
|
Ok(())
|
243
293
|
}
|
244
294
|
}
|