itsi 0.1.14 → 0.1.18

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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +124 -109
  3. data/Cargo.toml +6 -0
  4. data/crates/itsi_error/Cargo.toml +1 -0
  5. data/crates/itsi_error/src/lib.rs +100 -10
  6. data/crates/itsi_scheduler/src/itsi_scheduler.rs +1 -1
  7. data/crates/itsi_server/Cargo.toml +8 -10
  8. data/crates/itsi_server/src/default_responses/html/401.html +68 -0
  9. data/crates/itsi_server/src/default_responses/html/403.html +68 -0
  10. data/crates/itsi_server/src/default_responses/html/404.html +68 -0
  11. data/crates/itsi_server/src/default_responses/html/413.html +71 -0
  12. data/crates/itsi_server/src/default_responses/html/429.html +68 -0
  13. data/crates/itsi_server/src/default_responses/html/500.html +71 -0
  14. data/crates/itsi_server/src/default_responses/html/502.html +71 -0
  15. data/crates/itsi_server/src/default_responses/html/503.html +68 -0
  16. data/crates/itsi_server/src/default_responses/html/504.html +69 -0
  17. data/crates/itsi_server/src/default_responses/html/index.html +238 -0
  18. data/crates/itsi_server/src/default_responses/json/401.json +6 -0
  19. data/crates/itsi_server/src/default_responses/json/403.json +6 -0
  20. data/crates/itsi_server/src/default_responses/json/404.json +6 -0
  21. data/crates/itsi_server/src/default_responses/json/413.json +6 -0
  22. data/crates/itsi_server/src/default_responses/json/429.json +6 -0
  23. data/crates/itsi_server/src/default_responses/json/500.json +6 -0
  24. data/crates/itsi_server/src/default_responses/json/502.json +6 -0
  25. data/crates/itsi_server/src/default_responses/json/503.json +6 -0
  26. data/crates/itsi_server/src/default_responses/json/504.json +6 -0
  27. data/crates/itsi_server/src/default_responses/mod.rs +11 -0
  28. data/crates/itsi_server/src/lib.rs +58 -26
  29. data/crates/itsi_server/src/prelude.rs +2 -0
  30. data/crates/itsi_server/src/ruby_types/README.md +21 -0
  31. data/crates/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +8 -6
  32. data/crates/itsi_server/src/ruby_types/itsi_grpc_call.rs +344 -0
  33. data/crates/itsi_server/src/ruby_types/{itsi_grpc_stream → itsi_grpc_response_stream}/mod.rs +121 -73
  34. data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +103 -40
  35. data/crates/itsi_server/src/ruby_types/itsi_http_response.rs +8 -5
  36. data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +4 -4
  37. data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +37 -17
  38. data/crates/itsi_server/src/ruby_types/itsi_server.rs +4 -3
  39. data/crates/itsi_server/src/ruby_types/mod.rs +6 -13
  40. data/crates/itsi_server/src/server/{bind.rs → binds/bind.rs} +23 -4
  41. data/crates/itsi_server/src/server/{listener.rs → binds/listener.rs} +24 -10
  42. data/crates/itsi_server/src/server/binds/mod.rs +4 -0
  43. data/crates/itsi_server/src/server/{tls.rs → binds/tls.rs} +9 -4
  44. data/crates/itsi_server/src/server/http_message_types.rs +97 -0
  45. data/crates/itsi_server/src/server/io_stream.rs +2 -1
  46. data/crates/itsi_server/src/server/middleware_stack/middleware.rs +28 -16
  47. data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +17 -8
  48. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +47 -18
  49. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +13 -9
  50. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +50 -29
  51. data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +5 -2
  52. data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +37 -48
  53. data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +25 -20
  54. data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +14 -7
  55. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +190 -0
  56. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +125 -95
  57. data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +9 -5
  58. data/crates/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +1 -4
  59. data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +25 -19
  60. data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +4 -4
  61. data/crates/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
  62. data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +9 -4
  63. data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +260 -62
  64. data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +29 -22
  65. data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +6 -6
  66. data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +6 -5
  67. data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +4 -2
  68. data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +51 -18
  69. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +31 -13
  70. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +55 -0
  71. data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +13 -8
  72. data/crates/itsi_server/src/server/middleware_stack/mod.rs +101 -69
  73. data/crates/itsi_server/src/server/mod.rs +3 -9
  74. data/crates/itsi_server/src/server/process_worker.rs +21 -3
  75. data/crates/itsi_server/src/server/request_job.rs +2 -2
  76. data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +8 -3
  77. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +26 -26
  78. data/crates/itsi_server/src/server/signal.rs +24 -41
  79. data/crates/itsi_server/src/server/size_limited_incoming.rs +101 -0
  80. data/crates/itsi_server/src/server/thread_worker.rs +59 -28
  81. data/crates/itsi_server/src/services/itsi_http_service.rs +239 -0
  82. data/crates/itsi_server/src/services/mime_types.rs +1416 -0
  83. data/crates/itsi_server/src/services/mod.rs +6 -0
  84. data/crates/itsi_server/src/services/password_hasher.rs +83 -0
  85. data/crates/itsi_server/src/{server → services}/rate_limiter.rs +35 -31
  86. data/crates/itsi_server/src/{server → services}/static_file_server.rs +521 -181
  87. data/crates/itsi_tracing/src/lib.rs +145 -55
  88. data/{Itsi.rb → foo/Itsi.rb} +6 -9
  89. data/gems/scheduler/Cargo.lock +7 -0
  90. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  91. data/gems/scheduler/test/helpers/test_helper.rb +0 -1
  92. data/gems/scheduler/test/test_address_resolve.rb +0 -1
  93. data/gems/scheduler/test/test_network_io.rb +1 -1
  94. data/gems/scheduler/test/test_process_wait.rb +0 -1
  95. data/gems/server/Cargo.lock +124 -109
  96. data/gems/server/exe/itsi +65 -19
  97. data/gems/server/itsi-server.gemspec +4 -3
  98. data/gems/server/lib/itsi/http_request/response_status_shortcodes.rb +74 -0
  99. data/gems/server/lib/itsi/http_request.rb +116 -17
  100. data/gems/server/lib/itsi/http_response.rb +2 -0
  101. data/gems/server/lib/itsi/passfile.rb +109 -0
  102. data/gems/server/lib/itsi/server/config/dsl.rb +160 -101
  103. data/gems/server/lib/itsi/server/config.rb +58 -23
  104. data/gems/server/lib/itsi/server/default_app/default_app.rb +25 -29
  105. data/gems/server/lib/itsi/server/default_app/index.html +113 -89
  106. data/gems/server/lib/itsi/server/{Itsi.rb → default_config/Itsi-rackup.rb} +1 -1
  107. data/gems/server/lib/itsi/server/default_config/Itsi.rb +107 -0
  108. data/gems/server/lib/itsi/server/grpc/grpc_call.rb +246 -0
  109. data/gems/server/lib/itsi/server/grpc/grpc_interface.rb +100 -0
  110. data/gems/server/lib/itsi/server/grpc/reflection/v1/reflection_pb.rb +26 -0
  111. data/gems/server/lib/itsi/server/grpc/reflection/v1/reflection_services_pb.rb +122 -0
  112. data/gems/server/lib/itsi/server/route_tester.rb +107 -0
  113. data/gems/server/lib/itsi/server/typed_handlers/param_parser.rb +200 -0
  114. data/gems/server/lib/itsi/server/typed_handlers/source_parser.rb +55 -0
  115. data/gems/server/lib/itsi/server/typed_handlers.rb +17 -0
  116. data/gems/server/lib/itsi/server/version.rb +1 -1
  117. data/gems/server/lib/itsi/server.rb +82 -12
  118. data/gems/server/lib/ruby_lsp/itsi/addon.rb +111 -0
  119. data/gems/server/lib/shell_completions/completions.rb +26 -0
  120. data/gems/server/test/helpers/test_helper.rb +2 -1
  121. data/lib/itsi/version.rb +1 -1
  122. data/sandbox/README.md +5 -0
  123. data/sandbox/itsi_file/Gemfile +4 -2
  124. data/sandbox/itsi_file/Gemfile.lock +48 -6
  125. data/sandbox/itsi_file/Itsi.rb +326 -129
  126. data/sandbox/itsi_file/call.json +1 -0
  127. data/sandbox/itsi_file/echo_client/Gemfile +10 -0
  128. data/sandbox/itsi_file/echo_client/Gemfile.lock +27 -0
  129. data/sandbox/itsi_file/echo_client/README.md +95 -0
  130. data/sandbox/itsi_file/echo_client/echo_client.rb +164 -0
  131. data/sandbox/itsi_file/echo_client/gen_proto.sh +17 -0
  132. data/sandbox/itsi_file/echo_client/lib/echo_pb.rb +16 -0
  133. data/sandbox/itsi_file/echo_client/lib/echo_services_pb.rb +29 -0
  134. data/sandbox/itsi_file/echo_client/run_client.rb +64 -0
  135. data/sandbox/itsi_file/echo_client/test_compressions.sh +20 -0
  136. data/sandbox/itsi_file/echo_service_nonitsi/Gemfile +10 -0
  137. data/sandbox/itsi_file/echo_service_nonitsi/Gemfile.lock +79 -0
  138. data/sandbox/itsi_file/echo_service_nonitsi/echo.proto +26 -0
  139. data/sandbox/itsi_file/echo_service_nonitsi/echo_pb.rb +16 -0
  140. data/sandbox/itsi_file/echo_service_nonitsi/echo_services_pb.rb +29 -0
  141. data/sandbox/itsi_file/echo_service_nonitsi/server.rb +52 -0
  142. data/sandbox/itsi_sandbox_async/config.ru +0 -1
  143. data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
  144. data/sandbox/itsi_sandbox_rails/Gemfile +2 -2
  145. data/sandbox/itsi_sandbox_rails/Gemfile.lock +76 -2
  146. data/sandbox/itsi_sandbox_rails/app/controllers/home_controller.rb +15 -0
  147. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +1 -0
  148. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +1 -0
  149. data/sandbox/itsi_sandbox_rails/config/routes.rb +2 -0
  150. data/sandbox/itsi_sinatra/app.rb +0 -1
  151. data/sandbox/static_files/.env +1 -0
  152. data/sandbox/static_files/404.html +25 -0
  153. data/sandbox/static_files/_DSC0102.NEF.jpg +0 -0
  154. data/sandbox/static_files/about.html +68 -0
  155. data/sandbox/static_files/tiny.html +1 -0
  156. data/sandbox/static_files/writebook.zip +0 -0
  157. data/tasks.txt +28 -33
  158. metadata +87 -26
  159. data/crates/itsi_error/src/from.rs +0 -68
  160. data/crates/itsi_server/src/ruby_types/itsi_grpc_request.rs +0 -147
  161. data/crates/itsi_server/src/ruby_types/itsi_grpc_response.rs +0 -19
  162. data/crates/itsi_server/src/server/itsi_service.rs +0 -172
  163. data/crates/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +0 -72
  164. data/crates/itsi_server/src/server/types.rs +0 -43
  165. data/gems/server/lib/itsi/server/grpc_interface.rb +0 -213
  166. data/sandbox/itsi_file/public/assets/index.html +0 -1
  167. /data/crates/itsi_server/src/server/{bind_protocol.rs → binds/bind_protocol.rs} +0 -0
  168. /data/crates/itsi_server/src/server/{tls → binds/tls}/locked_dir_cache.rs +0 -0
  169. /data/crates/itsi_server/src/{server → services}/cache_store.rs +0 -0
