itsi 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +49 -0
  3. data/Rakefile +20 -0
  4. data/crates/itsi_error/src/from.rs +26 -29
  5. data/crates/itsi_error/src/lib.rs +1 -1
  6. data/crates/itsi_server/Cargo.lock +2956 -0
  7. data/crates/itsi_server/Cargo.toml +2 -1
  8. data/crates/itsi_server/src/env.rs +43 -0
  9. data/crates/itsi_server/src/lib.rs +1 -0
  10. data/crates/itsi_server/src/request/itsi_request.rs +7 -7
  11. data/crates/itsi_server/src/server/bind.rs +4 -3
  12. data/crates/itsi_server/src/server/itsi_server.rs +1 -8
  13. data/crates/itsi_server/src/server/listener.rs +98 -107
  14. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +22 -12
  15. data/crates/itsi_server/src/server/tls/locked_dir_cache.rs +3 -3
  16. data/crates/itsi_server/src/server/tls.rs +83 -44
  17. data/gems/scheduler/ext/itsi_error/src/from.rs +26 -29
  18. data/gems/scheduler/ext/itsi_error/src/lib.rs +1 -1
  19. data/gems/scheduler/ext/itsi_server/Cargo.lock +2956 -0
  20. data/gems/scheduler/ext/itsi_server/Cargo.toml +2 -1
  21. data/gems/scheduler/ext/itsi_server/src/env.rs +43 -0
  22. data/gems/scheduler/ext/itsi_server/src/lib.rs +1 -0
  23. data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +7 -7
  24. data/gems/scheduler/ext/itsi_server/src/server/bind.rs +4 -3
  25. data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +1 -8
  26. data/gems/scheduler/ext/itsi_server/src/server/listener.rs +98 -107
  27. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +22 -12
  28. data/gems/scheduler/ext/itsi_server/src/server/tls/locked_dir_cache.rs +3 -3
  29. data/gems/scheduler/ext/itsi_server/src/server/tls.rs +83 -44
  30. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  31. data/gems/server/Cargo.lock +2917 -0
  32. data/gems/server/Cargo.toml +7 -0
  33. data/gems/server/ext/itsi_error/src/from.rs +26 -29
  34. data/gems/server/ext/itsi_error/src/lib.rs +1 -1
  35. data/gems/server/ext/itsi_server/Cargo.lock +2956 -0
  36. data/gems/server/ext/itsi_server/Cargo.toml +2 -1
  37. data/gems/server/ext/itsi_server/src/env.rs +43 -0
  38. data/gems/server/ext/itsi_server/src/lib.rs +1 -0
  39. data/gems/server/ext/itsi_server/src/request/itsi_request.rs +7 -7
  40. data/gems/server/ext/itsi_server/src/server/bind.rs +4 -3
  41. data/gems/server/ext/itsi_server/src/server/itsi_server.rs +1 -8
  42. data/gems/server/ext/itsi_server/src/server/listener.rs +98 -107
  43. data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +22 -12
  44. data/gems/server/ext/itsi_server/src/server/tls/locked_dir_cache.rs +3 -3
  45. data/gems/server/ext/itsi_server/src/server/tls.rs +83 -44
  46. data/gems/server/lib/itsi/index.html.erb +91 -0
  47. data/gems/server/lib/itsi/server/scheduler_mode.rb +1 -1
  48. data/gems/server/lib/itsi/server/version.rb +1 -1
  49. data/gems/server/lib/itsi/server.rb +22 -2
  50. data/lib/itsi/version.rb +1 -1
  51. data/sandbox/deploy/main.tf +237 -0
  52. data/sandbox/deploy/outputs.tf +4 -0
  53. data/sandbox/deploy/vars.tf +11 -0
  54. data/sandbox/falcon_benchmark/Gemfile +10 -0
  55. data/sandbox/falcon_benchmark/Gemfile.lock +140 -0
  56. data/sandbox/falcon_benchmark/config.ru +54 -0
  57. data/sandbox/itsi_sandbox_async/Gemfile +10 -0
  58. data/sandbox/itsi_sandbox_async/Gemfile.lock +69 -0
  59. data/sandbox/itsi_sandbox_async/config.ru +10 -0
  60. data/sandbox/itsi_sandbox_hanami/.env +2 -0
  61. data/sandbox/itsi_sandbox_hanami/.gitignore +6 -0
  62. data/sandbox/itsi_sandbox_hanami/.rspec +1 -0
  63. data/sandbox/itsi_sandbox_hanami/Gemfile +49 -0
  64. data/sandbox/itsi_sandbox_hanami/Gemfile.lock +440 -0
  65. data/sandbox/itsi_sandbox_hanami/Guardfile +9 -0
  66. data/sandbox/itsi_sandbox_hanami/Procfile.dev +2 -0
  67. data/sandbox/itsi_sandbox_hanami/README.md +1 -0
  68. data/sandbox/itsi_sandbox_hanami/Rakefile +3 -0
  69. data/sandbox/itsi_sandbox_hanami/app/action.rb +12 -0
  70. data/sandbox/itsi_sandbox_hanami/app/actions/.keep +0 -0
  71. data/sandbox/itsi_sandbox_hanami/app/assets/css/app.css +5 -0
  72. data/sandbox/itsi_sandbox_hanami/app/assets/images/favicon.ico +0 -0
  73. data/sandbox/itsi_sandbox_hanami/app/assets/js/app.js +1 -0
  74. data/sandbox/itsi_sandbox_hanami/app/db/relation.rb +10 -0
  75. data/sandbox/itsi_sandbox_hanami/app/db/repo.rb +10 -0
  76. data/sandbox/itsi_sandbox_hanami/app/db/struct.rb +10 -0
  77. data/sandbox/itsi_sandbox_hanami/app/operation.rb +9 -0
  78. data/sandbox/itsi_sandbox_hanami/app/relations/.keep +0 -0
  79. data/sandbox/itsi_sandbox_hanami/app/repos/.keep +0 -0
  80. data/sandbox/itsi_sandbox_hanami/app/structs/.keep +0 -0
  81. data/sandbox/itsi_sandbox_hanami/app/templates/layouts/app.html.erb +14 -0
  82. data/sandbox/itsi_sandbox_hanami/app/view.rb +9 -0
  83. data/sandbox/itsi_sandbox_hanami/app/views/helpers.rb +10 -0
  84. data/sandbox/itsi_sandbox_hanami/bin/dev +8 -0
  85. data/sandbox/itsi_sandbox_hanami/config/app.rb +8 -0
  86. data/sandbox/itsi_sandbox_hanami/config/assets.js +16 -0
  87. data/sandbox/itsi_sandbox_hanami/config/db/migrate/.keep +0 -0
  88. data/sandbox/itsi_sandbox_hanami/config/db/seeds.rb +15 -0
  89. data/sandbox/itsi_sandbox_hanami/config/puma.rb +47 -0
  90. data/sandbox/itsi_sandbox_hanami/config/routes.rb +7 -0
  91. data/sandbox/itsi_sandbox_hanami/config/settings.rb +9 -0
  92. data/sandbox/itsi_sandbox_hanami/config.ru +5 -0
  93. data/sandbox/itsi_sandbox_hanami/db/.keep +0 -0
  94. data/sandbox/itsi_sandbox_hanami/lib/itsi_hanami/types.rb +11 -0
  95. data/sandbox/itsi_sandbox_hanami/lib/tasks/.keep +0 -0
  96. data/sandbox/itsi_sandbox_hanami/package-lock.json +946 -0
  97. data/sandbox/itsi_sandbox_hanami/package.json +8 -0
  98. data/sandbox/itsi_sandbox_hanami/spec/requests/root_spec.rb +11 -0
  99. data/sandbox/itsi_sandbox_hanami/spec/spec_helper.rb +9 -0
  100. data/sandbox/itsi_sandbox_hanami/spec/support/db/cleaning.rb +42 -0
  101. data/sandbox/itsi_sandbox_hanami/spec/support/db.rb +10 -0
  102. data/sandbox/itsi_sandbox_hanami/spec/support/features.rb +5 -0
  103. data/sandbox/itsi_sandbox_hanami/spec/support/operations.rb +8 -0
  104. data/sandbox/itsi_sandbox_hanami/spec/support/requests.rb +13 -0
  105. data/sandbox/itsi_sandbox_hanami/spec/support/rspec.rb +61 -0
  106. data/sandbox/itsi_sandbox_rack/Gemfile +17 -0
  107. data/sandbox/itsi_sandbox_rack/Gemfile.lock +153 -0
  108. data/sandbox/itsi_sandbox_rack/config.ru +18 -0
  109. data/sandbox/itsi_sandbox_rack_lint/Gemfile +7 -0
  110. data/sandbox/itsi_sandbox_rack_lint/Gemfile.lock +27 -0
  111. data/sandbox/itsi_sandbox_rack_lint/config.ru +3 -0
  112. data/sandbox/itsi_sandbox_rails/.dockerignore +51 -0
  113. data/sandbox/itsi_sandbox_rails/.gitattributes +9 -0
  114. data/sandbox/itsi_sandbox_rails/.github/dependabot.yml +12 -0
  115. data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +90 -0
  116. data/sandbox/itsi_sandbox_rails/.gitignore +34 -0
  117. data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +3 -0
  118. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +3 -0
  119. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +14 -0
  120. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +3 -0
  121. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +3 -0
  122. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +51 -0
  123. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +47 -0
  124. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +109 -0
  125. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +3 -0
  126. data/sandbox/itsi_sandbox_rails/.kamal/secrets +17 -0
  127. data/sandbox/itsi_sandbox_rails/.rubocop.yml +8 -0
  128. data/sandbox/itsi_sandbox_rails/.ruby-version +1 -0
  129. data/sandbox/itsi_sandbox_rails/Dockerfile +72 -0
  130. data/sandbox/itsi_sandbox_rails/Gemfile +72 -0
  131. data/sandbox/itsi_sandbox_rails/Gemfile.lock +480 -0
  132. data/sandbox/itsi_sandbox_rails/README.md +24 -0
  133. data/sandbox/itsi_sandbox_rails/Rakefile +6 -0
  134. data/sandbox/itsi_sandbox_rails/app/assets/images/.keep +0 -0
  135. data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +10 -0
  136. data/sandbox/itsi_sandbox_rails/app/controllers/application_controller.rb +4 -0
  137. data/sandbox/itsi_sandbox_rails/app/controllers/concerns/.keep +0 -0
  138. data/sandbox/itsi_sandbox_rails/app/controllers/home_controller.rb +51 -0
  139. data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +41 -0
  140. data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +32 -0
  141. data/sandbox/itsi_sandbox_rails/app/helpers/application_helper.rb +2 -0
  142. data/sandbox/itsi_sandbox_rails/app/javascript/application.js +3 -0
  143. data/sandbox/itsi_sandbox_rails/app/javascript/controllers/application.js +9 -0
  144. data/sandbox/itsi_sandbox_rails/app/javascript/controllers/hello_controller.js +7 -0
  145. data/sandbox/itsi_sandbox_rails/app/javascript/controllers/index.js +4 -0
  146. data/sandbox/itsi_sandbox_rails/app/jobs/application_job.rb +7 -0
  147. data/sandbox/itsi_sandbox_rails/app/mailers/application_mailer.rb +4 -0
  148. data/sandbox/itsi_sandbox_rails/app/models/application_record.rb +3 -0
  149. data/sandbox/itsi_sandbox_rails/app/models/concerns/.keep +0 -0
  150. data/sandbox/itsi_sandbox_rails/app/models/post.rb +2 -0
  151. data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +28 -0
  152. data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.html.erb +13 -0
  153. data/sandbox/itsi_sandbox_rails/app/views/layouts/mailer.text.erb +1 -0
  154. data/sandbox/itsi_sandbox_rails/app/views/pwa/manifest.json.erb +22 -0
  155. data/sandbox/itsi_sandbox_rails/app/views/pwa/service-worker.js +26 -0
  156. data/sandbox/itsi_sandbox_rails/bin/brakeman +7 -0
  157. data/sandbox/itsi_sandbox_rails/bin/bundle +109 -0
  158. data/sandbox/itsi_sandbox_rails/bin/dev +2 -0
  159. data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +14 -0
  160. data/sandbox/itsi_sandbox_rails/bin/importmap +4 -0
  161. data/sandbox/itsi_sandbox_rails/bin/jobs +6 -0
  162. data/sandbox/itsi_sandbox_rails/bin/kamal +27 -0
  163. data/sandbox/itsi_sandbox_rails/bin/rails +4 -0
  164. data/sandbox/itsi_sandbox_rails/bin/rake +4 -0
  165. data/sandbox/itsi_sandbox_rails/bin/rubocop +8 -0
  166. data/sandbox/itsi_sandbox_rails/bin/setup +34 -0
  167. data/sandbox/itsi_sandbox_rails/bin/thrust +5 -0
  168. data/sandbox/itsi_sandbox_rails/config/application.rb +61 -0
  169. data/sandbox/itsi_sandbox_rails/config/boot.rb +4 -0
  170. data/sandbox/itsi_sandbox_rails/config/cable.yml +17 -0
  171. data/sandbox/itsi_sandbox_rails/config/cache.yml +16 -0
  172. data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -0
  173. data/sandbox/itsi_sandbox_rails/config/database.yml +40 -0
  174. data/sandbox/itsi_sandbox_rails/config/deploy.yml +116 -0
  175. data/sandbox/itsi_sandbox_rails/config/environment.rb +5 -0
  176. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +72 -0
  177. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +90 -0
  178. data/sandbox/itsi_sandbox_rails/config/environments/test.rb +53 -0
  179. data/sandbox/itsi_sandbox_rails/config/importmap.rb +7 -0
  180. data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +7 -0
  181. data/sandbox/itsi_sandbox_rails/config/initializers/content_security_policy.rb +25 -0
  182. data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +8 -0
  183. data/sandbox/itsi_sandbox_rails/config/initializers/inflections.rb +16 -0
  184. data/sandbox/itsi_sandbox_rails/config/locales/en.yml +31 -0
  185. data/sandbox/itsi_sandbox_rails/config/puma.rb +41 -0
  186. data/sandbox/itsi_sandbox_rails/config/queue.yml +18 -0
  187. data/sandbox/itsi_sandbox_rails/config/recurring.yml +10 -0
  188. data/sandbox/itsi_sandbox_rails/config/routes.rb +21 -0
  189. data/sandbox/itsi_sandbox_rails/config/storage.yml +34 -0
  190. data/sandbox/itsi_sandbox_rails/config.ru +7 -0
  191. data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +11 -0
  192. data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +14 -0
  193. data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +10 -0
  194. data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +129 -0
  195. data/sandbox/itsi_sandbox_rails/db/schema.rb +23 -0
  196. data/sandbox/itsi_sandbox_rails/db/seeds.rb +9 -0
  197. data/sandbox/itsi_sandbox_rails/lib/tasks/.keep +0 -0
  198. data/sandbox/itsi_sandbox_rails/log/.keep +0 -0
  199. data/sandbox/itsi_sandbox_rails/public/400.html +114 -0
  200. data/sandbox/itsi_sandbox_rails/public/404.html +114 -0
  201. data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +114 -0
  202. data/sandbox/itsi_sandbox_rails/public/422.html +114 -0
  203. data/sandbox/itsi_sandbox_rails/public/500.html +114 -0
  204. data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
  205. data/sandbox/itsi_sandbox_rails/public/icon.svg +3 -0
  206. data/sandbox/itsi_sandbox_rails/public/robots.txt +1 -0
  207. data/sandbox/itsi_sandbox_rails/script/.keep +0 -0
  208. data/sandbox/itsi_sandbox_rails/storage/.keep +0 -0
  209. data/sandbox/itsi_sandbox_rails/test/application_system_test_case.rb +5 -0
  210. data/sandbox/itsi_sandbox_rails/test/controllers/.keep +0 -0
  211. data/sandbox/itsi_sandbox_rails/test/fixtures/files/.keep +0 -0
  212. data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +9 -0
  213. data/sandbox/itsi_sandbox_rails/test/helpers/.keep +0 -0
  214. data/sandbox/itsi_sandbox_rails/test/integration/.keep +0 -0
  215. data/sandbox/itsi_sandbox_rails/test/mailers/.keep +0 -0
  216. data/sandbox/itsi_sandbox_rails/test/models/.keep +0 -0
  217. data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +7 -0
  218. data/sandbox/itsi_sandbox_rails/test/system/.keep +0 -0
  219. data/sandbox/itsi_sandbox_rails/test/test_helper.rb +15 -0
  220. data/sandbox/itsi_sandbox_rails/tmp/.keep +0 -0
  221. data/sandbox/itsi_sandbox_rails/tmp/pids/.keep +0 -0
  222. data/sandbox/itsi_sandbox_rails/tmp/storage/.keep +0 -0
  223. data/sandbox/itsi_sandbox_rails/vendor/.keep +0 -0
  224. data/sandbox/itsi_sandbox_rails/vendor/javascript/.keep +0 -0
  225. data/sandbox/itsi_sandbox_roda/Gemfile +5 -0
  226. data/sandbox/itsi_sandbox_roda/Gemfile.lock +44 -0
  227. data/sandbox/itsi_sandbox_roda/config.ru +39 -0
  228. data/sandbox/itsi_sinatra/Gemfile +9 -0
  229. data/sandbox/itsi_sinatra/Gemfile.lock +81 -0
  230. data/sandbox/itsi_sinatra/app.rb +9 -0
  231. data/sandbox/pebble/docker-compose.yml +11 -0
  232. data/tasks.txt +10 -4
  233. metadata +196 -12
  234. data/crates/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -13
  235. data/crates/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -5
  236. data/gems/scheduler/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -13
  237. data/gems/scheduler/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -5
  238. data/gems/server/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -13
  239. data/gems/server/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -5
