itsi 0.1.11 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (293) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1535 -45
  3. data/{sandbox/itsi_itsi_file/Itsi.rb → Itsi.rb} +19 -13
  4. data/Rakefile +8 -7
  5. data/crates/itsi_error/src/lib.rs +9 -0
  6. data/crates/itsi_rb_helpers/Cargo.toml +1 -0
  7. data/crates/itsi_rb_helpers/src/heap_value.rs +18 -0
  8. data/crates/itsi_rb_helpers/src/lib.rs +34 -7
  9. data/crates/itsi_server/Cargo.toml +69 -30
  10. data/crates/itsi_server/src/lib.rs +79 -147
  11. data/crates/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
  12. data/crates/itsi_server/src/{body_proxy/itsi_body_proxy.rs → ruby_types/itsi_body_proxy/mod.rs} +22 -3
  13. data/crates/itsi_server/src/ruby_types/itsi_grpc_request.rs +147 -0
  14. data/crates/itsi_server/src/ruby_types/itsi_grpc_response.rs +19 -0
  15. data/crates/itsi_server/src/ruby_types/itsi_grpc_stream/mod.rs +216 -0
  16. data/{gems/server/ext/itsi_server/src/request/itsi_request.rs → crates/itsi_server/src/ruby_types/itsi_http_request.rs} +101 -117
  17. data/crates/itsi_server/src/{response/itsi_response.rs → ruby_types/itsi_http_response.rs} +72 -41
  18. data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
  19. data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +355 -0
  20. data/crates/itsi_server/src/ruby_types/itsi_server.rs +82 -0
  21. data/crates/itsi_server/src/ruby_types/mod.rs +55 -0
  22. data/crates/itsi_server/src/server/bind.rs +13 -5
  23. data/crates/itsi_server/src/server/byte_frame.rs +32 -0
  24. data/crates/itsi_server/src/server/cache_store.rs +74 -0
  25. data/crates/itsi_server/src/server/itsi_service.rs +172 -0
  26. data/crates/itsi_server/src/server/lifecycle_event.rs +3 -0
  27. data/crates/itsi_server/src/server/listener.rs +102 -2
  28. data/crates/itsi_server/src/server/middleware_stack/middleware.rs +153 -0
  29. data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +47 -0
  30. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +58 -0
  31. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +82 -0
  32. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +321 -0
  33. data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +139 -0
  34. data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +300 -0
  35. data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +287 -0
  36. data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +48 -0
  37. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +127 -0
  38. data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +191 -0
  39. data/crates/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +72 -0
  40. data/crates/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +85 -0
  41. data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +195 -0
  42. data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
  43. data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +82 -0
  44. data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +216 -0
  45. data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +124 -0
  46. data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
  47. data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +43 -0
  48. data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +34 -0
  49. data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +93 -0
  50. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +162 -0
  51. data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +158 -0
  52. data/crates/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
  53. data/crates/itsi_server/src/server/middleware_stack/mod.rs +315 -0
  54. data/crates/itsi_server/src/server/mod.rs +8 -1
  55. data/crates/itsi_server/src/server/process_worker.rs +38 -12
  56. data/crates/itsi_server/src/server/rate_limiter.rs +565 -0
  57. data/crates/itsi_server/src/server/request_job.rs +11 -0
  58. data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +119 -42
  59. data/crates/itsi_server/src/server/serve_strategy/mod.rs +9 -6
  60. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +256 -111
  61. data/crates/itsi_server/src/server/signal.rs +19 -0
  62. data/crates/itsi_server/src/server/static_file_server.rs +984 -0
  63. data/crates/itsi_server/src/server/thread_worker.rs +139 -94
  64. data/crates/itsi_server/src/server/types.rs +43 -0
  65. data/crates/itsi_server/test.md +14 -0
  66. data/crates/itsi_tracing/Cargo.toml +1 -0
  67. data/crates/itsi_tracing/src/lib.rs +216 -45
  68. data/docs/.gitignore +7 -0
  69. data/docs/.gitpod.yml +15 -0
  70. data/docs/Itsi.rb +17 -0
  71. data/docs/content/_index.md +17 -0
  72. data/docs/content/about.md +6 -0
  73. data/docs/content/docs/_index.md +18 -0
  74. data/docs/content/docs/first-page.md +9 -0
  75. data/docs/content/docs/folder/_index.md +10 -0
  76. data/docs/content/docs/folder/leaf.md +7 -0
  77. data/docs/go.mod +5 -0
  78. data/docs/go.sum +2 -0
  79. data/docs/hugo.yaml +77 -0
  80. data/examples/static_assets_example.rb +83 -0
  81. data/gems/_index.md +18 -0
  82. data/gems/scheduler/CODE_OF_CONDUCT.md +7 -0
  83. data/gems/scheduler/Cargo.lock +75 -14
  84. data/gems/scheduler/README.md +5 -0
  85. data/gems/scheduler/_index.md +7 -0
  86. data/gems/scheduler/itsi-scheduler.gemspec +4 -1
  87. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  88. data/gems/scheduler/lib/itsi/scheduler.rb +2 -2
  89. data/gems/scheduler/test/test_file_io.rb +0 -1
  90. data/gems/scheduler/test/test_itsi_scheduler.rb +1 -1
  91. data/gems/server/CHANGELOG.md +5 -0
  92. data/gems/server/CODE_OF_CONDUCT.md +7 -0
  93. data/gems/server/Cargo.lock +1536 -45
  94. data/gems/server/README.md +4 -0
  95. data/gems/server/_index.md +6 -0
  96. data/gems/server/exe/itsi +33 -74
  97. data/gems/server/itsi-server.gemspec +3 -2
  98. data/gems/server/lib/itsi/{request.rb → http_request.rb} +29 -5
  99. data/gems/server/lib/itsi/http_response.rb +39 -0
  100. data/gems/server/lib/itsi/server/Itsi.rb +11 -19
  101. data/gems/server/lib/itsi/server/config/dsl.rb +506 -0
  102. data/gems/server/lib/itsi/server/config.rb +103 -8
  103. data/gems/server/lib/itsi/server/default_app/default_app.rb +38 -0
  104. data/gems/server/lib/itsi/server/grpc_interface.rb +213 -0
  105. data/gems/server/lib/itsi/server/rack/handler/itsi.rb +8 -17
  106. data/gems/server/lib/itsi/server/rack_interface.rb +23 -4
  107. data/gems/server/lib/itsi/server/scheduler_interface.rb +1 -1
  108. data/gems/server/lib/itsi/server/scheduler_mode.rb +4 -0
  109. data/gems/server/lib/itsi/server/signal_trap.rb +7 -1
  110. data/gems/server/lib/itsi/server/version.rb +1 -1
  111. data/gems/server/lib/itsi/server.rb +74 -63
  112. data/gems/server/lib/itsi/standard_headers.rb +86 -0
  113. data/gems/server/test/helpers/test_helper.rb +12 -12
  114. data/gems/server/test/test_itsi_server.rb +2 -2
  115. data/lib/itsi/version.rb +1 -1
  116. data/sandbox/itsi_file/Gemfile +11 -0
  117. data/sandbox/itsi_file/Gemfile.lock +69 -0
  118. data/sandbox/itsi_file/Itsi.rb +276 -0
  119. data/sandbox/itsi_file/error.html +2 -0
  120. data/sandbox/itsi_file/organisations_controller.rb +20 -0
  121. data/sandbox/itsi_file/public/assets/image.png +0 -0
  122. data/sandbox/itsi_file/public/assets/index.html +1 -0
  123. data/sandbox/itsi_sandbox_hanami/Gemfile.lock +2 -2
  124. data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
  125. data/sandbox/itsi_sandbox_rack/config.ru +2 -15
  126. data/sandbox/itsi_sandbox_rails/.dockerignore +2 -5
  127. data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +1 -1
  128. data/sandbox/itsi_sandbox_rails/.gitignore +2 -1
  129. data/sandbox/itsi_sandbox_rails/Dockerfile +6 -9
  130. data/sandbox/itsi_sandbox_rails/Gemfile +16 -22
  131. data/sandbox/itsi_sandbox_rails/Gemfile.lock +100 -225
  132. data/sandbox/itsi_sandbox_rails/app/assets/config/manifest.js +4 -0
  133. data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +11 -6
  134. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/channel.rb +4 -0
  135. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/connection.rb +4 -0
  136. data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +7 -8
  137. data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +0 -3
  138. data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +2 -7
  139. data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +3 -4
  140. data/sandbox/itsi_sandbox_rails/bin/setup +8 -5
  141. data/sandbox/itsi_sandbox_rails/config/application.rb +1 -35
  142. data/sandbox/itsi_sandbox_rails/config/cable.yml +3 -10
  143. data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -1
  144. data/sandbox/itsi_sandbox_rails/config/database.yml +9 -19
  145. data/sandbox/itsi_sandbox_rails/config/environment.rb +1 -1
  146. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +21 -12
  147. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +49 -34
  148. data/sandbox/itsi_sandbox_rails/config/environments/test.rb +19 -5
  149. data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +5 -0
  150. data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +1 -1
  151. data/sandbox/itsi_sandbox_rails/config/initializers/permissions_policy.rb +13 -0
  152. data/sandbox/itsi_sandbox_rails/config/puma.rb +2 -9
  153. data/sandbox/itsi_sandbox_rails/config.ru +0 -1
  154. data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +1 -1
  155. data/sandbox/itsi_sandbox_rails/db/schema.rb +2 -2
  156. data/sandbox/itsi_sandbox_rails/lib/assets/.keep +0 -0
  157. data/sandbox/itsi_sandbox_rails/public/404.html +66 -113
  158. data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +65 -113
  159. data/sandbox/itsi_sandbox_rails/public/422.html +66 -113
  160. data/sandbox/itsi_sandbox_rails/public/500.html +65 -113
  161. data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
  162. data/sandbox/itsi_sandbox_rails/public/icon.svg +2 -2
  163. data/sandbox/itsi_sandbox_rails/test/channels/application_cable/connection_test.rb +13 -0
  164. data/sandbox/itsi_sandbox_roda/Gemfile.lock +3 -10
  165. data/tasks.txt +72 -35
  166. metadata +89 -139
  167. data/crates/itsi_server/src/body_proxy/mod.rs +0 -2
  168. data/crates/itsi_server/src/request/itsi_request.rs +0 -298
  169. data/crates/itsi_server/src/request/mod.rs +0 -1
  170. data/crates/itsi_server/src/response/mod.rs +0 -1
  171. data/crates/itsi_server/src/server/itsi_server.rs +0 -288
  172. data/gems/scheduler/ext/itsi_error/Cargo.lock +0 -368
  173. data/gems/scheduler/ext/itsi_error/Cargo.toml +0 -11
  174. data/gems/scheduler/ext/itsi_error/src/from.rs +0 -68
  175. data/gems/scheduler/ext/itsi_error/src/lib.rs +0 -24
  176. data/gems/scheduler/ext/itsi_instrument_entry/Cargo.toml +0 -15
  177. data/gems/scheduler/ext/itsi_instrument_entry/src/lib.rs +0 -31
  178. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.lock +0 -355
  179. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.toml +0 -10
  180. data/gems/scheduler/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  181. data/gems/scheduler/ext/itsi_rb_helpers/src/lib.rs +0 -201
  182. data/gems/scheduler/ext/itsi_scheduler/Cargo.toml +0 -24
  183. data/gems/scheduler/ext/itsi_scheduler/extconf.rb +0 -6
  184. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  185. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  186. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  187. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  188. data/gems/scheduler/ext/itsi_scheduler/src/lib.rs +0 -38
  189. data/gems/scheduler/ext/itsi_server/Cargo.lock +0 -2956
  190. data/gems/scheduler/ext/itsi_server/Cargo.toml +0 -50
  191. data/gems/scheduler/ext/itsi_server/extconf.rb +0 -6
  192. data/gems/scheduler/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  193. data/gems/scheduler/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  194. data/gems/scheduler/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  195. data/gems/scheduler/ext/itsi_server/src/env.rs +0 -43
  196. data/gems/scheduler/ext/itsi_server/src/lib.rs +0 -180
  197. data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +0 -298
  198. data/gems/scheduler/ext/itsi_server/src/request/mod.rs +0 -1
  199. data/gems/scheduler/ext/itsi_server/src/response/itsi_response.rs +0 -357
  200. data/gems/scheduler/ext/itsi_server/src/response/mod.rs +0 -1
  201. data/gems/scheduler/ext/itsi_server/src/server/bind.rs +0 -174
  202. data/gems/scheduler/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  203. data/gems/scheduler/ext/itsi_server/src/server/io_stream.rs +0 -104
  204. data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +0 -288
  205. data/gems/scheduler/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  206. data/gems/scheduler/ext/itsi_server/src/server/listener.rs +0 -318
  207. data/gems/scheduler/ext/itsi_server/src/server/mod.rs +0 -11
  208. data/gems/scheduler/ext/itsi_server/src/server/process_worker.rs +0 -203
  209. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -260
  210. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  211. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -276
  212. data/gems/scheduler/ext/itsi_server/src/server/signal.rs +0 -74
  213. data/gems/scheduler/ext/itsi_server/src/server/thread_worker.rs +0 -399
  214. data/gems/scheduler/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  215. data/gems/scheduler/ext/itsi_server/src/server/tls.rs +0 -265
  216. data/gems/scheduler/ext/itsi_tracing/Cargo.lock +0 -274
  217. data/gems/scheduler/ext/itsi_tracing/Cargo.toml +0 -16
  218. data/gems/scheduler/ext/itsi_tracing/src/lib.rs +0 -58
  219. data/gems/server/ext/itsi_error/Cargo.lock +0 -368
  220. data/gems/server/ext/itsi_error/Cargo.toml +0 -11
  221. data/gems/server/ext/itsi_error/src/from.rs +0 -68
  222. data/gems/server/ext/itsi_error/src/lib.rs +0 -24
  223. data/gems/server/ext/itsi_instrument_entry/Cargo.toml +0 -15
  224. data/gems/server/ext/itsi_instrument_entry/src/lib.rs +0 -31
  225. data/gems/server/ext/itsi_rb_helpers/Cargo.lock +0 -355
  226. data/gems/server/ext/itsi_rb_helpers/Cargo.toml +0 -10
  227. data/gems/server/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  228. data/gems/server/ext/itsi_rb_helpers/src/lib.rs +0 -201
  229. data/gems/server/ext/itsi_scheduler/Cargo.toml +0 -24
  230. data/gems/server/ext/itsi_scheduler/extconf.rb +0 -6
  231. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  232. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  233. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  234. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  235. data/gems/server/ext/itsi_scheduler/src/lib.rs +0 -38
  236. data/gems/server/ext/itsi_server/Cargo.lock +0 -2956
  237. data/gems/server/ext/itsi_server/Cargo.toml +0 -50
  238. data/gems/server/ext/itsi_server/extconf.rb +0 -6
  239. data/gems/server/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  240. data/gems/server/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  241. data/gems/server/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  242. data/gems/server/ext/itsi_server/src/env.rs +0 -43
  243. data/gems/server/ext/itsi_server/src/lib.rs +0 -180
  244. data/gems/server/ext/itsi_server/src/request/mod.rs +0 -1
  245. data/gems/server/ext/itsi_server/src/response/itsi_response.rs +0 -357
  246. data/gems/server/ext/itsi_server/src/response/mod.rs +0 -1
  247. data/gems/server/ext/itsi_server/src/server/bind.rs +0 -174
  248. data/gems/server/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  249. data/gems/server/ext/itsi_server/src/server/io_stream.rs +0 -104
  250. data/gems/server/ext/itsi_server/src/server/itsi_server.rs +0 -288
  251. data/gems/server/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  252. data/gems/server/ext/itsi_server/src/server/listener.rs +0 -318
  253. data/gems/server/ext/itsi_server/src/server/mod.rs +0 -11
  254. data/gems/server/ext/itsi_server/src/server/process_worker.rs +0 -203
  255. data/gems/server/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -260
  256. data/gems/server/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  257. data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -276
  258. data/gems/server/ext/itsi_server/src/server/signal.rs +0 -74
  259. data/gems/server/ext/itsi_server/src/server/thread_worker.rs +0 -399
  260. data/gems/server/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  261. data/gems/server/ext/itsi_server/src/server/tls.rs +0 -265
  262. data/gems/server/ext/itsi_tracing/Cargo.lock +0 -274
  263. data/gems/server/ext/itsi_tracing/Cargo.toml +0 -16
  264. data/gems/server/ext/itsi_tracing/src/lib.rs +0 -58
  265. data/gems/server/lib/itsi/server/options_dsl.rb +0 -401
  266. data/gems/server/lib/itsi/stream_io.rb +0 -38
  267. data/location_dsl.rb +0 -381
  268. data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +0 -3
  269. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +0 -3
  270. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +0 -14
  271. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +0 -3
  272. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +0 -3
  273. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +0 -51
  274. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +0 -47
  275. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +0 -109
  276. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +0 -3
  277. data/sandbox/itsi_sandbox_rails/.kamal/secrets +0 -17
  278. data/sandbox/itsi_sandbox_rails/bin/dev +0 -2
  279. data/sandbox/itsi_sandbox_rails/bin/jobs +0 -6
  280. data/sandbox/itsi_sandbox_rails/bin/kamal +0 -27
  281. data/sandbox/itsi_sandbox_rails/bin/thrust +0 -5
  282. data/sandbox/itsi_sandbox_rails/config/cache.yml +0 -16
  283. data/sandbox/itsi_sandbox_rails/config/deploy.yml +0 -116
  284. data/sandbox/itsi_sandbox_rails/config/queue.yml +0 -18
  285. data/sandbox/itsi_sandbox_rails/config/recurring.yml +0 -10
  286. data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +0 -11
  287. data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +0 -14
  288. data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +0 -129
  289. data/sandbox/itsi_sandbox_rails/public/400.html +0 -114
  290. data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +0 -9
  291. data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +0 -7
  292. /data/{sandbox/itsi_sandbox_rails/script/.keep → crates/_index.md} +0 -0
  293. /data/gems/server/lib/itsi/{index.html → server/default_app/index.html} +0 -0