@@ -5,15 +5,34 @@ use std::{
5
5
  };
6
6
  pub use tracing::{debug, error, info, trace, warn};
7
7
  use tracing_appender::rolling;
8
- use tracing_subscriber::Layer;
9
8
  use tracing_subscriber::fmt::writer::BoxMakeWriter;
10
9
  use tracing_subscriber::{EnvFilter, fmt, prelude::*, reload};
10
+ use tracing_subscriber::{Layer, Registry, layer::Layered};
11
11
 
12
12
  // Global reload handle for changing the level at runtime.
13
13
  static RELOAD_HANDLE: OnceLock<
14
14
  Mutex<Option<reload::Handle<EnvFilter, tracing_subscriber::Registry>>>,
15
15
  > = OnceLock::new();
16
16
 
17
+ // Global reload handle for changing the formatting layer (log target/format) at runtime.
18
+ type ReloadFmtHandle = reload::Handle<
19
+ Box<
20
+ dyn Layer<
21
+ tracing_subscriber::layer::Layered<
22
+ reload::Layer<EnvFilter, tracing_subscriber::Registry>,
23
+ tracing_subscriber::Registry,
24
+ >,
25
+ > + Send
26
+ + Sync,
27
+ >,
28
+ Layered<tracing_subscriber::reload::Layer<EnvFilter, Registry>, Registry>,
29
+ >;
30
+
31
+ static RELOAD_FMT_HANDLE: OnceLock<Mutex<Option<ReloadFmtHandle>>> = OnceLock::new();
32
+
33
+ // Global current log configuration for formatting options.
34
+ static CURRENT_CONFIG: OnceLock<Mutex<LogConfig>> = OnceLock::new();
35
+
17
36
  /// Log format: Plain or JSON.