@@ -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,8 +40,8 @@ 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"
46
46
  async-trait = "0.1.87"
47
+ dirs = "6.0.0"
@@ -0,0 +1,43 @@
1
+ use std::{
2
+ env::{var, VarError},
3
+ path::PathBuf,
4
+ sync::LazyLock,
5
+ };
6
+
7
+ type StringVar = LazyLock<String>;
8
+ type MaybeStringVar = LazyLock<Result<String, VarError>>;
9
+ type PathVar = LazyLock<PathBuf>;
10
+
11
+ /// ACME Configuration for auto-generating production certificates
12
+ /// *ITSI_ACME_CACHE_DIR* - Directory to store cached certificates
13
+ /// so that these are not regenerated every time the server starts
14
+ pub static ITSI_ACME_CACHE_DIR: StringVar = LazyLock::new(|| {
15
+ var("ITSI_ACME_CACHE_DIR").unwrap_or_else(|_| "./.rustls_acme_cache".to_string())
16
+ });
17
+
18
+ /// *ITSI_ACME_CONTACT_EMAIL* - Contact Email address to provide to ACME server during certificate renewal
19
+ pub static ITSI_ACME_CONTACT_EMAIL: MaybeStringVar =
20
+ LazyLock::new(|| var("ITSI_ACME_CONTACT_EMAIL"));
21
+
22
+ /// *ITSI_ACME_CA_PEM_PATH* - Optional CA Pem path, used for testing with non-trusted CAs for certifcate generation.
23
+ pub static ITSI_ACME_CA_PEM_PATH: MaybeStringVar = LazyLock::new(|| var("ITSI_ACME_CA_PEM_PATH"));
24
+
25
+ /// *ITSI_ACME_DIRECTORY_URL* - Directory URL to use for ACME certificate generation.
26
+ pub static ITSI_ACME_DIRECTORY_URL: StringVar = LazyLock::new(|| {
27
+ var("ITSI_ACME_DIRECTORY_URL")
28
+ .unwrap_or_else(|_| "https://acme-v02.api.letsencrypt.org/directory".to_string())
29
+ });
30
+
31
+ /// *ITSI_ACME_LOCK_FILE_NAME* - Name of the lock file used to prevent concurrent certificate generation.
32
+ pub static ITSI_ACME_LOCK_FILE_NAME: StringVar =
33
+ LazyLock::new(|| var("ITSI_ACME_LOCK_FILE_NAME").unwrap_or(".acme.lock".to_string()));
34
+
35
+ pub static ITSI_LOCAL_CA_DIR: PathVar = LazyLock::new(|| {
36
+ var("ITSI_LOCAL_CA_DIR")
37
+ .map(PathBuf::from)
38
+ .unwrap_or_else(|_| {
39
+ dirs::home_dir()
40
+ .expect("Failed to find HOME directory when initializing ITSI_LOCAL_CA_DIR")
41
+ .join(".itsi")
42
+ })
43
+ });
@@ -6,6 +6,7 @@ use server::{itsi_server::Server, signal::reset_signal_handlers};
6
6
  use tracing::*;