@@ -0,0 +1,315 @@
1
+ mod middleware;
2
+ mod middlewares;
3
+ use super::types::HttpRequest;
4
+ use http::header::{ACCEPT, CONTENT_TYPE, HOST};
5
+ use itsi_rb_helpers::HeapVal;
6
+ use magnus::{error::Result, value::ReprValue, RArray, RHash, Ruby, TryConvert, Value};
7
+ pub use middleware::Middleware;
8
+ pub use middlewares::*;
9
+ use regex::{Regex, RegexSet};
10
+ use std::{collections::HashMap, sync::Arc};
11
+ use tracing::info;
12
+
13
+ #[derive(Debug)]
14
+ pub struct MiddlewareSet {
15
+ pub route_set: RegexSet,
16
+ pub patterns: Vec<Arc<Regex>>,
17
+ pub stacks: HashMap<usize, MiddlewareStack>,
18
+ pub default_stack: Vec<Middleware>,
19
+ }
20
+
21
+ #[derive(Debug)]
22
+ pub struct MiddlewareStack {
23
+ layers: Vec<Middleware>,
24
+ methods: Option<Vec<StringMatch>>,
25
+ protocols: Option<Vec<StringMatch>>,
26
+ hosts: Option<Vec<StringMatch>>,
27
+ extensions: Option<Vec<StringMatch>>,
28
+ ports: Option<Vec<StringMatch>>,
29
+ content_types: Option<Vec<StringMatch>>,
30
+ accepts: Option<Vec<StringMatch>>,
31
+ }
32
+
33
+ #[derive(Debug)]
34
+ enum StringMatch {
35
+ Exact(String),
36
+ Wildcard(Regex),
37
+ }
38
+
39
+ impl StringMatch {
40
+ fn from_value(value: Value) -> Result<Self> {
41
+ let ruby = Ruby::get().unwrap();
42
+ if value.is_kind_of(ruby.class_regexp()) {
43
+ let src_str = value.funcall::<_, _, String>("source", ())?;
44
+ let regex = Regex::new(&src_str).map_err(|e| {
45
+ magnus::Error::new(
46
+ magnus::exception::exception(),
47
+ format!("Invalid regexp: {}", e),
48
+ )
49
+ })?;
50
+ Ok(StringMatch::Wildcard(regex))
51
+ } else {
52
+ Ok(StringMatch::Exact(value.to_string()))
53
+ }
54
+ }
55
+
56
+ fn matches(&self, value: &str) -> bool {
57
+ match self {
58
+ StringMatch::Exact(s) => s.eq_ignore_ascii_case(value),
59
+ StringMatch::Wildcard(re) => re.is_match(value),
60
+ }
61
+ }
62
+ }
63
+
64
+ impl MiddlewareStack {
65
+ pub fn matches(&self, request: &HttpRequest) -> bool {
66
+ if let Some(methods) = &self.methods {
67
+ let method = request.method().as_str();
68
+ if !methods.iter().any(|m| m.matches(method)) {
69
+ return false;
70
+ }
71
+ }
72
+
73
+ if let (Some(protocols), Some(protocol)) = (&self.protocols, request.uri().scheme()) {
74
+ if !protocols.iter().any(|p| p.matches(protocol.as_str())) {
75
+ return false;
76
+ }
77
+ }
78
+
79
+ if let (Some(hosts), Some(host)) = (&self.hosts, request.headers().get(HOST)) {
80
+ if let Ok(host) = host.to_str() {
81
+ if !hosts.iter().any(|d| d.matches(host)) {
82
+ return false;
83
+ }
84
+ }
85
+ }
86
+
87
+ if let (Some(ports), Some(port)) = (&self.ports, request.uri().port()) {
88
+ if !ports.iter().any(|d| d.matches(port.as_str())) {
89
+ info!("No match between port {} and {:?}", port, ports);
90
+ return false;
91
+ }
92
+ }
93
+
94
+ if let Some(extensions) = &self.extensions {
95
+ let extension = request.uri().path().split('.').next_back().unwrap_or("");
96
+ if !extensions.iter().any(|e| e.matches(extension)) {
97
+ return false;
98
+ }
99
+ }
100
+
101
+ if let Some(content_types) = &self.content_types {
102
+ if let Some(content_type) = request.headers().get(CONTENT_TYPE) {
103
+ if !content_types
104
+ .iter()
105
+ .any(|ct| ct.matches(content_type.to_str().unwrap_or("")))
106
+ {
107
+ return false;
108
+ }
109
+ }
110
+ }
111
+
112
+ if let Some(accepts) = &self.accepts {
113
+ if let Some(accept) = request.headers().get(ACCEPT) {
114
+ if !accepts
115
+ .iter()
116
+ .any(|a| a.matches(accept.to_str().unwrap_or("")))
117
+ {
118
+ return false;
119
+ }
120
+ }
121
+ }
122
+
123
+ true
124
+ }
125
+ }
126
+
127
+ impl MiddlewareSet {
128
+ pub fn new(routes_raw: Option<HeapVal>, default_app: HeapVal) -> Result<Self> {
129
+ if let Some(routes_raw) = routes_raw {
130
+ let mut stacks = HashMap::new();
131
+ let mut routes = vec![];
132
+ for (index, route) in RArray::from_value(*routes_raw)
133
+ .ok_or(magnus::Error::new(
134
+ magnus::exception::exception(),
135
+ format!("Routes must be an array. Got {:?}", routes_raw),
136
+ ))?
137
+ .into_iter()
138
+ .enumerate()
139
+ {
140
+ let route_hash: RHash = RHash::try_convert(route)?;
141
+ let route_raw = route_hash
142
+ .get("route")
143
+ .ok_or(magnus::Error::new(
144
+ magnus::exception::exception(),
145
+ "Route is missing :route key",
146
+ ))?
147
+ .funcall::<_, _, String>("source", ())?;
148
+ let middleware =
149
+ RArray::from_value(route_hash.get("middleware").ok_or(magnus::Error::new(
150
+ magnus::exception::exception(),
151
+ "Route is missing middleware key",
152
+ ))?)
153
+ .ok_or(magnus::Error::new(
154
+ magnus::exception::exception(),
155
+ format!("middleware must be an array. Got {:?}", routes_raw),
156
+ ))?;
157
+
158
+ let mut layers = middleware
159
+ .into_iter()
160
+ .map(MiddlewareSet::parse_middleware)
161
+ .collect::<Result<Vec<_>>>()?;
162
+ layers.push(Middleware::RubyApp(RubyApp::from_value(
163
+ default_app.clone(),
164
+ )?));
165
+ routes.push(route_raw);
166
+ layers.sort();
167
+ stacks.insert(
168
+ index,
169
+ MiddlewareStack {
170
+ layers,
171
+ methods: extract_optional_match_array(route_hash, "methods")?,
172
+ protocols: extract_optional_match_array(route_hash, "protocols")?,
173
+ hosts: extract_optional_match_array(route_hash, "hosts")?,
174
+ extensions: extract_optional_match_array(route_hash, "extensions")?,
175
+ ports: extract_optional_match_array(route_hash, "ports")?,
176
+ content_types: extract_optional_match_array(route_hash, "content_types")?,
177
+ accepts: extract_optional_match_array(route_hash, "accepts")?,
178
+ },
179
+ );
180
+ }
181
+ info!("Routes are {:?}", routes);
182
+ Ok(Self {
183
+ route_set: RegexSet::new(&routes).map_err(|e| {
184
+ magnus::Error::new(
185
+ magnus::exception::exception(),
186
+ format!("Failed to create route set: {}", e),
187
+ )
188
+ })?,
189
+ patterns: routes
190
+ .into_iter()
191
+ .map(|r| Regex::new(&r))
192
+ .collect::<std::result::Result<Vec<Regex>, regex::Error>>()
193
+ .map_err(|e| {
194
+ magnus::Error::new(
195
+ magnus::exception::exception(),
196
+ format!("Failed to create route set: {}", e),
197
+ )
198
+ })?
199
+ .into_iter()
200
+ .map(Arc::new)
201
+ .collect(),
202
+ stacks,
203
+ default_stack: vec![Middleware::RubyApp(RubyApp::from_value(default_app)?)],
204
+ })
205
+ } else {
206
+ Ok(Self {
207
+ route_set: RegexSet::empty(),
208
+ patterns: Vec::new(),
209
+ stacks: HashMap::new(),
210
+ default_stack: vec![Middleware::RubyApp(RubyApp::from_value(default_app)?)],
211
+ })
212
+ }
213
+ }
214
+
215
+ pub fn stack_for(&self, request: &HttpRequest) -> (&Vec<Middleware>, Option<Arc<Regex>>) {
216
+ let binding = self.route_set.matches(request.uri().path());
217
+ let matches = binding.iter();
218
+ for index in matches {
219
+ let matching_pattern = self.patterns.get(index).cloned();
220
+ if let Some(stack) = self.stacks.get(&index) {
221
+ if stack.matches(request) {
222
+ return (&stack.layers, matching_pattern);
223
+ }
224
+ }
225
+ }
226
+ (self.default_stack(), None)
227
+ }
228
+
229
+ pub fn parse_middleware(middleware: Value) -> Result<Middleware> {
230
+ let middleware_hash = RHash::from_value(middleware).ok_or(magnus::Error::new(
231
+ magnus::exception::exception(),
232
+ format!("Filter must be a hash. Got {:?}", middleware),
233
+ ))?;
234
+ let middleware_type: String = middleware_hash
235
+ .get("type")
236
+ .ok_or(magnus::Error::new(
237
+ magnus::exception::exception(),
238
+ format!("Filter must have a :type key. Got {:?}", middleware_hash),
239
+ ))?
240
+ .to_string();
241
+
242
+ let parameters: Value = middleware_hash.get("parameters").ok_or(magnus::Error::new(
243
+ magnus::exception::exception(),
244
+ format!(
245
+ "Filter must have a :parameters key. Got {:?}",
246
+ middleware_hash
247
+ ),
248
+ ))?;
249
+
250
+ let result = match middleware_type.as_str() {
251
+ "allow_list" => Middleware::AllowList(AllowList::from_value(parameters)?),
252
+ "auth_basic" => Middleware::AuthBasic(AuthBasic::from_value(parameters)?),
253
+ "auth_jwt" => Middleware::AuthJwt(Box::new(AuthJwt::from_value(parameters)?)),
254
+ "auth_api_key" => Middleware::AuthAPIKey(AuthAPIKey::from_value(parameters)?),
255
+ "cache_control" => Middleware::CacheControl(CacheControl::from_value(parameters)?),
256
+ "deny_list" => Middleware::DenyList(DenyList::from_value(parameters)?),
257
+ "etag" => Middleware::ETag(ETag::from_value(parameters)?),
258
+ "intrusion_protection" => {
259
+ Middleware::IntrusionProtection(IntrusionProtection::from_value(parameters)?)
260
+ }
261
+ "rate_limit" => Middleware::RateLimit(RateLimit::from_value(parameters)?),
262
+ "cors" => Middleware::Cors(Box::new(Cors::from_value(parameters)?)),
263
+ "request_headers" => {
264
+ Middleware::RequestHeaders(RequestHeaders::from_value(parameters)?)
265
+ }
266
+ "response_headers" => {
267
+ Middleware::ResponseHeaders(ResponseHeaders::from_value(parameters)?)
268
+ }
269
+ "static_assets" => Middleware::StaticAssets(StaticAssets::from_value(parameters)?),
270
+ "compression" => Middleware::Compression(Compression::from_value(parameters)?),
271
+ "log_requests" => Middleware::LogRequests(LogRequests::from_value(parameters)?),
272
+ "redirect" => Middleware::Redirect(Redirect::from_value(parameters)?),
273
+ "app" => Middleware::RubyApp(RubyApp::from_value(parameters.into())?),
274
+ "proxy" => Middleware::Proxy(Proxy::from_value(parameters)?),
275
+ _ => {
276
+ return Err(magnus::Error::new(
277
+ magnus::exception::exception(),
278
+ format!("Unknown filter type: {}", middleware_type),
279
+ ))
280
+ }
281
+ };
282
+
283
+ Ok(result)
284
+ }
285
+
286
+ fn default_stack(&self) -> &Vec<Middleware> {
287
+ &self.default_stack
288
+ }
289
+
290
+ pub async fn initialize_layers(&self) -> Result<()> {
291
+ for middleware in &self.default_stack {
292
+ middleware.initialize().await?;
293
+ }
294
+ for stack in self.stacks.values() {
295
+ for middleware in &stack.layers {
296
+ middleware.initialize().await?;
297
+ }
298
+ }
299
+ Ok(())
300
+ }
301
+ }
302
+
303
+ fn extract_optional_match_array(route_hash: RHash, arg: &str) -> Result<Option<Vec<StringMatch>>> {
304
+ let rarray = route_hash.aref::<_, Option<RArray>>(arg)?;
305
+ if let Some(array) = rarray {
306
+ Ok(Some(
307
+ array
308
+ .into_iter()
309
+ .map(StringMatch::from_value)
310
+ .collect::<Result<Vec<StringMatch>>>()?,
311
+ ))
312
+ } else {
313
+ Ok(None)
314
+ }
315
+ }
@@ -1,11 +1,18 @@
1
1
  pub mod bind;
