itsi 0.1.9 → 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 (294) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1542 -43
  3. data/Itsi.rb +125 -0
  4. data/Rakefile +8 -4
  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 +59 -9
  9. data/crates/itsi_server/Cargo.toml +70 -28
  10. data/crates/itsi_server/src/lib.rs +80 -80
  11. data/crates/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
  12. data/{gems/server/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs → crates/itsi_server/src/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/crates/itsi_server/src/ruby_types/itsi_http_request.rs +282 -0
  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 +29 -17
  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 +111 -11
  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 +44 -11
  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 +129 -46
  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 +325 -167
  61. data/crates/itsi_server/src/server/signal.rs +20 -4
  62. data/crates/itsi_server/src/server/static_file_server.rs +984 -0
  63. data/crates/itsi_server/src/server/thread_worker.rs +165 -88
  64. data/crates/itsi_server/src/server/tls.rs +1 -1
  65. data/crates/itsi_server/src/server/types.rs +43 -0
  66. data/crates/itsi_server/test.md +14 -0
  67. data/crates/itsi_tracing/Cargo.toml +1 -0
  68. data/crates/itsi_tracing/src/lib.rs +216 -45
  69. data/docs/.gitignore +7 -0
  70. data/docs/.gitpod.yml +15 -0
  71. data/docs/Itsi.rb +17 -0
  72. data/docs/content/_index.md +17 -0
  73. data/docs/content/about.md +6 -0
  74. data/docs/content/docs/_index.md +18 -0
  75. data/docs/content/docs/first-page.md +9 -0
  76. data/docs/content/docs/folder/_index.md +10 -0
  77. data/docs/content/docs/folder/leaf.md +7 -0
  78. data/docs/go.mod +5 -0
  79. data/docs/go.sum +2 -0
  80. data/docs/hugo.yaml +77 -0
  81. data/examples/static_assets_example.rb +83 -0
  82. data/gems/_index.md +18 -0
  83. data/gems/scheduler/CODE_OF_CONDUCT.md +7 -0
  84. data/gems/scheduler/Cargo.lock +75 -14
  85. data/gems/scheduler/README.md +5 -0
  86. data/gems/scheduler/_index.md +7 -0
  87. data/gems/scheduler/itsi-scheduler.gemspec +4 -1
  88. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  89. data/gems/scheduler/lib/itsi/scheduler.rb +2 -2
  90. data/gems/scheduler/test/test_file_io.rb +0 -1
  91. data/gems/scheduler/test/test_itsi_scheduler.rb +1 -1
  92. data/gems/server/CHANGELOG.md +5 -0
  93. data/gems/server/CODE_OF_CONDUCT.md +7 -0
  94. data/gems/server/Cargo.lock +1543 -43
  95. data/gems/server/README.md +4 -0
  96. data/gems/server/_index.md +6 -0
  97. data/gems/server/exe/itsi +46 -57
  98. data/gems/server/itsi-server.gemspec +3 -2
  99. data/gems/server/lib/itsi/{request.rb → http_request.rb} +29 -5
  100. data/gems/server/lib/itsi/http_response.rb +39 -0
  101. data/gems/server/lib/itsi/server/Itsi.rb +119 -0
  102. data/gems/server/lib/itsi/server/config/dsl.rb +506 -0
  103. data/gems/server/lib/itsi/server/config.rb +131 -0
  104. data/gems/server/lib/itsi/server/default_app/default_app.rb +38 -0
  105. data/gems/server/lib/itsi/server/grpc_interface.rb +213 -0
  106. data/gems/server/lib/itsi/server/rack/handler/itsi.rb +9 -6
  107. data/gems/server/lib/itsi/server/rack_interface.rb +24 -9
  108. data/gems/server/lib/itsi/server/scheduler_interface.rb +1 -1
  109. data/gems/server/lib/itsi/server/scheduler_mode.rb +4 -0
  110. data/gems/server/lib/itsi/server/signal_trap.rb +6 -1
  111. data/gems/server/lib/itsi/server/version.rb +1 -1
  112. data/gems/server/lib/itsi/server.rb +75 -60
  113. data/gems/server/lib/itsi/standard_headers.rb +86 -0
  114. data/gems/server/test/helpers/test_helper.rb +14 -12
  115. data/gems/server/test/test_itsi_server.rb +21 -2
  116. data/lib/itsi/version.rb +1 -1
  117. data/sandbox/itsi_file/Gemfile +11 -0
  118. data/sandbox/itsi_file/Gemfile.lock +69 -0
  119. data/sandbox/itsi_file/Itsi.rb +276 -0
  120. data/sandbox/itsi_file/error.html +2 -0
  121. data/sandbox/itsi_file/organisations_controller.rb +20 -0
  122. data/sandbox/itsi_file/public/assets/image.png +0 -0
  123. data/sandbox/itsi_file/public/assets/index.html +1 -0
  124. data/sandbox/itsi_sandbox_async/Gemfile +1 -1
  125. data/sandbox/itsi_sandbox_hanami/Gemfile.lock +2 -2
  126. data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
  127. data/sandbox/itsi_sandbox_rack/config.ru +2 -15
  128. data/sandbox/itsi_sandbox_rails/.dockerignore +2 -5
  129. data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +1 -1
  130. data/sandbox/itsi_sandbox_rails/.gitignore +2 -1
  131. data/sandbox/itsi_sandbox_rails/Dockerfile +6 -9
  132. data/sandbox/itsi_sandbox_rails/Gemfile +16 -22
  133. data/sandbox/itsi_sandbox_rails/Gemfile.lock +100 -225
  134. data/sandbox/itsi_sandbox_rails/app/assets/config/manifest.js +4 -0
  135. data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +11 -6
  136. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/channel.rb +4 -0
  137. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/connection.rb +4 -0
  138. data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +7 -8
  139. data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +0 -3
  140. data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +2 -7
  141. data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +3 -4
  142. data/sandbox/itsi_sandbox_rails/bin/setup +8 -5
  143. data/sandbox/itsi_sandbox_rails/config/application.rb +1 -35
  144. data/sandbox/itsi_sandbox_rails/config/cable.yml +3 -10
  145. data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -1
  146. data/sandbox/itsi_sandbox_rails/config/database.yml +9 -19
  147. data/sandbox/itsi_sandbox_rails/config/environment.rb +1 -1
  148. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +21 -12
  149. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +49 -34
  150. data/sandbox/itsi_sandbox_rails/config/environments/test.rb +19 -5
  151. data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +5 -0
  152. data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +1 -1
  153. data/sandbox/itsi_sandbox_rails/config/initializers/permissions_policy.rb +13 -0
  154. data/sandbox/itsi_sandbox_rails/config/puma.rb +2 -9
  155. data/sandbox/itsi_sandbox_rails/config.ru +0 -1
  156. data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +1 -1
  157. data/sandbox/itsi_sandbox_rails/db/schema.rb +2 -2
  158. data/sandbox/itsi_sandbox_rails/lib/assets/.keep +0 -0
  159. data/sandbox/itsi_sandbox_rails/public/404.html +66 -113
  160. data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +65 -113
  161. data/sandbox/itsi_sandbox_rails/public/422.html +66 -113
  162. data/sandbox/itsi_sandbox_rails/public/500.html +65 -113
  163. data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
  164. data/sandbox/itsi_sandbox_rails/public/icon.svg +2 -2
  165. data/sandbox/itsi_sandbox_rails/test/channels/application_cable/connection_test.rb +13 -0
  166. data/sandbox/itsi_sandbox_roda/Gemfile.lock +3 -10
  167. data/tasks.txt +72 -12
  168. metadata +94 -139
  169. data/crates/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  170. data/crates/itsi_server/src/body_proxy/mod.rs +0 -2
  171. data/crates/itsi_server/src/request/itsi_request.rs +0 -305
  172. data/crates/itsi_server/src/request/mod.rs +0 -1
  173. data/crates/itsi_server/src/response/mod.rs +0 -1
  174. data/crates/itsi_server/src/server/itsi_server.rs +0 -294
  175. data/gems/scheduler/ext/itsi_error/Cargo.lock +0 -368
  176. data/gems/scheduler/ext/itsi_error/Cargo.toml +0 -11
  177. data/gems/scheduler/ext/itsi_error/src/from.rs +0 -68
  178. data/gems/scheduler/ext/itsi_error/src/lib.rs +0 -24
  179. data/gems/scheduler/ext/itsi_instrument_entry/Cargo.toml +0 -15
  180. data/gems/scheduler/ext/itsi_instrument_entry/src/lib.rs +0 -31
  181. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.lock +0 -355
  182. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.toml +0 -10
  183. data/gems/scheduler/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  184. data/gems/scheduler/ext/itsi_rb_helpers/src/lib.rs +0 -178
  185. data/gems/scheduler/ext/itsi_scheduler/Cargo.toml +0 -24
  186. data/gems/scheduler/ext/itsi_scheduler/extconf.rb +0 -6
  187. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  188. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  189. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  190. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  191. data/gems/scheduler/ext/itsi_scheduler/src/lib.rs +0 -38
  192. data/gems/scheduler/ext/itsi_server/Cargo.lock +0 -2956
  193. data/gems/scheduler/ext/itsi_server/Cargo.toml +0 -47
  194. data/gems/scheduler/ext/itsi_server/extconf.rb +0 -6
  195. data/gems/scheduler/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  196. data/gems/scheduler/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  197. data/gems/scheduler/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  198. data/gems/scheduler/ext/itsi_server/src/env.rs +0 -43
  199. data/gems/scheduler/ext/itsi_server/src/lib.rs +0 -112
  200. data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +0 -305
  201. data/gems/scheduler/ext/itsi_server/src/request/mod.rs +0 -1
  202. data/gems/scheduler/ext/itsi_server/src/response/itsi_response.rs +0 -357
  203. data/gems/scheduler/ext/itsi_server/src/response/mod.rs +0 -1
  204. data/gems/scheduler/ext/itsi_server/src/server/bind.rs +0 -170
  205. data/gems/scheduler/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  206. data/gems/scheduler/ext/itsi_server/src/server/io_stream.rs +0 -104
  207. data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +0 -294
  208. data/gems/scheduler/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  209. data/gems/scheduler/ext/itsi_server/src/server/listener.rs +0 -318
  210. data/gems/scheduler/ext/itsi_server/src/server/mod.rs +0 -11
  211. data/gems/scheduler/ext/itsi_server/src/server/process_worker.rs +0 -196
  212. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -254
  213. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  214. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -263
  215. data/gems/scheduler/ext/itsi_server/src/server/signal.rs +0 -77
  216. data/gems/scheduler/ext/itsi_server/src/server/thread_worker.rs +0 -367
  217. data/gems/scheduler/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  218. data/gems/scheduler/ext/itsi_server/src/server/tls.rs +0 -265
  219. data/gems/scheduler/ext/itsi_tracing/Cargo.lock +0 -274
  220. data/gems/scheduler/ext/itsi_tracing/Cargo.toml +0 -16
  221. data/gems/scheduler/ext/itsi_tracing/src/lib.rs +0 -58
  222. data/gems/server/ext/itsi_error/Cargo.lock +0 -368
  223. data/gems/server/ext/itsi_error/Cargo.toml +0 -11
  224. data/gems/server/ext/itsi_error/src/from.rs +0 -68
  225. data/gems/server/ext/itsi_error/src/lib.rs +0 -24
  226. data/gems/server/ext/itsi_instrument_entry/Cargo.toml +0 -15
  227. data/gems/server/ext/itsi_instrument_entry/src/lib.rs +0 -31
  228. data/gems/server/ext/itsi_rb_helpers/Cargo.lock +0 -355
  229. data/gems/server/ext/itsi_rb_helpers/Cargo.toml +0 -10
  230. data/gems/server/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  231. data/gems/server/ext/itsi_rb_helpers/src/lib.rs +0 -178
  232. data/gems/server/ext/itsi_scheduler/Cargo.toml +0 -24
  233. data/gems/server/ext/itsi_scheduler/extconf.rb +0 -6
  234. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  235. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  236. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  237. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  238. data/gems/server/ext/itsi_scheduler/src/lib.rs +0 -38
  239. data/gems/server/ext/itsi_server/Cargo.lock +0 -2956
  240. data/gems/server/ext/itsi_server/Cargo.toml +0 -47
  241. data/gems/server/ext/itsi_server/extconf.rb +0 -6
  242. data/gems/server/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  243. data/gems/server/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  244. data/gems/server/ext/itsi_server/src/env.rs +0 -43
  245. data/gems/server/ext/itsi_server/src/lib.rs +0 -112
  246. data/gems/server/ext/itsi_server/src/request/itsi_request.rs +0 -305
  247. data/gems/server/ext/itsi_server/src/request/mod.rs +0 -1
  248. data/gems/server/ext/itsi_server/src/response/itsi_response.rs +0 -357
  249. data/gems/server/ext/itsi_server/src/response/mod.rs +0 -1
  250. data/gems/server/ext/itsi_server/src/server/bind.rs +0 -170
  251. data/gems/server/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  252. data/gems/server/ext/itsi_server/src/server/io_stream.rs +0 -104
  253. data/gems/server/ext/itsi_server/src/server/itsi_server.rs +0 -294
  254. data/gems/server/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  255. data/gems/server/ext/itsi_server/src/server/listener.rs +0 -318
  256. data/gems/server/ext/itsi_server/src/server/mod.rs +0 -11
  257. data/gems/server/ext/itsi_server/src/server/process_worker.rs +0 -196
  258. data/gems/server/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -254
  259. data/gems/server/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  260. data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -263
  261. data/gems/server/ext/itsi_server/src/server/signal.rs +0 -77
  262. data/gems/server/ext/itsi_server/src/server/thread_worker.rs +0 -367
  263. data/gems/server/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  264. data/gems/server/ext/itsi_server/src/server/tls.rs +0 -265
  265. data/gems/server/ext/itsi_tracing/Cargo.lock +0 -274
  266. data/gems/server/ext/itsi_tracing/Cargo.toml +0 -16
  267. data/gems/server/ext/itsi_tracing/src/lib.rs +0 -58
  268. data/gems/server/lib/itsi/stream_io.rb +0 -38
  269. data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +0 -3
  270. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +0 -3
  271. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +0 -14
  272. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +0 -3
  273. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +0 -3
  274. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +0 -51
  275. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +0 -47
  276. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +0 -109
  277. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +0 -3
  278. data/sandbox/itsi_sandbox_rails/.kamal/secrets +0 -17
  279. data/sandbox/itsi_sandbox_rails/bin/dev +0 -2
  280. data/sandbox/itsi_sandbox_rails/bin/jobs +0 -6
  281. data/sandbox/itsi_sandbox_rails/bin/kamal +0 -27
  282. data/sandbox/itsi_sandbox_rails/bin/thrust +0 -5
  283. data/sandbox/itsi_sandbox_rails/config/cache.yml +0 -16
  284. data/sandbox/itsi_sandbox_rails/config/deploy.yml +0 -116
  285. data/sandbox/itsi_sandbox_rails/config/queue.yml +0 -18
  286. data/sandbox/itsi_sandbox_rails/config/recurring.yml +0 -10
  287. data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +0 -11
  288. data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +0 -14
  289. data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +0 -129
  290. data/sandbox/itsi_sandbox_rails/public/400.html +0 -114
  291. data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +0 -9
  292. data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +0 -7
  293. /data/{sandbox/itsi_sandbox_rails/script/.keep → crates/_index.md} +0 -0
  294. /data/gems/server/lib/itsi/{index.html → server/default_app/index.html} +0 -0
@@ -1,170 +0,0 @@
1
- use super::{
2
- bind_protocol::BindProtocol,
3
- tls::{configure_tls, ItsiTlsAcceptor},
4
- };
5
- use itsi_error::ItsiError;
6
- use std::{
7
- collections::HashMap,
8
- net::{IpAddr, Ipv4Addr, Ipv6Addr, ToSocketAddrs},
9
- path::PathBuf,
10
- str::FromStr,
11
- };
12
-
13
- #[derive(Debug, Clone)]
14
- pub enum BindAddress {
15
- Ip(IpAddr),
16
- UnixSocket(PathBuf),
17
- }
18
-
19
- impl Default for BindAddress {
20
- fn default() -> Self {
21
- BindAddress::Ip(IpAddr::V4(Ipv4Addr::UNSPECIFIED))
22
- }
23
- }
24
-
25
- #[derive(Default, Clone)]
26
- #[magnus::wrap(class = "Itsi::Bind")]
27
- pub struct Bind {
28
- pub address: BindAddress,
29
- pub port: Option<u16>, // None for Unix Sockets
30
- pub protocol: BindProtocol,
31
- pub tls_config: Option<ItsiTlsAcceptor>,
32
- }
33
-
34
- impl std::fmt::Debug for Bind {
35
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36
- match &self.address {
37
- BindAddress::Ip(ip) => match self.protocol {
38
- BindProtocol::Unix | BindProtocol::Unixs => {
39
- write!(f, "{}://{}", self.protocol, ip)
40
- }
41
- BindProtocol::Https if self.port == Some(443) => {
42
- write!(f, "{}://{}", self.protocol, ip)
43
- }
44
- BindProtocol::Http if self.port == Some(80) => {
45
- write!(f, "{}://{}", self.protocol, ip)
46
- }
47
- _ => match self.port {
48
- Some(port) => write!(f, "{}://{}:{}", self.protocol, ip, port),
49
- None => write!(f, "{}://{}", self.protocol, ip),
50
- },
51
- },
52
- BindAddress::UnixSocket(path) => {
53
- write!(f, "{}://{}", self.protocol, path.display())
54
- }
55
- }
56
- }
57
- }
58
-
59
- /// We can build a Bind from a string in the format `protocol://host:port?options`
60
- /// E.g.
61
- /// *`https://example.com:443?tls_cert=/path/to/cert.pem&tls_key=/path/to/key.pem`
62
- /// *`unix:///path/to/socket.sock`
63
- /// *`http://example.com:80`
64
- /// *`https://[::]:80`
65
- impl FromStr for Bind {
66
- type Err = ItsiError;
67
-
68
- fn from_str(s: &str) -> Result<Self, Self::Err> {
69
- let (protocol, remainder) = if let Some((proto, rest)) = s.split_once("://") {
70
- (proto.parse::<BindProtocol>()?, rest)
71
- } else {
72
- (BindProtocol::Https, s)
73
- };
74
-
75
- let (url, options) = if let Some((base, options)) = remainder.split_once('?') {
76
- (base, parse_bind_options(options))
77
- } else {
78
- (remainder, HashMap::new())
79
- };
80
-
81
- let (host, port) = if url.starts_with('[') {
82
- // IPv6 with brackets `[::]:port`
83
- if let Some(end) = url.find(']') {
84
- let host = &url[1..end]; // Extract `::`
85
- let port = url[end + 1..]
86
- .strip_prefix(':')
87
- .and_then(|p| p.parse().ok());
88
- (host, port)
89
- } else {
90
- return Err(ItsiError::InvalidInput(
91
- "Invalid IPv6 address format".to_owned(),
92
- ));
93
- }
94
- } else if let Some((h, p)) = url.rsplit_once(':') {
95
- // Check if `h` is an IPv6 address before assuming it's a port
96
- if h.contains('.') || h.parse::<Ipv4Addr>().is_ok() {
97
- (h, p.parse::<u16>().ok()) // IPv4 case
98
- } else if h.parse::<Ipv6Addr>().is_ok() {
99
- // If it's IPv6, require brackets for port
100
- return Err(ItsiError::InvalidInput(
101
- "IPv6 addresses must use [ ] when specifying a port".to_owned(),
102
- ));
103
- } else {
104
- (h, None) // Treat as a hostname
105
- }
106
- } else {
107
- (url, None)
108
- };
109
-
110
- let address = if let Ok(ip) = host.parse::<IpAddr>() {
111
- BindAddress::Ip(ip)
112
- } else {
113
- resolve_hostname(host)
114
- .map(BindAddress::Ip)
115
- .ok_or(ItsiError::ArgumentError(format!(
116
- "Failed to resolve hostname {}",
117
- host
118
- )))?
119
- };
120
- let (port, address) = match protocol {
121
- BindProtocol::Http => (port.or(Some(80)), address),
122
- BindProtocol::Https => (port.or(Some(443)), address),
123
- BindProtocol::Unix => (None, BindAddress::UnixSocket(host.into())),
124
- BindProtocol::Unixs => (None, BindAddress::UnixSocket(host.into())),
125
- };
126
-
127
- let tls_config = match protocol {
128
- BindProtocol::Http => None,
129
- BindProtocol::Https => Some(configure_tls(host, &options)?),
130
- BindProtocol::Unix => None,
131
- BindProtocol::Unixs => Some(configure_tls(host, &options)?),
132
- };
133
- let bind = Self {
134
- address,
135
- port,
136
- protocol,
137
- tls_config,
138
- };
139
- Ok(bind)
140
- }
141
- }
142
-
143
- fn parse_bind_options(query: &str) -> HashMap<String, String> {
144
- query
145
- .split('&')
146
- .filter_map(|pair| pair.split_once('='))
147
- .map(|(k, v)| (k.to_owned(), v.to_owned()))
148
- .collect()
149
- }
150
-
151
- /// Attempts to resolve a hostname into an IP address.
152
- fn resolve_hostname(hostname: &str) -> Option<IpAddr> {
153
- (hostname, 0)
154
- .to_socket_addrs()
155
- .ok()?
156
- .find_map(|addr| {
157
- if addr.is_ipv6() {
158
- Some(addr.ip()) // Prefer IPv6
159
- } else {
160
- None
161
- }
162
- })
163
- .or_else(|| {
164
- (hostname, 0)
165
- .to_socket_addrs()
166
- .ok()?
167
- .map(|addr| addr.ip())
168
- .next()
169
- }) // Fallback to IPv4
170
- }
@@ -1,37 +0,0 @@
1
- use itsi_error::ItsiError;
2
- use std::str::FromStr;
3
-
4
- #[derive(Debug, Default, Clone)]
5
- pub enum BindProtocol {
6
- #[default]
7
- Https,
8
- Http,
9
- Unix,
10
- Unixs,
11
- }
12
-
13
- impl FromStr for BindProtocol {
14
- type Err = ItsiError;
15
-
16
- fn from_str(s: &str) -> Result<Self, Self::Err> {
17
- match s {
18
- "http" => Ok(BindProtocol::Http),
19
- "https" => Ok(BindProtocol::Https),
20
- "unix" => Ok(BindProtocol::Unix),
21
- "tls" => Ok(BindProtocol::Unixs),
22
- _ => Err(ItsiError::UnsupportedProtocol(s.to_string())),
23
- }
24
- }
25
- }
26
-
27
- impl std::fmt::Display for BindProtocol {
28
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29
- let s = match self {
30
- BindProtocol::Https => "https",
31
- BindProtocol::Http => "http",
32
- BindProtocol::Unix => "unix",
33
- BindProtocol::Unixs => "tls",
34
- };
35
- write!(f, "{}", s)
36
- }
37
- }
@@ -1,104 +0,0 @@
1
- use super::listener::SockAddr;
2
- use pin_project::pin_project;
3
- use tokio::net::{TcpStream, UnixStream};
4
- use tokio_rustls::server::TlsStream;
5
-
6
- use std::os::unix::io::{AsRawFd, RawFd};
7
- use std::pin::Pin;
8
- use std::task::{Context, Poll};
9
- use tokio::io::{AsyncRead, AsyncWrite};
10
-
11
- #[pin_project(project = IoStreamEnumProj)]
12
- pub enum IoStream {
13
- Tcp {
14
- #[pin]
15
- stream: TcpStream,
16
- addr: SockAddr,
17
- },
18
- TcpTls {
19
- #[pin]
20
- stream: TlsStream<TcpStream>,
21
- addr: SockAddr,
22
- },
23
- Unix {
24
- #[pin]
25
- stream: UnixStream,
26
- addr: SockAddr,
27
- },
28
- UnixTls {
29
- #[pin]
30
- stream: TlsStream<UnixStream>,
31
- addr: SockAddr,
32
- },
33
- }
34
-
35
- impl IoStream {
36
- pub fn addr(&self) -> SockAddr {
37
- match self {
38
- IoStream::Tcp { addr, .. } => addr.clone(),
39
- IoStream::TcpTls { addr, .. } => addr.clone(),
40
- IoStream::Unix { addr, .. } => addr.clone(),
41
- IoStream::UnixTls { addr, .. } => addr.clone(),
42
- }
43
- }
44
- }
45
-
46
- impl AsyncRead for IoStream {
47
- fn poll_read(
48
- self: Pin<&mut Self>,
49
- cx: &mut Context<'_>,
50
- buf: &mut tokio::io::ReadBuf<'_>,
51
- ) -> Poll<std::io::Result<()>> {
52
- match self.project() {
53
- IoStreamEnumProj::Tcp { stream, .. } => stream.poll_read(cx, buf),
54
- IoStreamEnumProj::TcpTls { stream, .. } => stream.poll_read(cx, buf),
55
- IoStreamEnumProj::Unix { stream, .. } => stream.poll_read(cx, buf),
56
- IoStreamEnumProj::UnixTls { stream, .. } => stream.poll_read(cx, buf),
57
- }
58
- }
59
- }
60
-
61
- impl AsyncWrite for IoStream {
62
- fn poll_write(
63
- self: Pin<&mut Self>,
64
- cx: &mut Context<'_>,
65
- buf: &[u8],
66
- ) -> Poll<std::io::Result<usize>> {
67
- match self.project() {
68
- IoStreamEnumProj::Tcp { stream, .. } => stream.poll_write(cx, buf),
69
- IoStreamEnumProj::TcpTls { stream, .. } => stream.poll_write(cx, buf),
70
- IoStreamEnumProj::Unix { stream, .. } => stream.poll_write(cx, buf),
71
- IoStreamEnumProj::UnixTls { stream, .. } => stream.poll_write(cx, buf),
72
- }
73
- }
74
-
75
- fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
76
- match self.project() {
77
- IoStreamEnumProj::Tcp { stream, .. } => stream.poll_flush(cx),
78
- IoStreamEnumProj::TcpTls { stream, .. } => stream.poll_flush(cx),
79
- IoStreamEnumProj::Unix { stream, .. } => stream.poll_flush(cx),
80
- IoStreamEnumProj::UnixTls { stream, .. } => stream.poll_flush(cx),
81
- }
82
- }
83
-
84
- fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
85
- match self.project() {
86
- IoStreamEnumProj::Tcp { stream, .. } => stream.poll_shutdown(cx),
87
- IoStreamEnumProj::TcpTls { stream, .. } => stream.poll_shutdown(cx),
88
- IoStreamEnumProj::Unix { stream, .. } => stream.poll_shutdown(cx),
89
- IoStreamEnumProj::UnixTls { stream, .. } => stream.poll_shutdown(cx),
90
- }
91
- }
92
- }
93
-
94
- impl AsRawFd for IoStream {
95
- fn as_raw_fd(&self) -> RawFd {
96
- // For immutable access, we can simply pattern-match on self.
97
- match self {
98
- IoStream::Tcp { stream, .. } => stream.as_raw_fd(),
99
- IoStream::TcpTls { stream, .. } => stream.get_ref().0.as_raw_fd(),
100
- IoStream::Unix { stream, .. } => stream.as_raw_fd(),
101
- IoStream::UnixTls { stream, .. } => stream.get_ref().0.as_raw_fd(),
102
- }
103
- }
104
- }
@@ -1,294 +0,0 @@
1
- use super::{
2
- bind::Bind,
3
- listener::Listener,
4
- serve_strategy::{cluster_mode::ClusterMode, single_mode::SingleMode},
5
- signal::{
6
- clear_signal_handlers, reset_signal_handlers, send_shutdown_event, SIGNAL_HANDLER_CHANNEL,
7
- },
8
- };
9
- use crate::{request::itsi_request::ItsiRequest, server::serve_strategy::ServeStrategy};
10
- use derive_more::Debug;
11
- use itsi_rb_helpers::{call_without_gvl, HeapVal};
12
- use itsi_tracing::{error, run_silently};
13
- use magnus::{
14
- block::Proc,
15
- error::Result,
16
- scan_args::{get_kwargs, scan_args, Args, KwArgs, ScanArgsKw, ScanArgsOpt, ScanArgsRequired},
17
- value::{InnerValue, Opaque, ReprValue},
18
- ArgList, RHash, Ruby, Symbol, Value,
19
- };
20
- use parking_lot::{Mutex, RwLock};
21
- use std::{cmp::max, ops::Deref, sync::Arc};
22
- use tracing::{info, instrument};
23
-
24
- static DEFAULT_BIND: &str = "http://localhost:3000";
25
-
26
- #[magnus::wrap(class = "Itsi::Server", free_immediately, size)]
27
- #[derive(Clone)]
28
- pub struct Server {
29
- pub config: Arc<ServerConfig>,
30
- }
31
-
32
- impl Deref for Server {
33
- type Target = ServerConfig;
34
-
35
- fn deref(&self) -> &Self::Target {
36
- &self.config
37
- }
38
- }
39
- type AfterFork = Mutex<Arc<Option<Box<dyn Fn() + Send + Sync>>>>;
40
-
41
- #[derive(Debug)]
42
- pub struct ServerConfig {
43
- #[debug(skip)]
44
- pub app: HeapVal,
45
- #[allow(unused)]
46
- pub workers: u8,
47
- #[allow(unused)]
48
- pub threads: u8,
49
- #[allow(unused)]
50
- pub shutdown_timeout: f64,
51
- pub script_name: String,
52
- pub(crate) binds: Mutex<Vec<Bind>>,
53
- #[debug(skip)]
54
- pub before_fork: Mutex<Option<Box<dyn FnOnce() + Send + Sync>>>,
55
- #[debug(skip)]
56
- pub after_fork: AfterFork,
57
- pub scheduler_class: Option<String>,
58
- pub stream_body: Option<bool>,
59
- pub worker_memory_limit: Option<u64>,
60
- #[debug(skip)]
61
- pub(crate) strategy: RwLock<Option<ServeStrategy>>,
62
- pub silence: bool,
63
- }
64
-
65
- #[derive(Debug)]
66
- pub enum RequestJob {
67
- ProcessRequest(ItsiRequest),
68
- Shutdown,
69
- }
70
-
71
- // Define your helper function.
72
- // Here P, A, C correspond to the types for the first tuple, second tuple, and extra parameters respectively.
73
- fn extract_args<Req, Opt, Splat>(
74
- scan_args: &Args<(), (), (), (), RHash, ()>,
75
- primaries: &[&str],
76
- rest: &[&str],
77
- ) -> Result<KwArgs<Req, Opt, Splat>>
78
- where
79
- Req: ScanArgsRequired,
80
- Opt: ScanArgsOpt,
81
- Splat: ScanArgsKw,
82
- {
83
- // Combine the primary and rest names into one Vec of Symbols.
84
- let symbols: Vec<Symbol> = primaries
85
- .iter()
86
- .chain(rest.iter())
87
- .map(|&name| Symbol::new(name))
88
- .collect();
89
-
90
- // Call the "slice" function with the combined symbols.
91
- let hash = scan_args
92
- .keywords
93
- .funcall::<_, _, RHash>("slice", symbols.into_arg_list_with(&Ruby::get().unwrap()))
94
- .unwrap();
95
-
96
- // Finally, call get_kwargs with the original name slices.
97
- get_kwargs(hash, primaries, rest)
98
- }
99
-
100
- impl Server {
101
- #[instrument(
102
- name = "Itsi",
103
- parent=None,
104
- skip(args),
105
- fields(workers = 1, threads = 1, shutdown_timeout = 5)
106
- )]
107
- pub fn new(args: &[Value]) -> Result<Self> {
108
- let scan_args: Args<(), (), (), (), RHash, ()> = scan_args(args)?;
109
-
110
- type Args1 = KwArgs<
111
- (Value,),
112
- (
113
- // Workers
114
- Option<u8>,
115
- // Threads
116
- Option<u8>,
117
- // Shutdown Timeout
118
- Option<f64>,
119
- // Script Name
120
- Option<String>,
121
- // Binds
122
- Option<Vec<String>>,
123
- // Stream Body
124
- Option<bool>,
125
- ),
126
- (),
127
- >;
128
-
129
- type Args2 = KwArgs<
130
- (),
131
- (
132
- // Before Fork
133
- Option<Proc>,
134
- // After Fork
135
- Option<Proc>,
136
- // Scheduler Class
137
- Option<String>,
138
- // Worker Memory Limit
139
- Option<u64>,
140
- // Silence
141
- Option<bool>,
142
- ),
143
- (),
144
- >;
145
-
146
- let args1: Args1 = extract_args(
147
- &scan_args,
148
- &["app"],
149
- &[
150
- "workers",
151
- "threads",
152
- "shutdown_timeout",
153
- "script_name",
154
- "binds",
155
- "stream_body",
156
- ],
157
- )?;
158
-
159
- let args2: Args2 = extract_args(
160
- &scan_args,
161
- &[],
162
- &[
163
- "before_fork",
164
- "after_fork",
165
- "scheduler_class",
166
- "worker_memory_limit",
167
- "silence",
168
- ],
169
- )?;
170
-
171
- let config = ServerConfig {
172
- app: HeapVal::from(args1.required.0),
173
- workers: max(args1.optional.0.unwrap_or(1), 1),
174
- threads: max(args1.optional.1.unwrap_or(1), 1),
175
- shutdown_timeout: args1.optional.2.unwrap_or(5.0),
176
- script_name: args1.optional.3.unwrap_or("".to_string()),
177
- binds: Mutex::new(
178
- args1
179
- .optional
180
- .4
181
- .unwrap_or_else(|| vec![DEFAULT_BIND.to_string()])
182
- .into_iter()
183
- .map(|s| s.parse())
184
- .collect::<itsi_error::Result<Vec<Bind>>>()?,
185
- ),
186
- stream_body: args1.optional.5,
187
- before_fork: Mutex::new(args2.optional.0.map(|p| {
188
- let opaque_proc = Opaque::from(p);
189
- Box::new(move || {
190
- opaque_proc
191
- .get_inner_with(&Ruby::get().unwrap())
192
- .call::<_, Value>(())
193
- .unwrap();
194
- }) as Box<dyn FnOnce() + Send + Sync>
195
- })),
196
- after_fork: Mutex::new(Arc::new(args2.optional.1.map(|p| {
197
- let opaque_proc = Opaque::from(p);
198
- Box::new(move || {
199
- opaque_proc
200
- .get_inner_with(&Ruby::get().unwrap())
201
- .call::<_, Value>(())
202
- .unwrap();
203
- }) as Box<dyn Fn() + Send + Sync>
204
- }))),
205
- scheduler_class: args2.optional.2.clone(),
206
- worker_memory_limit: args2.optional.3,
207
- silence: args2.optional.4.is_some_and(|s| s),
208
- strategy: RwLock::new(None),
209
- };
210
-
211
- if !config.silence {
212
- if let Some(scheduler_class) = args2.optional.2 {
213
- info!(scheduler_class, fiber_scheduler = true);
214
- } else {
215
- info!(fiber_scheduler = false);
216
- }
217
- }
218
-
219
- Ok(Server {
220
- config: Arc::new(config),
221
- })
222
- }
223
-
224
- #[instrument(name = "Bind", skip_all, fields(binds=format!("{:?}", self.config.binds.lock())))]
225
- pub(crate) fn build_listeners(&self) -> Result<Arc<Vec<Arc<Listener>>>> {
226
- let listeners = self
227
- .config
228
- .binds
229
- .lock()
230
- .iter()
231
- .cloned()
232
- .map(Listener::try_from)
233
- .collect::<std::result::Result<Vec<Listener>, _>>()?
234
- .into_iter()
235
- .map(Arc::new)
236
- .collect::<Vec<_>>();
237
- info!("Bound {:?} listeners", listeners.len());
238
- Ok(Arc::new(listeners))
239
- }
240
-
241
- pub(crate) fn build_strategy(self, listeners: Arc<Vec<Arc<Listener>>>) -> Result<()> {
242
- let server = Arc::new(self);
243
- let server_clone = server.clone();
244
-
245
- let strategy = if server.config.workers == 1 {
246
- ServeStrategy::Single(Arc::new(SingleMode::new(
247
- server,
248
- listeners,
249
- SIGNAL_HANDLER_CHANNEL.0.clone(),
250
- )?))
251
- } else {
252
- ServeStrategy::Cluster(Arc::new(ClusterMode::new(
253
- server,
254
- listeners,
255
- SIGNAL_HANDLER_CHANNEL.0.clone(),
256
- )))
257
- };
258
-
259
- *server_clone.strategy.write() = Some(strategy);
260
- Ok(())
261
- }
262
-
263
- pub fn stop(&self) -> Result<()> {
264
- send_shutdown_event();
265
- Ok(())
266
- }
267
-
268
- pub fn start(&self) -> Result<()> {
269
- if self.silence {
270
- run_silently(|| self.build_and_run_strategy())
271
- } else {
272
- self.build_and_run_strategy()
273
- }
274
- }
275
-
276
- fn build_and_run_strategy(&self) -> Result<()> {
277
- reset_signal_handlers();
278
- let rself = self.clone();
279
- let listeners = self.build_listeners()?;
280
- let listeners_clone = listeners.clone();
281
- call_without_gvl(move || -> Result<()> {
282
- rself.clone().build_strategy(listeners_clone)?;
283
- if let Err(e) = rself.clone().strategy.read().as_ref().unwrap().run() {
284
- error!("Error running server: {}", e);
285
- rself.strategy.read().as_ref().unwrap().stop()?;
286
- }
287
- Ok(())
288
- })?;
289
- clear_signal_handlers();
290
- self.strategy.write().take();
291
- info!("Server stopped");
292
- Ok(())
293
- }
294
- }
@@ -1,9 +0,0 @@
1
- #[derive(Debug, Clone)]
2
- pub enum LifecycleEvent {
3
- Start,
4
- Shutdown,
5
- Restart,
6
- IncreaseWorkers,
7
- DecreaseWorkers,
8
- ForceShutdown,
9
- }