7
7
 
8
8
  pub mod body_proxy;
9
+ pub mod env;
9
10
  pub mod request;
10
11
  pub mod response;
11
12
  pub mod server;
@@ -6,7 +6,7 @@ use crate::{
6
6
  response::itsi_response::ItsiResponse,
7
7
  server::{
8
8
  itsi_server::{RequestJob, Server},
9
- listener::{SockAddr, TokioListener},
9
+ listener::{ListenerInfo, SockAddr},
10
10
  serve_strategy::single_mode::RunningPhase,
11
11
  },
12
12
  };
@@ -44,7 +44,7 @@ pub struct ItsiRequest {
44
44
  pub remote_addr: String,
45
45
  pub version: String,
46
46
  #[debug(skip)]
47
- pub(crate) listener: Arc<TokioListener>,
47
+ pub(crate) listener: Arc<ListenerInfo>,
48
48
  #[debug(skip)]
49
49
  pub server: Arc<Server>,
50
50
  pub response: ItsiResponse,
@@ -128,7 +128,7 @@ impl ItsiRequest {
128
128
  hyper_request: Request<Incoming>,
129
129
  sender: async_channel::Sender<RequestJob>,
130
130
  server: Arc<Server>,
131
- listener: Arc<TokioListener>,
131
+ listener: Arc<ListenerInfo>,
132
132
  addr: SockAddr,
133
133
  shutdown_rx: watch::Receiver<RunningPhase>,
134
134
  ) -> itsi_error::Result<Response<BoxBody<Bytes, Infallible>>> {
@@ -153,7 +153,7 @@ impl ItsiRequest {
153
153
  request: Request<Incoming>,
154
154
  sock_addr: SockAddr,
155
155
  server: Arc<Server>,
156
- listener: Arc<TokioListener>,
156
+ listener: Arc<ListenerInfo>,
157
157
  ) -> (ItsiRequest, mpsc::Receiver<Option<Bytes>>) {
158
158
  let (parts, body) = request.into_parts();
159
159
  let body = if server.stream_body.is_some_and(|f| f) {
@@ -231,7 +231,7 @@ impl ItsiRequest {
231
231
  .uri
232
232
  .host()
233
233
  .map(|host| host.to_string())
234
- .unwrap_or_else(|| self.listener.host()))
234
+ .unwrap_or_else(|| self.listener.host.clone()))
235
235
  }
236
236
 
237
237
  pub(crate) fn scheme(&self) -> MagnusResult<String> {
@@ -240,7 +240,7 @@ impl ItsiRequest {
240
240
  .uri
241
241
  .scheme()
242
242
  .map(|scheme| scheme.to_string())
243
- .unwrap_or_else(|| self.listener.scheme()))
243
+ .unwrap_or_else(|| self.listener.scheme.clone()))
244
244
  }
245
245
 
246
246
  pub(crate) fn headers(&self) -> MagnusResult<Vec<(String, &str)>> {
@@ -264,7 +264,7 @@ impl ItsiRequest {
264
264
  }
265
265
 
266
266
  pub(crate) fn port(&self) -> MagnusResult<u16> {
267
- Ok(self.parts.uri.port_u16().unwrap_or(self.listener.port()))
267
+ Ok(self.parts.uri.port_u16().unwrap_or(self.listener.port))
268
268
  }
269
269
 
270
270
  pub(crate) fn body(&self) -> MagnusResult<Value> {
@@ -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
 
@@ -19,7 +19,7 @@ use parking_lot::Mutex;
19
19
  use std::{cmp::max, ops::Deref, sync::Arc};
20
20
  use tracing::{info, instrument};
21
21
 
22
- static DEFAULT_BIND: &str = "localhost:3000";
22
+ static DEFAULT_BIND: &str = "http://localhost:3000";
23
23
 
24
24
  #[magnus::wrap(class = "Itsi::Server", free_immediately, size)]
25
25
  #[derive(Clone)]
@@ -231,13 +231,6 @@ impl Server {
231
231
  drop(strategy);
232
232
  Ok(())
233
233
  })?;
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
234
  clear_signal_handlers();
242
235
  Ok(())
243
236
  }
@@ -1,6 +1,7 @@
1
1
  use super::bind::{Bind, BindAddress};
2
2
  use super::bind_protocol::BindProtocol;
3
3
  use super::io_stream::IoStream;
4
+ use super::serve_strategy::single_mode::RunningPhase;
4
5
  use super::tls::ItsiTlsAcceptor;
5
6
  use itsi_error::{ItsiError, Result};
6
7
  use itsi_tracing::info;
@@ -11,6 +12,7 @@ use std::{os::unix::net::UnixListener, path::PathBuf};
11
12
  use tokio::net::TcpListener as TokioTcpListener;
12
13
  use tokio::net::UnixListener as TokioUnixListener;
13
14
  use tokio::net::{unix, TcpStream, UnixStream};
15
+ use tokio::sync::watch::Receiver;
14
16
  use tokio_rustls::TlsAcceptor;
15
17
  use tokio_stream::StreamExt;
16
18
  use tracing::error;
@@ -23,45 +25,79 @@ pub(crate) enum Listener {
23
25
  }
24
26
 
25
27
  pub(crate) enum TokioListener {
26
- Tcp {
27
- listener: TokioTcpListener,
28
- host: String,
29
- port: u16,
30
- },
31
- TcpTls {
32
- listener: TokioTcpListener,
33
- acceptor: ItsiTlsAcceptor,
34
- host: String,
35
- port: u16,
36
- },
37
- Unix {
38
- listener: TokioUnixListener,
39
- },
40
- UnixTls {
41
- listener: TokioUnixListener,
42
- acceptor: ItsiTlsAcceptor,
43
- },
28
+ Tcp(TokioTcpListener),
29
+ TcpTls(TokioTcpListener, ItsiTlsAcceptor),
30
+ Unix(TokioUnixListener),
31
+ UnixTls(TokioUnixListener, ItsiTlsAcceptor),
32
+ }
33
+
34
+ #[derive(Debug, Clone)]
35
+ pub struct ListenerInfo {
36
+ pub host: String,
37
+ pub port: u16,
38
+ pub scheme: String,
44
39
  }
45
40
 
46
41
  impl TokioListener {
47
- pub fn unbind(self) {
42
+ pub fn listener_info(&self) -> ListenerInfo {
48
43
  match self {
49
- TokioListener::Tcp { listener, .. } => drop(listener.into_std().unwrap()),
50
- TokioListener::TcpTls { listener, .. } => drop(listener.into_std().unwrap()),
51
- TokioListener::Unix { listener } => drop(listener.into_std().unwrap()),
52
- TokioListener::UnixTls { listener, .. } => drop(listener.into_std().unwrap()),
53
- };
44
+ TokioListener::Tcp(listener) => ListenerInfo {
45
+ host: listener
46
+ .local_addr()
47
+ .unwrap()
48
+ .ip()
49
+ .to_canonical()
50
+ .to_string(),
51
+ port: listener.local_addr().unwrap().port(),
52
+ scheme: "http".to_string(),
53
+ },
54
+ TokioListener::TcpTls(listener, _) => ListenerInfo {
55
+ host: listener
56
+ .local_addr()
57
+ .unwrap()
58
+ .ip()
59
+ .to_canonical()
60
+ .to_string(),
61
+ port: listener.local_addr().unwrap().port(),
62
+ scheme: "https".to_string(),
63
+ },
64
+ TokioListener::Unix(listener) => ListenerInfo {
65
+ host: listener
66
+ .local_addr()
67
+ .unwrap()
68
+ .as_pathname()
69
+ .unwrap()
70
+ .to_str()
71
+ .unwrap()
72
+ .to_owned(),
73
+ port: 0,
74
+ scheme: "unix".to_string(),
75
+ },
76
+ TokioListener::UnixTls(listener, _) => ListenerInfo {
77
+ host: listener
78
+ .local_addr()
79
+ .unwrap()
80
+ .as_pathname()
81
+ .unwrap()
82
+ .to_str()
83
+ .unwrap()
84
+ .to_owned(),
85
+ port: 0,
86
+ scheme: "ssl".to_string(),
87
+ },
88
+ }
54
89
  }
90
+
55
91
  pub(crate) async fn accept(&self) -> Result<IoStream> {
56
92
  match self {
57
- TokioListener::Tcp { listener, .. } => TokioListener::accept_tcp(listener).await,
58
- TokioListener::TcpTls {
59
- listener, acceptor, ..
60
- } => TokioListener::accept_tls(listener, acceptor).await,
61
- TokioListener::Unix { listener, .. } => TokioListener::accept_unix(listener).await,
62
- TokioListener::UnixTls {
63
- listener, acceptor, ..
64
- } => TokioListener::accept_unix_tls(listener, acceptor).await,
93
+ TokioListener::Tcp(listener) => TokioListener::accept_tcp(listener).await,
94
+ TokioListener::TcpTls(listener, acceptor) => {
95
+ TokioListener::accept_tls(listener, acceptor).await
96
+ }
97
+ TokioListener::Unix(listener) => TokioListener::accept_unix(listener).await,
98
+ TokioListener::UnixTls(listener, acceptor) => {
99
+ TokioListener::accept_unix_tls(listener, acceptor).await
100
+ }
65
101
  }
66
102
  }
67
103
 
@@ -70,17 +106,24 @@ impl TokioListener {
70
106
  Self::to_tokio_io(Stream::TcpStream(tcp_stream), None).await
71
107
  }
72
108
 
73
- pub async fn spawn_state_task(&self) {
74
- if let TokioListener::TcpTls {
75
- acceptor: ItsiTlsAcceptor::Automatic(_acme_acceptor, state, _server_config),
76
- ..
77
- } = self
109
+ pub async fn spawn_state_task(&self, mut shutdown_receiver: Receiver<RunningPhase>) {
110
+ if let TokioListener::TcpTls(
111
+ _,
112
+ ItsiTlsAcceptor::Automatic(_acme_acceptor, state, _server_config),
113
+ ) = self
78
114
  {
79
115
  let mut state = state.lock().await;
80
116
  loop {
81
- match StreamExt::next(&mut *state).await {
82
- Some(event) => info!("Received acme event: {:?}", event),
83
- None => error!("Received no acme event"),
117
+ tokio::select! {
118
+ stream_event = StreamExt::next(&mut *state) => {
119
+ match stream_event {
120
+ Some(event) => info!("Received acme event: {:?}", event),
121
+ None => error!("Received no acme event"),
122
+ }
123
+ },
124
+ _ = shutdown_receiver.changed() => {
125
+ break;
126
+ }
84
127
  }
85
128
  }
86
129
  }
@@ -175,33 +218,6 @@ impl TokioListener {
175
218
  },
176
219
  }
177
220
  }
178
-
179
- pub(crate) fn scheme(&self) -> String {
180
- match self {
181
- TokioListener::Tcp { .. } => "http".to_string(),
182
- TokioListener::TcpTls { .. } => "https".to_string(),
183
- TokioListener::Unix { .. } => "http".to_string(),
184
- TokioListener::UnixTls { .. } => "https".to_string(),
185
- }
186
- }
187
-
188
- pub(crate) fn port(&self) -> u16 {
189
- match self {
190
- TokioListener::Tcp { port, .. } => *port,
191
- TokioListener::TcpTls { port, .. } => *port,
192
- TokioListener::Unix { .. } => 0,
193
- TokioListener::UnixTls { .. } => 0,
194
- }
195
- }
196
-
197
- pub(crate) fn host(&self) -> String {
198
- match self {
199
- TokioListener::Tcp { host, .. } => host.to_string(),
200
- TokioListener::TcpTls { host, .. } => host.to_string(),
201
- TokioListener::Unix { .. } => "unix".to_string(),
202
- TokioListener::UnixTls { .. } => "unix".to_string(),
203
- }
204
- }
205
221
  }
206
222
 
207
223
  enum Stream {
@@ -227,48 +243,22 @@ impl std::fmt::Display for SockAddr {
227
243
  }
228
244
 
229
245
  impl Listener {
230
- pub fn unbind(self) {
231
- match self {
232
- Listener::Tcp(listener) => drop(listener),
233
- Listener::TcpTls((listener, _)) => drop(listener),
234
- Listener::Unix(listener) => drop(listener),
235
- Listener::UnixTls((listener, _)) => drop(listener),
236
- };
237
- }
238
246
  pub fn to_tokio_listener(&self) -> TokioListener {
239
247
  match self {
240
- Listener::Tcp(listener) => TokioListener::Tcp {
241
- listener: TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap())
242
- .unwrap(),
243
- host: listener
244
- .local_addr()
245
- .unwrap()
246
- .ip()
247
- .to_canonical()
248
- .to_string(),
249
- port: listener.local_addr().unwrap().port(),
250
- },
251
- Listener::TcpTls((listener, acceptor)) => TokioListener::TcpTls {
252
- listener: TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap())
253
- .unwrap(),
254
- acceptor: acceptor.clone(),
255
- host: listener
256
- .local_addr()
257
- .unwrap()
258
- .ip()
259
- .to_canonical()
260
- .to_string(),
261
- port: listener.local_addr().unwrap().port(),
262
- },
263
- Listener::Unix(listener) => TokioListener::Unix {
264
- listener: TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap())
265
- .unwrap(),
266
- },
267
- Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls {
268
- listener: TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap())
269
- .unwrap(),
270
- acceptor: acceptor.clone(),
271
- },
248
+ Listener::Tcp(listener) => TokioListener::Tcp(
249
+ TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap()).unwrap(),
250
+ ),
251
+ Listener::TcpTls((listener, acceptor)) => TokioListener::TcpTls(
252
+ TokioTcpListener::from_std(TcpListener::try_clone(listener).unwrap()).unwrap(),
253
+ acceptor.clone(),
254
+ ),
255
+ Listener::Unix(listener) => TokioListener::Unix(
256
+ TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap()).unwrap(),
257
+ ),
258
+ Listener::UnixTls((listener, acceptor)) => TokioListener::UnixTls(
259
+ TokioUnixListener::from_std(UnixListener::try_clone(listener).unwrap()).unwrap(),
260
+ acceptor.clone(),
261
+ ),
272
262
  }