18
37
  #[derive(Debug, Clone)]
19
38
  pub enum LogFormat {
@@ -73,18 +92,19 @@ impl Default for LogConfig {
73
92
  }
74
93
  }
75
94
 
76
- /// Initialize the global tracing subscriber with the default configuration.
77
- pub fn init() {
78
- init_with_config(LogConfig::default());
79
- }
80
-
81
- /// Initialize the global tracing subscriber with a given configuration.
82
- pub fn init_with_config(config: LogConfig) {
83
- // Build an EnvFilter from the configured level.
84
- let env_filter = EnvFilter::new(config.level);
85
-
86
- // Build the formatting layer based on target and format.
87
- let fmt_layer = match config.target {
95
+ /// Build the formatting layer based on the provided configuration.
96
+ fn build_fmt_layer(
97
+ config: &LogConfig,
98
+ ) -> Box<
99
+ dyn Layer<
100
+ tracing_subscriber::layer::Layered<
101
+ reload::Layer<EnvFilter, tracing_subscriber::Registry>,
102
+ tracing_subscriber::Registry,
103
+ >,
104
+ > + Send
105
+ + Sync,
106
+ > {
107
+ match &config.target {
88
108
  LogTarget::Stdout => match config.format {
89
109
  LogFormat::Plain => fmt::layer()
90
110
  .compact()
@@ -106,35 +126,39 @@ pub fn init_with_config(config: LogConfig) {
106
126
  .json()
107
127
  .boxed(),
108
128
  },
109
- LogTarget::File(file) => match config.format {
110
- LogFormat::Plain => fmt::layer()
111
- .compact()
112
- .with_file(false)
113
- .with_line_number(false)
114
- .with_target(false)
115
- .with_thread_ids(false)
116
- .with_writer(BoxMakeWriter::new({
117
- let file = file.clone();
118
- move || rolling::daily(".", file.clone())
119
- }))
120
- .with_ansi(false)
121
- .boxed(),
122
- LogFormat::Json => fmt::layer()
123
- .compact()
124
- .with_file(false)
125
- .with_line_number(false)
126
- .with_target(false)
127
- .with_thread_ids(false)
128
- .with_writer(BoxMakeWriter::new({
129
- let file = file.clone();
130
- move || rolling::daily(".", file.clone())
131
- }))
132
- .with_ansi(false)
133
- .json()
134
- .boxed(),
135
- },
129
+ LogTarget::File(file) => {
130
+ let file_clone = file.clone();
131
+ match config.format {
132
+ LogFormat::Plain => fmt::layer()
133
+ .compact()
134
+ .with_file(false)
135
+ .with_line_number(false)
136
+ .with_target(false)
137
+ .with_thread_ids(false)
138
+ .with_writer(BoxMakeWriter::new(move || {
139
+ rolling::daily(".", file_clone.clone())
140
+ }))
141
+ .with_ansi(false)
142
+ .boxed(),
143
+ LogFormat::Json => {
144
+ let file_clone = file.clone();
145
+ fmt::layer()
146
+ .compact()
147
+ .with_file(false)
148
+ .with_line_number(false)
149
+ .with_target(false)
150
+ .with_thread_ids(false)
151
+ .with_writer(BoxMakeWriter::new(move || {
152
+ rolling::daily(".", file_clone.clone())
153
+ }))
154
+ .with_ansi(false)
155
+ .json()
156
+ .boxed()
157
+ }
158
+ }
159
+ }
136
160
  LogTarget::Both(file) => {
137
- // For "Both" target, handle each format separately to avoid type mismatches
161
+ let file_clone = file.clone();
138
162
  match config.format {
139
163
  LogFormat::Plain => {
140
164
  let stdout_layer = fmt::layer()
@@ -145,19 +169,16 @@ pub fn init_with_config(config: LogConfig) {
145
169
  .with_thread_ids(false)
146
170
  .with_writer(BoxMakeWriter::new(std::io::stdout))
147
171
  .with_ansi(config.use_ansi);
148
-
149
172
  let file_layer = fmt::layer()
150
173
  .compact()
151
174
  .with_file(false)
152
175
  .with_line_number(false)
153
176
  .with_target(false)
154
177
  .with_thread_ids(false)
155
- .with_writer(BoxMakeWriter::new({
156
- let file = file.clone();
157
- move || rolling::daily(".", file.clone())
178
+ .with_writer(BoxMakeWriter::new(move || {
179
+ rolling::daily(".", file_clone.clone())
158
180
  }))
159
181
  .with_ansi(false);
160
-
161
182
  stdout_layer.and_then(file_layer).boxed()
162
183
  }
163
184
  LogFormat::Json => {
@@ -170,30 +191,61 @@ pub fn init_with_config(config: LogConfig) {
170
191
  .with_writer(BoxMakeWriter::new(std::io::stdout))
171
192
  .with_ansi(config.use_ansi)
172
193
  .json();
173
-
174
194
  let file_layer = fmt::layer()
175
195
  .compact()
176
196
  .with_file(false)
177
197
  .with_line_number(false)
178
198
  .with_target(false)
179
199
  .with_thread_ids(false)
180
- .with_writer(BoxMakeWriter::new({
181
- let file = file.clone();
182
- move || rolling::daily(".", file.clone())
200
+ .with_writer(BoxMakeWriter::new(move || {
201
+ rolling::daily(".", file_clone.clone())
183
202
  }))
184
203
  .with_ansi(false)
185
204
  .json();
186
-
187
205
  stdout_layer.and_then(file_layer).boxed()
188
206
  }
189
207
  }
190
208
  }
191
- };
209
+ }
210
+ }
211
+
212
+ /// Update the formatting layer using the current configuration.
213
+ fn update_fmt_layer(config: &LogConfig) {
214
+ if let Some(handle) = RELOAD_FMT_HANDLE.get().unwrap().lock().unwrap().as_ref() {
215
+ let new_layer = build_fmt_layer(config);
216
+ handle
217
+ .modify(|layer| {
218
+ *layer = new_layer;
219
+ })
220
+ .expect("Failed to update formatting layer");
221
+ } else {
222
+ eprintln!("Reload handle for formatting layer not initialized; call init() first.");
223
+ }
224
+ }
225
+
226
+ /// Initialize the global tracing subscriber with the default configuration.
227
+ pub fn init() {
228
+ init_with_config(LogConfig::default());
229
+ }
230
+
231
+ /// Initialize the global tracing subscriber with a given configuration.
232
+ pub fn init_with_config(config: LogConfig) {
233
+ // Store the current config in a global for future updates.
234
+ CURRENT_CONFIG.set(Mutex::new(config.clone())).ok();
235
+
236
+ // Build an EnvFilter from the configured level.
237
+ let env_filter = EnvFilter::new(config.clone().level);
238
+
239
+ // Build the formatting layer based on the configuration.
240
+ let fmt_layer = build_fmt_layer(&config);
192
241
 
193
242
  // Create a reloadable filter layer so we can update the level at runtime.
194
- let (filter_layer, handle) = reload::Layer::new(env_filter);
243
+ let (filter_layer, filter_handle) = reload::Layer::new(env_filter);
244
+
245
+ // Create a reloadable formatting layer so we can update the target/format at runtime.
246
+ let (fmt_layer, fmt_handle) = reload::Layer::new(fmt_layer);
195
247
 
196
- // Build the subscriber registry
248
+ // Build the subscriber registry.
197
249
  let subscriber = tracing_subscriber::registry()
198
250
  .with(filter_layer)
199
251
  .with(fmt_layer);
@@ -201,7 +253,8 @@ pub fn init_with_config(config: LogConfig) {
201
253
  tracing::subscriber::set_global_default(subscriber)
202
254
  .expect("Unable to set global tracing subscriber");
203
255
 
204
- RELOAD_HANDLE.set(Mutex::new(Some(handle))).unwrap();
256
+ RELOAD_HANDLE.set(Mutex::new(Some(filter_handle))).unwrap();
257
+ RELOAD_FMT_HANDLE.set(Mutex::new(Some(fmt_handle))).ok();
205
258
  }
206
259
 
207
260
  /// Change the log level at runtime.
@@ -210,11 +263,48 @@ pub fn set_level(new_level: &str) {
210
263
  handle
211
264
  .modify(|filter| *filter = EnvFilter::new(new_level))
212
265
  .expect("Failed to update log level");
266
+
267
+ // Also update the stored config.
268
+ if let Some(config_mutex) = CURRENT_CONFIG.get() {
269
+ let mut config = config_mutex.lock().unwrap();
270
+ config.level = new_level.to_string();
271
+ }
213
272
  } else {
214
273
  eprintln!("Reload handle not initialized; call init() first.");
215
274
  }
216
275
  }
217
276
 
277
+ /// Change the log target at runtime.
278
+ pub fn set_target(new_target: &str) {
279
+ let target: LogTarget = match new_target {
280
+ "stdout" => LogTarget::Stdout,
281
+ path => LogTarget::File(path.to_string()),
282
+ };
283
+ if let Some(config_mutex) = CURRENT_CONFIG.get() {
284
+ let mut config = config_mutex.lock().unwrap();
285
+ config.target = target;
286
+ update_fmt_layer(&config);
287
+ } else {
288
+ eprintln!("Current configuration not initialized; call init() first.");
289
+ }
290
+ }
291
+
292
+ /// Change the log format at runtime.
293
+ pub fn set_format(new_format: &str) {
294
+ let format = match new_format {
295
+ "json" => LogFormat::Json,
296
+ "plain" => LogFormat::Plain,
297
+ _ => LogFormat::Json,
298
+ };
299
+ if let Some(config_mutex) = CURRENT_CONFIG.get() {
300
+ let mut config = config_mutex.lock().unwrap();
301
+ config.format = format;
302
+ update_fmt_layer(&config);
303
+ } else {
304
+ eprintln!("Current configuration not initialized; call init() first.");
305
+ }
306
+ }
307
+
218
308
  /// Run a function silently by temporarily setting a no-op subscriber.
219
309
  pub fn run_silently<F, R>(f: F) -> R
220
310
  where
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # This is the default Itsi configuration file, installed when you run `itsi init`
3
4
  # It contains a sane starting point for configuring your Itsi server.
4
5
  # You can use this file in both development and production environments.
@@ -11,14 +12,14 @@ env = ENV.fetch("APP_ENV") { ENV.fetch("RACK_ENV", "development") }
11
12
  # If more than 1, Itsi will be booted in Cluster mode
12
13
  workers ENV.fetch("ITSI_WORKERS") {
13
14
  require "etc"
14
- env == "development" ? 1 : Etc.nprocessors
15
+ env == "development" ? 1 : nil
15
16
  }
16
17
 
17
18
  # Number of threads to spawn per worker process
18
19
  # For pure CPU bound applicationss, you'll get the best results keeping this number low
19
20
  # Setting a value of 1 is great for superficial benchmarks, but in reality
20
21
  # it's better to set this a bit higher to allow expensive requests to get overtaken and minimize head-of-line blocking
21
- threads ENV.fetch("ITSI_THREADS", 1)
22
+ threads ENV.fetch("ITSI_THREADS", 3)
22
23
 
23
24
  # If your application is IO bound (e.g. performing a lot of proxied HTTP requests, or heavy queries etc)
24
25
  # you can see *substantial* benefits from enabling this option.
@@ -40,13 +41,9 @@ fiber_scheduler nil
40
41
  # end)
41
42
  # rackup_file "config.ru"
42
43
 
43
- watch "*.rb", [%w[bundle exec itsi reload]]
44
- location "/*" do
45
- get "" do |req|
46
- req.respond("Hello")
47
- end
44
+ endpoint do |req|
45
+ req.respond("Im Itsi")
48
46
  end
49
- # run ->(env) { [200, { 'content-type' => 'text/plain' }, ['OK']] }
50
47
  # If you bind to https, without specifying a certificate, Itsi will use a self-signed certificate.
51
48
  # The self-signed certificate will use a CA generated for your host and stored inside `ITSI_LOCAL_CA_DIR` (Defaults to ~/.itsi)
52
49
  # bind "https://localhost:3000"
@@ -65,7 +62,7 @@ end
65
62
  # bind "tls:///tmp/itsi.secure.sock"
66
63
 
67
64
  if env == "development"
68
- bind "http://127.0.0.1:3001"
65
+ bind "http://localhost:3000"
69
66
  else
70
67
  bind "https://0.0.0.0?domains=#{ENV["PRODUCTION_DOMAINS"]}&cert=acme&acme_email=admin@itsi.fyi"
71
68
  end
@@ -11,6 +11,12 @@ dependencies = [
11
11
  "memchr",
12
12
  ]
13
13
 
14
+ [[package]]
15
+ name = "anyhow"
16
+ version = "1.0.97"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
19
+
14
20
  [[package]]
15
21
  name = "atty"
16
22
  version = "0.2.14"
@@ -227,6 +233,7 @@ dependencies = [
227
233
  name = "itsi_error"
228
234
  version = "0.1.0"
229
235
  dependencies = [
236
+ "anyhow",
230
237
  "httparse",
231
238
  "magnus",
232
239
  "nix",
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Itsi
4
4
  class Scheduler
5
- VERSION = "0.1.14"
5
+ VERSION = "0.1.18"
6
6
  end
7
7
  end
@@ -4,7 +4,6 @@ require "minitest/reporters"
4
4
  Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
5
5
 
6
6
  require "itsi/scheduler"
7
- require 'debug'
8
7
  module Itsi::Scheduler::TestHelper
9
8
  SchedulerClass = Itsi::Scheduler
10
9
 
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'debug'
3
2
 
4
3
  class TestAddressResolve < Minitest::Test
5
4
  include Itsi::Scheduler::TestHelper
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "socket"
4
4
  require "timeout"
5
- require "debug"
5
+
6
6
 
7
7
  class TestNetworkIO < Minitest::Test
8
8
  include Itsi::Scheduler::TestHelper
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'debug'
3
2
 
4
3
 
5
4
  class TestProcessWait < Minitest::Test