2
2
  pub mod bind_protocol;
3
+ pub mod byte_frame;
4
+ pub mod cache_store;
3
5
  pub mod io_stream;
4
- pub mod itsi_server;
6
+ pub mod itsi_service;
5
7
  pub mod lifecycle_event;
6
8
  pub mod listener;
9
+ pub mod middleware_stack;
7
10
  pub mod process_worker;
11
+ pub mod rate_limiter;
12
+ pub mod request_job;
8
13
  pub mod serve_strategy;
9
14
  pub mod signal;
15
+ pub mod static_file_server;
10
16
  pub mod thread_worker;
11
17
  pub mod tls;
18
+ pub mod types;
@@ -7,7 +7,7 @@ use nix::{
7
7
  sys::{
8
8
  signal::{
9
9
  kill,
10
- Signal::{SIGKILL, SIGTERM},
10
+ Signal::{SIGINFO, SIGKILL, SIGTERM},
11
11
  },
12
12
  wait::{waitpid, WaitPidFlag, WaitStatus},
13
13
  },
@@ -53,8 +53,18 @@ impl ProcessWorker {
53
53
  }
54
54
  *self.child_pid.lock() = None;
55
55
  }
56
- match call_with_gvl(|_ruby| fork(cluster_template.server.hooks.get("after_fork").cloned()))
57
- {
56
+
57
+ match call_with_gvl(|_ruby| {
58
+ fork(
59
+ cluster_template
60
+ .server_config
61
+ .server_params
62
+ .read()
63
+ .hooks
64
+ .get("after_fork")
65
+ .cloned(),
66
+ )
67
+ }) {
58
68
  Some(pid) => {
59
69
  *self.child_pid.lock() = Some(Pid::from_raw(pid));
60
70
  }
@@ -65,11 +75,7 @@ impl ProcessWorker {
65
75
  ) {
66
76
  error!("Failed to set process group ID: {}", e);
67
77
  }
68
- match SingleMode::new(
69
- cluster_template.server.clone(),
70
- cluster_template.listeners.lock().drain(..).collect(),
71
- cluster_template.lifecycle_channel.clone(),
72
- ) {
78
+ match SingleMode::new(cluster_template.server_config.clone()) {
73
79
  Ok(single_mode) => {
74
80
  Arc::new(single_mode).run().ok();
75
81
  }
@@ -129,8 +135,14 @@ impl ProcessWorker {
129
135
  pub(crate) async fn graceful_shutdown(&self, cluster_template: Arc<ClusterMode>) {
130
136
  let self_clone = self.clone();
131
137
  self_clone.request_shutdown();
132
- let force_kill_time =
133
- Instant::now() + Duration::from_secs_f64(cluster_template.server.shutdown_timeout);
138
+ let force_kill_time = Instant::now()
139
+ + Duration::from_secs_f64(
140
+ cluster_template
141
+ .server_config
142
+ .server_params
143
+ .read()
144
+ .shutdown_timeout,
145
+ );
134
146
  while self_clone.is_alive() && force_kill_time > Instant::now() {
135
147
  tokio::time::sleep(Duration::from_millis(100)).await;
136
148
  }
@@ -171,10 +183,24 @@ impl ProcessWorker {
171
183
  pub(crate) fn force_kill(&self) {
172
184
  let child_pid = *self.child_pid.lock();
173
185
  if let Some(pid) = child_pid {
174
- if let Err(e) = kill(pid, SIGKILL) {
175
- error!("Failed to force kill process {}: {}", pid, e);
186
+ if self.is_alive() {
187
+ if let Err(e) = kill(pid, SIGKILL) {
188
+ error!("Failed to force kill process {}: {}", pid, e);
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ pub fn print_info(&self) -> Result<()> {
195
+ let child_pid = *self.child_pid.lock();
196
+ if let Some(pid) = child_pid {
197
+ println!("Worker {:?}, PID: {:?}", self.worker_id, pid);
198
+ if let Err(e) = kill(pid, SIGINFO) {
199
+ error!("Failed to send SIGINFO to process {}: {}", pid, e);
176
200
  }
177
201
  }
202
+
203
+ Ok(())
178
204
  }
179
205
 
180
206
  pub(crate) fn just_started(&self) -> bool {