273
263
  }
274
264
  }
@@ -307,6 +297,7 @@ fn connect_tcp_socket(addr: IpAddr, port: u16) -> Result<TcpListener> {
307
297
  socket.set_nonblocking(true).ok();
308
298
  socket.set_nodelay(true).ok();
309
299
  socket.set_recv_buffer_size(262_144).ok();
300
+ info!("Binding to {:?}", socket_address);
310
301
  socket.bind(&socket_address.into())?;
311
302
  socket.listen(1024)?;
312
303
  Ok(socket.into())
@@ -4,7 +4,7 @@ use crate::{
4
4
  io_stream::IoStream,
5
5
  itsi_server::{RequestJob, Server},
6
6
  lifecycle_event::LifecycleEvent,
7
- listener::{Listener, TokioListener},
7
+ listener::{Listener, ListenerInfo},
8
8
  thread_worker::{build_thread_workers, ThreadWorker},
9
9
  },
10
10
  };
@@ -87,18 +87,25 @@ impl SingleMode {
87
87
  pub fn run(self: Arc<Self>) -> Result<()> {
88
88
  let mut listener_task_set = JoinSet::new();
89
89
  let self_ref = Arc::new(self);
90
- self_ref.build_runtime().block_on(async {
90
+ let runtime = self_ref.build_runtime();
91
91
 
92
- for listener in self_ref.listeners.clone().iter() {
93
- let listener = Arc::new(listener.to_tokio_listener());
92
+ runtime.block_on(async {
93
+ let tokio_listeners = self_ref
94
+ .listeners
95
+ .iter()
96
+ .map(|list| Arc::new(list.to_tokio_listener()))
97
+ .collect::<Vec<_>>();
98
+ for listener in tokio_listeners.iter() {
94
99
  let mut lifecycle_rx = self_ref.lifecycle_channel.subscribe();
100
+ let listener_info = Arc::new(listener.listener_info());
95
101
  let self_ref = self_ref.clone();
96
102
  let listener = listener.clone();
97
103
  let (shutdown_sender, mut shutdown_receiver) = tokio::sync::watch::channel::<RunningPhase>(RunningPhase::Running);
98
104
  let listener_clone = listener.clone();
99
105
 
100
- tokio::spawn(async move {
101
- listener_clone.spawn_state_task().await;
106
+ let shutdown_receiver_clone = shutdown_receiver.clone();
107
+ listener_task_set.spawn(async move {
108
+ listener_clone.spawn_state_task(shutdown_receiver_clone).await;
102
109
  });
103
110
 
104
111
  listener_task_set.spawn(async move {
@@ -107,8 +114,11 @@ impl SingleMode {
107
114
  tokio::select! {
108
115
  accept_result = listener.accept() => match accept_result {
109
116
  Ok(accept_result) => {
110
- if let Err(e) = strategy.serve_connection(accept_result, listener.clone(), shutdown_receiver.clone()).await {
111
- error!("Error in serve_connection {:?}", e)
117
+ match strategy.serve_connection(accept_result, listener_info.clone(), shutdown_receiver.clone()).await {
118
+ Ok(_) => {
119
+ debug!("Connection accepted and served");
120
+ },
121
+ Err(e) => error!("Error in serve_connection {:?}", e)
112
122
  }
113
123
  },
114
124
  Err(e) => debug!("Listener.accept failed {:?}", e),
@@ -130,23 +140,23 @@ impl SingleMode {
130
140
  }
131
141
  }
132
142
  }
133
- if let Ok(listener) = Arc::try_unwrap(listener){
134
- listener.unbind();
135
- }
136
143
  });
137
144
 
138
145
  }
139
146
 
140
147
  while let Some(_res) = listener_task_set.join_next().await {}
148
+
141
149
  });
150
+ runtime.shutdown_timeout(Duration::from_millis(100));
142
151
 
152
+ info!("Runtime has shut down");
143
153
  Ok(())
144
154
  }
145
155
 
146
156
  pub(crate) async fn serve_connection(
147
157
  &self,
148
158
  stream: IoStream,
149
- listener: Arc<TokioListener>,
159
+ listener: Arc<ListenerInfo>,
150
160
  shutdown_channel: tokio::sync::watch::Receiver<RunningPhase>,
151
161
  ) -> Result<()> {
152
162
  let sender_clone = self.sender.clone();
@@ -1,13 +1,14 @@
1
1
  use async_trait::async_trait;
2
2
  use fs2::FileExt;
3
3
  use parking_lot::Mutex;
4
- use std::env;
5
4
  use std::fs::{self, OpenOptions};
6
5
  use std::io::Error as IoError;
7
6
  use std::path::{Path, PathBuf};
8
7
  use tokio_rustls_acme::caches::DirCache;
9
8
  use tokio_rustls_acme::{AccountCache, CertCache};
10
9
 
10
+ use crate::env::ITSI_ACME_LOCK_FILE_NAME;
11
+
11
12
  /// A wrapper around DirCache that locks a file before writing cert/account data.
12
13
  pub struct LockedDirCache<P: AsRef<Path> + Send + Sync> {
13
14
  inner: DirCache<P>,
@@ -19,8 +20,7 @@ impl<P: AsRef<Path> + Send + Sync> LockedDirCache<P> {
19
20
  pub fn new(dir: P) -> Self {
20
21
  let dir_path = dir.as_ref().to_path_buf();
21
22
  std::fs::create_dir_all(&dir_path).unwrap();
22
- let lock_path =
23
- dir_path.join(env::var("ITSI_ACME_LOCK_FILE_NAME").unwrap_or(".acme.lock".to_string()));
23
+ let lock_path = dir_path.join(&*ITSI_ACME_LOCK_FILE_NAME);
24
24
  Self::touch_file(&lock_path).expect("Failed to create lock file");
25
25
 
26
26
  Self {