itsi-server 0.1.1 → 0.1.20

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.

Potentially problematic release.


This version of itsi-server might be problematic. Click here for more details.

Files changed (324) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +4487 -0
  3. data/Cargo.toml +7 -0
  4. data/README.md +6 -0
  5. data/Rakefile +8 -1
  6. data/exe/itsi +141 -46
  7. data/ext/itsi_acme/Cargo.toml +86 -0
  8. data/ext/itsi_acme/examples/high_level.rs +63 -0
  9. data/ext/itsi_acme/examples/high_level_warp.rs +52 -0
  10. data/ext/itsi_acme/examples/low_level.rs +87 -0
  11. data/ext/itsi_acme/examples/low_level_axum.rs +66 -0
  12. data/ext/itsi_acme/src/acceptor.rs +81 -0
  13. data/ext/itsi_acme/src/acme.rs +354 -0
  14. data/ext/itsi_acme/src/axum.rs +86 -0
  15. data/ext/itsi_acme/src/cache.rs +39 -0
  16. data/ext/itsi_acme/src/caches/boxed.rs +80 -0
  17. data/ext/itsi_acme/src/caches/composite.rs +69 -0
  18. data/ext/itsi_acme/src/caches/dir.rs +106 -0
  19. data/ext/itsi_acme/src/caches/mod.rs +11 -0
  20. data/ext/itsi_acme/src/caches/no.rs +78 -0
  21. data/ext/itsi_acme/src/caches/test.rs +136 -0
  22. data/ext/itsi_acme/src/config.rs +172 -0
  23. data/ext/itsi_acme/src/https_helper.rs +69 -0
  24. data/ext/itsi_acme/src/incoming.rs +142 -0
  25. data/ext/itsi_acme/src/jose.rs +161 -0
  26. data/ext/itsi_acme/src/lib.rs +142 -0
  27. data/ext/itsi_acme/src/resolver.rs +59 -0
  28. data/ext/itsi_acme/src/state.rs +424 -0
  29. data/ext/itsi_error/Cargo.toml +3 -0
  30. data/ext/itsi_error/src/lib.rs +98 -24
  31. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  32. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  33. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  34. data/ext/itsi_error/target/debug/build/rb-sys-49f554618693db24/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
  35. data/ext/itsi_error/target/debug/incremental/itsi_error-1mmt5sux7jb0i/s-h510z7m8v9-0bxu7yd.lock +0 -0
  36. data/ext/itsi_error/target/debug/incremental/itsi_error-2vn3jey74oiw0/s-h5113n0e7e-1v5qzs6.lock +0 -0
  37. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510ykifhe-0tbnep2.lock +0 -0
  38. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510yyocpj-0tz7ug7.lock +0 -0
  39. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510z0xc8g-14ol18k.lock +0 -0
  40. data/ext/itsi_error/target/debug/incremental/itsi_error-3g5qf4y7d54uj/s-h5113n0e7d-1trk8on.lock +0 -0
  41. data/ext/itsi_error/target/debug/incremental/itsi_error-3lpfftm45d3e2/s-h510z7m8r3-1pxp20o.lock +0 -0
  42. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510ykifek-1uxasnk.lock +0 -0
  43. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510yyocki-11u37qm.lock +0 -0
  44. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510z0xc93-0pmy0zm.lock +0 -0
  45. data/ext/itsi_instrument_entry/Cargo.toml +15 -0
  46. data/ext/itsi_instrument_entry/src/lib.rs +31 -0
  47. data/ext/itsi_rb_helpers/Cargo.toml +3 -0
  48. data/ext/itsi_rb_helpers/src/heap_value.rs +139 -0
  49. data/ext/itsi_rb_helpers/src/lib.rs +140 -10
  50. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  51. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  52. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  53. data/ext/itsi_rb_helpers/target/debug/build/rb-sys-eb9ed4ff3a60f995/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
  54. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-040pxg6yhb3g3/s-h5113n7a1b-03bwlt4.lock +0 -0
  55. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h51113xnh3-1eik1ip.lock +0 -0
  56. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h5111704jj-0g4rj8x.lock +0 -0
  57. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-1q2d3drtxrzs5/s-h5113n79yl-0bxcqc5.lock +0 -0
  58. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h51113xoox-10de2hp.lock +0 -0
  59. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h5111704w7-0vdq7gq.lock +0 -0
  60. data/ext/itsi_scheduler/Cargo.toml +24 -0
  61. data/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +56 -0
  62. data/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +44 -0
  63. data/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +44 -0
  64. data/ext/itsi_scheduler/src/itsi_scheduler.rs +308 -0
  65. data/ext/itsi_scheduler/src/lib.rs +38 -0
  66. data/ext/itsi_server/Cargo.lock +2956 -0
  67. data/ext/itsi_server/Cargo.toml +75 -14
  68. data/ext/itsi_server/extconf.rb +1 -1
  69. data/ext/itsi_server/src/default_responses/html/401.html +68 -0
  70. data/ext/itsi_server/src/default_responses/html/403.html +68 -0
  71. data/ext/itsi_server/src/default_responses/html/404.html +68 -0
  72. data/ext/itsi_server/src/default_responses/html/413.html +71 -0
  73. data/ext/itsi_server/src/default_responses/html/429.html +68 -0
  74. data/ext/itsi_server/src/default_responses/html/500.html +71 -0
  75. data/ext/itsi_server/src/default_responses/html/502.html +71 -0
  76. data/ext/itsi_server/src/default_responses/html/503.html +68 -0
  77. data/ext/itsi_server/src/default_responses/html/504.html +69 -0
  78. data/ext/itsi_server/src/default_responses/html/index.html +238 -0
  79. data/ext/itsi_server/src/default_responses/json/401.json +6 -0
  80. data/ext/itsi_server/src/default_responses/json/403.json +6 -0
  81. data/ext/itsi_server/src/default_responses/json/404.json +6 -0
  82. data/ext/itsi_server/src/default_responses/json/413.json +6 -0
  83. data/ext/itsi_server/src/default_responses/json/429.json +6 -0
  84. data/ext/itsi_server/src/default_responses/json/500.json +6 -0
  85. data/ext/itsi_server/src/default_responses/json/502.json +6 -0
  86. data/ext/itsi_server/src/default_responses/json/503.json +6 -0
  87. data/ext/itsi_server/src/default_responses/json/504.json +6 -0
  88. data/ext/itsi_server/src/default_responses/mod.rs +11 -0
  89. data/ext/itsi_server/src/env.rs +43 -0
  90. data/ext/itsi_server/src/lib.rs +132 -40
  91. data/ext/itsi_server/src/prelude.rs +2 -0
  92. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/big_bytes.rs +109 -0
  93. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +143 -0
  94. data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +344 -0
  95. data/ext/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +264 -0
  96. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +345 -0
  97. data/ext/itsi_server/src/ruby_types/itsi_http_response.rs +391 -0
  98. data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
  99. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +506 -0
  100. data/ext/itsi_server/src/ruby_types/itsi_server.rs +84 -0
  101. data/ext/itsi_server/src/ruby_types/mod.rs +48 -0
  102. data/ext/itsi_server/src/server/binds/bind.rs +201 -0
  103. data/ext/itsi_server/src/server/binds/bind_protocol.rs +37 -0
  104. data/ext/itsi_server/src/server/binds/listener.rs +437 -0
  105. data/ext/itsi_server/src/server/binds/mod.rs +4 -0
  106. data/ext/itsi_server/src/server/binds/tls/locked_dir_cache.rs +132 -0
  107. data/ext/itsi_server/src/server/binds/tls.rs +270 -0
  108. data/ext/itsi_server/src/server/byte_frame.rs +32 -0
  109. data/ext/itsi_server/src/server/http_message_types.rs +97 -0
  110. data/ext/itsi_server/src/server/io_stream.rs +105 -0
  111. data/ext/itsi_server/src/server/lifecycle_event.rs +12 -0
  112. data/ext/itsi_server/src/server/middleware_stack/middleware.rs +170 -0
  113. data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +56 -0
  114. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +87 -0
  115. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +86 -0
  116. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +338 -0
  117. data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +142 -0
  118. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +289 -0
  119. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +292 -0
  120. data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +179 -0
  121. data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +55 -0
  122. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +190 -0
  123. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +157 -0
  124. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +195 -0
  125. data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +82 -0
  126. data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +201 -0
  127. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
  128. data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
  129. data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +110 -0
  130. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +414 -0
  131. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +131 -0
  132. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
  133. data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +44 -0
  134. data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +36 -0
  135. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +126 -0
  136. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +181 -0
  137. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +55 -0
  138. data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +163 -0
  139. data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
  140. data/ext/itsi_server/src/server/middleware_stack/mod.rs +345 -0
  141. data/ext/itsi_server/src/server/mod.rs +12 -5
  142. data/ext/itsi_server/src/server/process_worker.rs +247 -0
  143. data/ext/itsi_server/src/server/request_job.rs +11 -0
  144. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +348 -0
  145. data/ext/itsi_server/src/server/serve_strategy/mod.rs +30 -0
  146. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +444 -0
  147. data/ext/itsi_server/src/server/signal.rs +76 -0
  148. data/ext/itsi_server/src/server/size_limited_incoming.rs +101 -0
  149. data/ext/itsi_server/src/server/thread_worker.rs +475 -0
  150. data/ext/itsi_server/src/services/cache_store.rs +74 -0
  151. data/ext/itsi_server/src/services/itsi_http_service.rs +239 -0
  152. data/ext/itsi_server/src/services/mime_types.rs +1416 -0
  153. data/ext/itsi_server/src/services/mod.rs +6 -0
  154. data/ext/itsi_server/src/services/password_hasher.rs +83 -0
  155. data/ext/itsi_server/src/services/rate_limiter.rs +569 -0
  156. data/ext/itsi_server/src/services/static_file_server.rs +1326 -0
  157. data/ext/itsi_tracing/Cargo.toml +5 -0
  158. data/ext/itsi_tracing/src/lib.rs +346 -7
  159. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0994n8rpvvt9m/s-h510hfz1f6-1kbycmq.lock +0 -0
  160. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0bob7bf4yq34i/s-h5113125h5-0lh4rag.lock +0 -0
  161. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2fcodulrxbbxo/s-h510h2infk-0hp5kjw.lock +0 -0
  162. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2iak63r1woi1l/s-h510h2in4q-0kxfzw1.lock +0 -0
  163. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2kk4qj9gn5dg2/s-h5113124kv-0enwon2.lock +0 -0
  164. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2mwo0yas7dtw4/s-h510hfz1ha-1udgpei.lock +0 -0
  165. data/lib/itsi/http_request/response_status_shortcodes.rb +74 -0
  166. data/lib/itsi/http_request.rb +187 -0
  167. data/lib/itsi/http_response.rb +41 -0
  168. data/lib/itsi/passfile.rb +109 -0
  169. data/lib/itsi/server/config/config_helpers.rb +93 -0
  170. data/lib/itsi/server/config/dsl.rb +626 -0
  171. data/lib/itsi/server/config/known_paths/KitchensinkDirectories.txt +2346 -0
  172. data/lib/itsi/server/config/known_paths/Randomfiles.txt +24 -0
  173. data/lib/itsi/server/config/known_paths/UnixDotfiles.txt +52 -0
  174. data/lib/itsi/server/config/known_paths/backdoors/ASP_CommonBackdoors.txt +29 -0
  175. data/lib/itsi/server/config/known_paths/backdoors/bot_control_panels.txt +1668 -0
  176. data/lib/itsi/server/config/known_paths/backdoors/shells.txt +1167 -0
  177. data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST.txt +7 -0
  178. data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST_Windows.txt +6 -0
  179. data/lib/itsi/server/config/known_paths/cgi/CGI_Microsoft.txt +79 -0
  180. data/lib/itsi/server/config/known_paths/cgi/CGI_XPlatform.txt +3948 -0
  181. data/lib/itsi/server/config/known_paths/cms/README.md +5 -0
  182. data/lib/itsi/server/config/known_paths/cms/drupal_plugins.txt +6320 -0
  183. data/lib/itsi/server/config/known_paths/cms/drupal_themes.txt +828 -0
  184. data/lib/itsi/server/config/known_paths/cms/joomla_plugins.txt +224 -0
  185. data/lib/itsi/server/config/known_paths/cms/joomla_themes.txt +30 -0
  186. data/lib/itsi/server/config/known_paths/cms/php-nuke.txt +2142 -0
  187. data/lib/itsi/server/config/known_paths/cms/wordpress.txt +1566 -0
  188. data/lib/itsi/server/config/known_paths/cms/wp_common_theme_files.txt +46 -0
  189. data/lib/itsi/server/config/known_paths/cms/wp_plugins.txt +13366 -0
  190. data/lib/itsi/server/config/known_paths/cms/wp_plugins_full.txt +68662 -0
  191. data/lib/itsi/server/config/known_paths/cms/wp_plugins_top225.txt +225 -0
  192. data/lib/itsi/server/config/known_paths/cms/wp_themes.readme +12 -0
  193. data/lib/itsi/server/config/known_paths/cms/wp_themes.txt +7336 -0
  194. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/3CharExtBrute.txt +17576 -0
  195. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/CommonWebExtensions.txt +80 -0
  196. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Backup.txt +14 -0
  197. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Common.txt +865 -0
  198. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Compressed.txt +186 -0
  199. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Mostcommon.txt +30 -0
  200. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Skipfish.txt +93 -0
  201. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/WordlistSkipfish.txt +1918 -0
  202. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/copy_of.txt +8 -0
  203. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories-lowercase.txt +56180 -0
  204. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories.txt +62290 -0
  205. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions-lowercase.txt +2367 -0
  206. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions.txt +2450 -0
  207. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files-lowercase.txt +35323 -0
  208. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files.txt +37037 -0
  209. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words-lowercase.txt +107982 -0
  210. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words.txt +119600 -0
  211. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories-lowercase.txt +26593 -0
  212. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories.txt +30009 -0
  213. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions-lowercase.txt +1233 -0
  214. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions.txt +1289 -0
  215. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files-lowercase.txt +16243 -0
  216. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files.txt +17128 -0
  217. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words-lowercase.txt +56293 -0
  218. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words.txt +63087 -0
  219. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories-lowercase.txt +17776 -0
  220. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories.txt +20122 -0
  221. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions-lowercase.txt +914 -0
  222. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions.txt +963 -0
  223. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files-lowercase.txt +10848 -0
  224. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files.txt +11424 -0
  225. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words-lowercase.txt +38267 -0
  226. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words.txt +43003 -0
  227. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/spanish.txt +445 -0
  228. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/test_demo.txt +36 -0
  229. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/upload_variants.txt +44 -0
  230. data/lib/itsi/server/config/known_paths/login-file-locations/Logins.txt +71 -0
  231. data/lib/itsi/server/config/known_paths/login-file-locations/cfm.txt +294 -0
  232. data/lib/itsi/server/config/known_paths/login-file-locations/html.txt +295 -0
  233. data/lib/itsi/server/config/known_paths/login-file-locations/jsp.txt +294 -0
  234. data/lib/itsi/server/config/known_paths/login-file-locations/php.txt +294 -0
  235. data/lib/itsi/server/config/known_paths/login-file-locations/windows-asp.txt +294 -0
  236. data/lib/itsi/server/config/known_paths/login-file-locations/windows-aspx.txt +294 -0
  237. data/lib/itsi/server/config/known_paths/password-file-locations/Passwords.txt +47 -0
  238. data/lib/itsi/server/config/known_paths/php/PHP.txt +30 -0
  239. data/lib/itsi/server/config/known_paths/php/PHP_CommonBackdoors.txt +5 -0
  240. data/lib/itsi/server/config/known_paths/proxy-conf.txt +31 -0
  241. data/lib/itsi/server/config/known_paths/tftp.txt +79 -0
  242. data/lib/itsi/server/config/known_paths/webservers-appservers/ADFS.txt +86 -0
  243. data/lib/itsi/server/config/known_paths/webservers-appservers/AdobeXML.txt +16 -0
  244. data/lib/itsi/server/config/known_paths/webservers-appservers/Apache.txt +101 -0
  245. data/lib/itsi/server/config/known_paths/webservers-appservers/ApacheTomcat.txt +47 -0
  246. data/lib/itsi/server/config/known_paths/webservers-appservers/Apache_Axis.txt +16 -0
  247. data/lib/itsi/server/config/known_paths/webservers-appservers/ColdFusion.txt +111 -0
  248. data/lib/itsi/server/config/known_paths/webservers-appservers/FatwireCMS.txt +390 -0
  249. data/lib/itsi/server/config/known_paths/webservers-appservers/Frontpage.txt +38 -0
  250. data/lib/itsi/server/config/known_paths/webservers-appservers/HP_System_Mgmt_Homepage.txt +239 -0
  251. data/lib/itsi/server/config/known_paths/webservers-appservers/HTTP_POST_Microsoft.txt +2 -0
  252. data/lib/itsi/server/config/known_paths/webservers-appservers/Hyperion.txt +578 -0
  253. data/lib/itsi/server/config/known_paths/webservers-appservers/IIS.txt +187 -0
  254. data/lib/itsi/server/config/known_paths/webservers-appservers/JBoss.txt +5 -0
  255. data/lib/itsi/server/config/known_paths/webservers-appservers/JRun.txt +13 -0
  256. data/lib/itsi/server/config/known_paths/webservers-appservers/JavaServlets_Common.txt +3 -0
  257. data/lib/itsi/server/config/known_paths/webservers-appservers/Joomla_exploitable.txt +1937 -0
  258. data/lib/itsi/server/config/known_paths/webservers-appservers/LotusNotes.txt +206 -0
  259. data/lib/itsi/server/config/known_paths/webservers-appservers/Netware.txt +18 -0
  260. data/lib/itsi/server/config/known_paths/webservers-appservers/Oracle9i.txt +60 -0
  261. data/lib/itsi/server/config/known_paths/webservers-appservers/OracleAppServer.txt +192 -0
  262. data/lib/itsi/server/config/known_paths/webservers-appservers/README.md +6 -0
  263. data/lib/itsi/server/config/known_paths/webservers-appservers/Ruby_Rails.txt +121 -0
  264. data/lib/itsi/server/config/known_paths/webservers-appservers/SAP.txt +463 -0
  265. data/lib/itsi/server/config/known_paths/webservers-appservers/Sharepoint.txt +1707 -0
  266. data/lib/itsi/server/config/known_paths/webservers-appservers/SiteMinder.txt +19 -0
  267. data/lib/itsi/server/config/known_paths/webservers-appservers/SunAppServerGlassfish.txt +51 -0
  268. data/lib/itsi/server/config/known_paths/webservers-appservers/SuniPlanet.txt +35 -0
  269. data/lib/itsi/server/config/known_paths/webservers-appservers/Vignette.txt +73 -0
  270. data/lib/itsi/server/config/known_paths/webservers-appservers/Weblogic.txt +160 -0
  271. data/lib/itsi/server/config/known_paths/webservers-appservers/Websphere.txt +366 -0
  272. data/lib/itsi/server/config/known_paths/wellknown-rfc5785.txt +30 -0
  273. data/lib/itsi/server/config/known_paths.rb +17 -0
  274. data/lib/itsi/server/config/middleware/_index.md +54 -0
  275. data/lib/itsi/server/config/middleware/log_requests.md +63 -0
  276. data/lib/itsi/server/config/middleware/log_requests.rb +33 -0
  277. data/lib/itsi/server/config/middleware.rb +9 -0
  278. data/lib/itsi/server/config/option.rb +9 -0
  279. data/lib/itsi/server/config/options/_index.md +36 -0
  280. data/lib/itsi/server/config/options/fiber_scheduler.md +35 -0
  281. data/lib/itsi/server/config/options/fiber_scheduler.rb +18 -0
  282. data/lib/itsi/server/config/options/threads.md +39 -0
  283. data/lib/itsi/server/config/options/threads.rb +17 -0
  284. data/lib/itsi/server/config/options/workers.md +43 -0
  285. data/lib/itsi/server/config/options/workers.rb +17 -0
  286. data/lib/itsi/server/config/typed_struct.rb +203 -0
  287. data/lib/itsi/server/config.rb +260 -0
  288. data/lib/itsi/server/default_app/default_app.rb +34 -0
  289. data/lib/itsi/server/default_app/index.html +115 -0
  290. data/lib/itsi/server/default_config/Itsi-rackup.rb +119 -0
  291. data/lib/itsi/server/default_config/Itsi.rb +107 -0
  292. data/lib/itsi/server/grpc/grpc_call.rb +246 -0
  293. data/lib/itsi/server/grpc/grpc_interface.rb +100 -0
  294. data/lib/itsi/server/grpc/reflection/v1/reflection_pb.rb +26 -0
  295. data/lib/itsi/server/grpc/reflection/v1/reflection_services_pb.rb +122 -0
  296. data/lib/itsi/server/rack/handler/itsi.rb +27 -0
  297. data/lib/itsi/server/rack_interface.rb +94 -0
  298. data/lib/itsi/server/route_tester.rb +107 -0
  299. data/lib/itsi/server/scheduler_interface.rb +21 -0
  300. data/lib/itsi/server/scheduler_mode.rb +10 -0
  301. data/lib/itsi/server/signal_trap.rb +33 -0
  302. data/lib/itsi/server/typed_handlers/param_parser.rb +200 -0
  303. data/lib/itsi/server/typed_handlers/source_parser.rb +55 -0
  304. data/lib/itsi/server/typed_handlers.rb +17 -0
  305. data/lib/itsi/server/version.rb +1 -1
  306. data/lib/itsi/server.rb +181 -9
  307. data/lib/itsi/standard_headers.rb +86 -0
  308. data/lib/ruby_lsp/itsi/addon.rb +127 -0
  309. data/lib/shell_completions/completions.rb +26 -0
  310. metadata +321 -28
  311. data/CHANGELOG.md +0 -5
  312. data/CODE_OF_CONDUCT.md +0 -132
  313. data/LICENSE.txt +0 -21
  314. data/ext/itsi_server/src/request/itsi_request.rs +0 -143
  315. data/ext/itsi_server/src/request/mod.rs +0 -1
  316. data/ext/itsi_server/src/server/bind.rs +0 -138
  317. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -32
  318. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -52
  319. data/ext/itsi_server/src/server/itsi_server.rs +0 -182
  320. data/ext/itsi_server/src/server/listener.rs +0 -218
  321. data/ext/itsi_server/src/server/tls.rs +0 -138
  322. data/ext/itsi_server/src/server/transfer_protocol.rs +0 -23
  323. data/ext/itsi_server/src/stream_writer/mod.rs +0 -21
  324. data/lib/itsi/request.rb +0 -39
@@ -0,0 +1,506 @@
1
+ use super::file_watcher::{self};
2
+ use crate::{
3
+ ruby_types::ITSI_SERVER_CONFIG,
4
+ server::{
5
+ binds::{bind::Bind, listener::Listener},
6
+ middleware_stack::MiddlewareSet,
7
+ },
8
+ };
9
+ use derive_more::Debug;
10
+ use futures::executor::block_on;
11
+ use itsi_rb_helpers::{call_with_gvl, print_rb_backtrace, HeapValue};
12
+ use itsi_tracing::{set_format, set_level, set_target, set_target_filters};
13
+ use magnus::{
14
+ block::Proc,
15
+ error::Result,
16
+ value::{LazyId, ReprValue},
17
+ RArray, RHash, Ruby, Symbol, Value,
18
+ };
19
+ use nix::{
20
+ fcntl::{fcntl, FcntlArg, FdFlag},
21
+ unistd::{close, dup},
22
+ };
23
+ use parking_lot::{Mutex, RwLock};
24
+ use std::{
25
+ collections::HashMap,
26
+ os::fd::{AsRawFd, OwnedFd, RawFd},
27
+ path::PathBuf,
28
+ sync::{Arc, OnceLock},
29
+ time::Duration,
30
+ };
31
+ use tracing::{debug, error};
32
+ static DEFAULT_BIND: &str = "http://localhost:3000";
33
+ static ID_BUILD_CONFIG: LazyId = LazyId::new("build_config");
34
+ static ID_RELOAD_EXEC: LazyId = LazyId::new("reload_exec");
35
+
36
+ #[derive(Debug, Clone)]
37
+ pub struct ItsiServerConfig {
38
+ pub cli_params: Arc<HeapValue<RHash>>,
39
+ pub itsifile_path: Option<PathBuf>,
40
+ pub itsi_config_proc: Arc<Option<HeapValue<Proc>>>,
41
+ #[debug(skip)]
42
+ pub server_params: Arc<RwLock<Arc<ServerParams>>>,
43
+ pub watcher_fd: Arc<Option<OwnedFd>>,
44
+ }
45
+
46
+ #[derive(Debug)]
47
+ pub struct ServerParams {
48
+ /// Cluster params
49
+ pub workers: u8,
50
+ pub worker_memory_limit: Option<u64>,
51
+ pub silence: bool,
52
+ pub shutdown_timeout: f64,
53
+ pub hooks: HashMap<String, HeapValue<Proc>>,
54
+ pub preload: bool,
55
+
56
+ pub request_timeout: Option<Duration>,
57
+ pub header_read_timeout: Duration,
58
+ pub notify_watchers: Option<Vec<(String, Vec<Vec<String>>)>>,
59
+
60
+ /// Worker params
61
+ pub threads: u8,
62
+ pub scheduler_threads: Option<u8>,
63
+ pub streamable_body: bool,
64
+ pub multithreaded_reactor: bool,
65
+ pub pin_worker_cores: bool,
66
+ pub scheduler_class: Option<String>,
67
+ pub oob_gc_responses_threshold: Option<u64>,
68
+ pub middleware_loader: HeapValue<Proc>,
69
+ pub middleware: OnceLock<MiddlewareSet>,
70
+ pub binds: Vec<Bind>,
71
+ #[debug(skip)]
72
+ pub(crate) listeners: Mutex<Vec<Listener>>,
73
+ listener_info: Mutex<HashMap<String, i32>>,
74
+ }
75
+
76
+ pub struct SocketOpts {
77
+ pub reuse_address: bool,
78
+ pub reuse_port: bool,
79
+ pub listen_backlog: usize,
80
+ pub nodelay: bool,
81
+ pub recv_buffer_size: usize,
82
+ }
83
+
84
+ impl ServerParams {
85
+ pub fn preload_ruby(self: &Arc<Self>) -> Result<()> {
86
+ call_with_gvl(|ruby| -> Result<()> {
87
+ debug!("Preloading Ruby");
88
+ if self
89
+ .scheduler_class
90
+ .as_ref()
91
+ .is_some_and(|t| t == "Itsi::Scheduler")
92
+ {
93
+ debug!("Loading Itsi Scheduler");
94
+ ruby.require("itsi/scheduler")?;
95
+ }
96
+ let routes_raw = self
97
+ .middleware_loader
98
+ .call::<_, Option<Value>>(())
99
+ .inspect_err(|e| {
100
+ eprintln!("Error loading middleware: {:?}", e);
101
+ if let Some(err_value) = e.value() {
102
+ print_rb_backtrace(err_value);
103
+ }
104
+ })?
105
+ .map(|mw| mw.into());
106
+ debug!("Middleware routes returned");
107
+ let middleware = MiddlewareSet::new(routes_raw)?;
108
+ debug!("Middleware loaded");
109
+ self.middleware.set(middleware).map_err(|_| {
110
+ magnus::Error::new(
111
+ magnus::exception::runtime_error(),
112
+ "Failed to set middleware",
113
+ )
114
+ })?;
115
+ Ok(())
116
+ })?;
117
+ Ok(())
118
+ }
119
+
120
+ pub async fn initialize_middleware(self: &Arc<Self>) -> Result<()> {
121
+ self.middleware.get().unwrap().initialize_layers().await?;
122
+ Ok(())
123
+ }
124
+
125
+ fn from_rb_hash(rb_param_hash: RHash) -> Result<ServerParams> {
126
+ let workers = rb_param_hash
127
+ .fetch::<_, Option<u8>>("workers")?
128
+ .unwrap_or(num_cpus::get() as u8);
129
+ let worker_memory_limit: Option<u64> = rb_param_hash.fetch("worker_memory_limit")?;
130
+ let silence: bool = rb_param_hash.fetch("silence")?;
131
+ let multithreaded_reactor: bool = rb_param_hash
132
+ .fetch::<_, Option<bool>>("multithreaded_reactor")?
133
+ .unwrap_or(workers == 1);
134
+ let pin_worker_cores: bool = rb_param_hash
135
+ .fetch::<_, Option<bool>>("pin_worker_cores")?
136
+ .unwrap_or(true);
137
+ let shutdown_timeout: f64 = rb_param_hash.fetch("shutdown_timeout")?;
138
+
139
+ let hooks: Option<RHash> = rb_param_hash.fetch("hooks")?;
140
+ let hooks = hooks
141
+ .map(|rhash| -> Result<HashMap<String, HeapValue<Proc>>> {
142
+ let mut hook_map: HashMap<String, HeapValue<Proc>> = HashMap::new();
143
+ for pair in rhash.enumeratorize::<_, ()>("each", ()) {
144
+ if let Some(pair_value) = RArray::from_value(pair?) {
145
+ if let (Ok(key), Ok(value)) =
146
+ (pair_value.entry::<Value>(0), pair_value.entry::<Proc>(1))
147
+ {
148
+ hook_map.insert(key.to_string(), HeapValue::from(value));
149
+ }
150
+ }
151
+ }
152
+ Ok(hook_map)
153
+ })
154
+ .transpose()?
155
+ .unwrap_or_default();
156
+ let preload: bool = rb_param_hash.fetch("preload")?;
157
+ let request_timeout: Option<u64> = rb_param_hash.fetch("request_timeout")?;
158
+ let request_timeout = request_timeout.map(Duration::from_secs);
159
+ let header_read_timeout: Duration = rb_param_hash
160
+ .fetch::<_, Option<u64>>("header_read_timeout")?
161
+ .map(Duration::from_secs)
162
+ .unwrap_or(Duration::from_secs(1));
163
+
164
+ let notify_watchers: Option<Vec<(String, Vec<Vec<String>>)>> =
165
+ rb_param_hash.fetch("notify_watchers")?;
166
+ let threads: u8 = rb_param_hash.fetch("threads")?;
167
+ let scheduler_threads: Option<u8> = rb_param_hash.fetch("scheduler_threads")?;
168
+ let streamable_body: bool = rb_param_hash.fetch("streamable_body")?;
169
+ let scheduler_class: Option<String> = rb_param_hash.fetch("scheduler_class")?;
170
+ let oob_gc_responses_threshold: Option<u64> =
171
+ rb_param_hash.fetch("oob_gc_responses_threshold")?;
172
+ let middleware_loader: Proc = rb_param_hash.fetch("middleware_loader")?;
173
+ let log_level: Option<String> = rb_param_hash.fetch("log_level")?;
174
+ let log_target: Option<String> = rb_param_hash.fetch("log_target")?;
175
+ let log_format: Option<String> = rb_param_hash.fetch("log_format")?;
176
+ let log_target_filters: Option<Vec<String>> = rb_param_hash.fetch("log_target_filters")?;
177
+
178
+ let reuse_address: bool = rb_param_hash
179
+ .fetch::<_, Option<bool>>("reuse_address")?
180
+ .unwrap_or(true);
181
+ let reuse_port: bool = rb_param_hash
182
+ .fetch::<_, Option<bool>>("reuse_port")?
183
+ .unwrap_or(true);
184
+ let listen_backlog: usize = rb_param_hash
185
+ .fetch::<_, Option<usize>>("listen_backlog")?
186
+ .unwrap_or(1024);
187
+ let nodelay: bool = rb_param_hash
188
+ .fetch::<_, Option<bool>>("nodelay")?
189
+ .unwrap_or(true);
190
+ let recv_buffer_size: usize = rb_param_hash
191
+ .fetch::<_, Option<usize>>("recv_buffer_size")?
192
+ .unwrap_or(262_144);
193
+
194
+ if let Some(level) = log_level {
195
+ set_level(&level);
196
+ }
197
+
198
+ if let Some(target) = log_target {
199
+ set_target(&target);
200
+ }
201
+
202
+ if let Some(format) = log_format {
203
+ set_format(&format);
204
+ }
205
+
206
+ if let Some(target_filters) = log_target_filters {
207
+ let target_filters = target_filters
208
+ .iter()
209
+ .filter_map(|filter| {
210
+ let mut parts = filter.splitn(2, '=');
211
+ if let (Some(target), Some(level_str)) = (parts.next(), parts.next()) {
212
+ if let Ok(level) = level_str.parse::<tracing::Level>() {
213
+ return Some((target, level));
214
+ }
215
+ }
216
+ None
217
+ })
218
+ .collect::<Vec<(&str, tracing::Level)>>();
219
+ set_target_filters(target_filters);
220
+ }
221
+
222
+ let binds: Option<Vec<String>> = rb_param_hash.fetch("binds")?;
223
+ let binds = binds
224
+ .unwrap_or_else(|| vec![DEFAULT_BIND.to_string()])
225
+ .into_iter()
226
+ .map(|s| s.parse())
227
+ .collect::<itsi_error::Result<Vec<Bind>>>()?;
228
+
229
+ let socket_opts = SocketOpts {
230
+ reuse_address,
231
+ reuse_port,
232
+ listen_backlog,
233
+ nodelay,
234
+ recv_buffer_size,
235
+ };
236
+ let listeners = if let Some(preexisting_listeners) =
237
+ rb_param_hash.delete::<_, Option<String>>("listeners")?
238
+ {
239
+ let bind_to_fd_map: HashMap<String, i32> = serde_json::from_str(&preexisting_listeners)
240
+ .map_err(|e| {
241
+ magnus::Error::new(
242
+ magnus::exception::standard_error(),
243
+ format!("Invalid listener info: {}", e),
244
+ )
245
+ })?;
246
+
247
+ binds
248
+ .iter()
249
+ .cloned()
250
+ .map(|bind| {
251
+ if let Some(fd) = bind_to_fd_map.get(&bind.listener_address_string()) {
252
+ Listener::inherit_fd(bind, *fd, &socket_opts)
253
+ } else {
254
+ Listener::build(bind, &socket_opts)
255
+ }
256
+ })
257
+ .collect::<std::result::Result<Vec<Listener>, _>>()?
258
+ .into_iter()
259
+ .collect::<Vec<_>>()
260
+ } else {
261
+ binds
262
+ .iter()
263
+ .cloned()
264
+ .map(|b| Listener::build(b, &socket_opts))
265
+ .collect::<std::result::Result<Vec<Listener>, _>>()?
266
+ .into_iter()
267
+ .collect::<Vec<_>>()
268
+ };
269
+
270
+ let listener_info = listeners
271
+ .iter()
272
+ .map(|listener| {
273
+ listener.handover().map_err(|e| {
274
+ magnus::Error::new(magnus::exception::runtime_error(), e.to_string())
275
+ })
276
+ })
277
+ .collect::<Result<HashMap<String, i32>>>()?;
278
+
279
+ Ok(ServerParams {
280
+ workers,
281
+ worker_memory_limit,
282
+ silence,
283
+ multithreaded_reactor,
284
+ pin_worker_cores,
285
+ shutdown_timeout,
286
+ hooks,
287
+ preload,
288
+ request_timeout,
289
+ header_read_timeout,
290
+ notify_watchers,
291
+ threads,
292
+ scheduler_threads,
293
+ streamable_body,
294
+ scheduler_class,
295
+ oob_gc_responses_threshold,
296
+ binds,
297
+ listener_info: Mutex::new(listener_info),
298
+ listeners: Mutex::new(listeners),
299
+ middleware_loader: middleware_loader.into(),
300
+ middleware: OnceLock::new(),
301
+ })
302
+ }
303
+ }
304
+
305
+ impl ItsiServerConfig {
306
+ pub fn new(
307
+ ruby: &Ruby,
308
+ cli_params: RHash,
309
+ itsifile_path: Option<PathBuf>,
310
+ itsi_config_proc: Option<Proc>,
311
+ ) -> Result<Self> {
312
+ let itsi_config_proc = Arc::new(itsi_config_proc.map(HeapValue::from));
313
+ let server_params = Self::combine_params(
314
+ ruby,
315
+ cli_params,
316
+ itsifile_path.as_ref(),
317
+ itsi_config_proc.clone(),
318
+ )?;
319
+
320
+ cli_params.delete::<_, Value>(Symbol::new("listeners"))?;
321
+
322
+ let watcher_fd = if let Some(watchers) = server_params.notify_watchers.clone() {
323
+ file_watcher::watch_groups(watchers)?
324
+ } else {
325
+ None
326
+ };
327
+
328
+ Ok(ItsiServerConfig {
329
+ cli_params: Arc::new(cli_params.into()),
330
+ server_params: RwLock::new(server_params.clone()).into(),
331
+ itsi_config_proc,
332
+ itsifile_path,
333
+ watcher_fd: watcher_fd.into(),
334
+ })
335
+ }
336
+
337
+ /// Reload
338
+ pub fn reload(self: Arc<Self>, cluster_worker: bool) -> Result<bool> {
339
+ let server_params = call_with_gvl(|ruby| {
340
+ Self::combine_params(
341
+ &ruby,
342
+ self.cli_params.cloned(),
343
+ self.itsifile_path.as_ref(),
344
+ self.itsi_config_proc.clone(),
345
+ )
346
+ })?;
347
+ let is_single_mode = self.server_params.read().workers == 1;
348
+
349
+ let requires_exec = if !is_single_mode && !server_params.preload {
350
+ // In cluster mode children are cycled during a reload
351
+ // and if preload is disabled, will get a clean memory slate,
352
+ // so we don't need to exec.
353
+ false
354
+ } else {
355
+ // In non-cluster mode, or when preloading is enabled, we shouldn't try to
356
+ // reload inside the existing process (as new code may conflict with old),
357
+ // and should re-exec instead.
358
+ true
359
+ };
360
+
361
+ *self.server_params.write() = server_params.clone();
362
+ Ok(requires_exec && (cluster_worker || is_single_mode))
363
+ }
364
+
365
+ fn combine_params(
366
+ ruby: &Ruby,
367
+ cli_params: RHash,
368
+ itsifile_path: Option<&PathBuf>,
369
+ itsi_config_proc: Arc<Option<HeapValue<Proc>>>,
370
+ ) -> Result<Arc<ServerParams>> {
371
+ let inner = itsi_config_proc
372
+ .as_ref()
373
+ .clone()
374
+ .map(|hv| hv.clone().inner());
375
+ let (rb_param_hash, errors): (RHash, Vec<String>) =
376
+ ruby.get_inner_ref(&ITSI_SERVER_CONFIG).funcall(
377
+ *ID_BUILD_CONFIG,
378
+ (cli_params, itsifile_path.cloned(), inner),
379
+ )?;
380
+ if !errors.is_empty() {
381
+ Self::print_config_errors(errors);
382
+ return Err(magnus::Error::new(
383
+ magnus::exception::standard_error(),
384
+ "Invalid server config",
385
+ ));
386
+ }
387
+ Ok(Arc::new(ServerParams::from_rb_hash(rb_param_hash)?))
388
+ }
389
+
390
+ fn clear_cloexec(fd: RawFd) -> nix::Result<()> {
391
+ let current_flags = fcntl(fd, FcntlArg::F_GETFD)?;
392
+ let mut flags = FdFlag::from_bits_truncate(current_flags);
393
+ // Remove the FD_CLOEXEC flag
394
+ flags.remove(FdFlag::FD_CLOEXEC);
395
+ // Set the new flags back on the file descriptor
396
+ fcntl(fd, FcntlArg::F_SETFD(flags))?;
397
+ Ok(())
398
+ }
399
+
400
+ pub fn get_config_errors(&self) -> Option<Vec<String>> {
401
+ let rb_param_hash = call_with_gvl(|ruby| {
402
+ let inner = self
403
+ .itsi_config_proc
404
+ .as_ref()
405
+ .clone()
406
+ .map(|hv| hv.clone().inner());
407
+ let cli_params = self.cli_params.cloned();
408
+ let itsifile_path = self.itsifile_path.clone();
409
+
410
+ let (rb_param_hash, errors): (RHash, Vec<String>) = ruby
411
+ .get_inner_ref(&ITSI_SERVER_CONFIG)
412
+ .funcall(*ID_BUILD_CONFIG, (cli_params, itsifile_path, inner))
413
+ .unwrap();
414
+ if !errors.is_empty() {
415
+ return Err(errors);
416
+ }
417
+ Ok(rb_param_hash)
418
+ });
419
+ match rb_param_hash {
420
+ Ok(rb_param_hash) => match ServerParams::from_rb_hash(rb_param_hash) {
421
+ Ok(test_params) => {
422
+ let params_arc = Arc::new(test_params);
423
+ if let Err(err) = params_arc.clone().preload_ruby() {
424
+ let err_val = call_with_gvl(|_| format!("{}", err));
425
+ return Some(vec![err_val]);
426
+ }
427
+ if let Err(err) =
428
+ block_on(params_arc.middleware.get().unwrap().initialize_layers())
429
+ {
430
+ let err_val = call_with_gvl(|_| format!("{}", err));
431
+ return Some(vec![err_val]);
432
+ }
433
+ None
434
+ }
435
+ Err(err) => Some(vec![format!("{:?}", err)]),
436
+ },
437
+ Err(err) => Some(err),
438
+ }
439
+ }
440
+
441
+ pub fn dup_fds(self: &Arc<Self>) -> Result<()> {
442
+ let binding = self.server_params.read();
443
+ let mut listener_info_guard = binding.listener_info.lock();
444
+ let dupped_fd_map = listener_info_guard
445
+ .iter()
446
+ .map(|(str, fd)| {
447
+ let dupped_fd = dup(*fd).map_err(|errno| {
448
+ magnus::Error::new(
449
+ magnus::exception::standard_error(),
450
+ format!("Errno {} while trying to dup {}", errno, fd),
451
+ )
452
+ })?;
453
+ Self::clear_cloexec(dupped_fd).map_err(|e| {
454
+ magnus::Error::new(
455
+ magnus::exception::standard_error(),
456
+ format!("Failed to clear cloexec flag for fd {}: {}", dupped_fd, e),
457
+ )
458
+ })?;
459
+ Ok((str.clone(), dupped_fd))
460
+ })
461
+ .collect::<Result<HashMap<String, i32>>>()?;
462
+ *listener_info_guard = dupped_fd_map;
463
+ Ok(())
464
+ }
465
+
466
+ pub fn stop_watcher(self: &Arc<Self>) -> Result<()> {
467
+ if let Some(r_fd) = self.watcher_fd.as_ref() {
468
+ close(r_fd.as_raw_fd()).ok();
469
+ }
470
+ Ok(())
471
+ }
472
+
473
+ pub fn print_config_errors(errors: Vec<String>) {
474
+ error!("Refusing to reload configuration due to fatal errors:");
475
+ for error in errors {
476
+ eprintln!("{}", error);
477
+ }
478
+ }
479
+
480
+ pub fn check_config(&self) -> bool {
481
+ if let Some(errors) = self.get_config_errors() {
482
+ Self::print_config_errors(errors);
483
+ return false;
484
+ }
485
+ true
486
+ }
487
+
488
+ pub fn reload_exec(self: &Arc<Self>) -> Result<()> {
489
+ let listener_json =
490
+ serde_json::to_string(&self.server_params.read().listener_info.lock().clone())
491
+ .map_err(|e| {
492
+ magnus::Error::new(
493
+ magnus::exception::standard_error(),
494
+ format!("Invalid listener info: {}", e),
495
+ )
496
+ })?;
497
+
498
+ self.stop_watcher()?;
499
+ call_with_gvl(|ruby| -> Result<()> {
500
+ ruby.get_inner_ref(&ITSI_SERVER_CONFIG)
501
+ .funcall::<_, _, Value>(*ID_RELOAD_EXEC, (listener_json,))?;
502
+ Ok(())
503
+ })?;
504
+ Ok(())
505
+ }
506
+ }
@@ -0,0 +1,84 @@
1
+ use crate::server::{
2
+ lifecycle_event::LifecycleEvent,
3
+ serve_strategy::{cluster_mode::ClusterMode, single_mode::SingleMode, ServeStrategy},
4
+ signal::{clear_signal_handlers, reset_signal_handlers, send_lifecycle_event},
5
+ };
6
+ use itsi_rb_helpers::{call_without_gvl, print_rb_backtrace};
7
+ use itsi_server_config::ItsiServerConfig;
8
+ use itsi_tracing::{error, run_silently};
9
+ use magnus::{block::Proc, error::Result, RHash, Ruby};
10
+ use parking_lot::Mutex;
11
+ use std::{path::PathBuf, sync::Arc};
12
+ use tracing::{info, instrument};
13
+ mod file_watcher;
14
+ pub mod itsi_server_config;
15
+ #[magnus::wrap(class = "Itsi::Server", free_immediately, size)]
16
+ #[derive(Clone)]
17
+ pub struct ItsiServer {
18
+ pub config: Arc<Mutex<Arc<ItsiServerConfig>>>,
19
+ }
20
+
21
+ impl ItsiServer {
22
+ pub fn new(
23
+ ruby: &Ruby,
24
+ cli_params: RHash,
25
+ itsifile_path: Option<PathBuf>,
26
+ itsi_config_proc: Option<Proc>,
27
+ ) -> Result<Self> {
28
+ Ok(Self {
29
+ config: Arc::new(Mutex::new(Arc::new(ItsiServerConfig::new(
30
+ ruby,
31
+ cli_params,
32
+ itsifile_path,
33
+ itsi_config_proc,
34
+ )?))),
35
+ })
36
+ }
37
+
38
+ pub fn stop(&self) -> Result<()> {
39
+ send_lifecycle_event(LifecycleEvent::Shutdown);
40
+ Ok(())
41
+ }
42
+
43
+ #[instrument(skip(self))]
44
+ pub fn start(&self) -> Result<()> {
45
+ let result = if self.config.lock().server_params.read().silence {
46
+ run_silently(|| self.build_and_run_strategy())
47
+ } else {
48
+ info!("Itsi - Rolling into action. ⚪💨");
49
+ self.build_and_run_strategy()
50
+ };
51
+ if let Err(e) = result {
52
+ if let Some(err_value) = e.value() {
53
+ print_rb_backtrace(err_value);
54
+ }
55
+ return Err(e);
56
+ }
57
+ Ok(())
58
+ }
59
+
60
+ pub(crate) fn build_strategy(&self) -> Result<ServeStrategy> {
61
+ let server_config = self.config.lock();
62
+ Ok(if server_config.server_params.read().workers > 1 {
63
+ ServeStrategy::Cluster(Arc::new(ClusterMode::new(server_config.clone())))
64
+ } else {
65
+ ServeStrategy::Single(Arc::new(SingleMode::new(server_config.clone())?))
66
+ })
67
+ }
68
+
69
+ fn build_and_run_strategy(&self) -> Result<()> {
70
+ reset_signal_handlers();
71
+ call_without_gvl(move || -> Result<()> {
72
+ let strategy = self.build_strategy()?;
73
+ if let Err(e) = strategy.clone().run() {
74
+ error!("Error running server: {}", e);
75
+ send_lifecycle_event(LifecycleEvent::Shutdown);
76
+ strategy.stop()?;
77
+ }
78
+ Ok(())
79
+ })?;
80
+ clear_signal_handlers();
81
+ info!("Server stopped");
82
+ Ok(())
83
+ }
84
+ }
@@ -0,0 +1,48 @@
1
+ use magnus::{value::Lazy, Module, RClass, RModule};
2
+
3
+ pub mod itsi_body_proxy;
4
+ pub mod itsi_grpc_call;
5
+ pub mod itsi_grpc_response_stream;
6
+ pub mod itsi_http_request;
7
+ pub mod itsi_http_response;
8
+ pub mod itsi_server;
9
+
10
+ pub static ITSI_MODULE: Lazy<RModule> = Lazy::new(|ruby| ruby.define_module("Itsi").unwrap());
11
+ pub static ITSI_SERVER: Lazy<RClass> = Lazy::new(|ruby| {
12
+ ruby.get_inner(&ITSI_MODULE)
13
+ .define_class("Server", ruby.class_object())
14
+ .unwrap()
15
+ });
16
+
17
+ pub static ITSI_SERVER_CONFIG: Lazy<RModule> =
18
+ Lazy::new(|ruby| ruby.get_inner(&ITSI_SERVER).const_get("Config").unwrap());
19
+
20
+ pub static ITSI_REQUEST: Lazy<RClass> = Lazy::new(|ruby| {
21
+ ruby.get_inner(&ITSI_MODULE)
22
+ .define_class("HttpRequest", ruby.class_object())
23
+ .unwrap()
24
+ });
25
+
26
+ pub static ITSI_RESPONSE: Lazy<RClass> = Lazy::new(|ruby| {
27
+ ruby.get_inner(&ITSI_MODULE)
28
+ .define_class("HttpResponse", ruby.class_object())
29
+ .unwrap()
30
+ });
31
+
32
+ pub static ITSI_BODY_PROXY: Lazy<RClass> = Lazy::new(|ruby| {
33
+ ruby.get_inner(&ITSI_MODULE)
34
+ .define_class("BodyProxy", ruby.class_object())
35
+ .unwrap()
36
+ });
37
+
38
+ pub static ITSI_GRPC_CALL: Lazy<RClass> = Lazy::new(|ruby| {
39
+ ruby.get_inner(&ITSI_MODULE)
40
+ .define_class("GrpcCall", ruby.class_object())
41
+ .unwrap()
42
+ });
43
+
44
+ pub static ITSI_GRPC_RESPONSE_STREAM: Lazy<RClass> = Lazy::new(|ruby| {
45
+ ruby.get_inner(&ITSI_MODULE)
46
+ .define_class("GrpcResponseStream", ruby.class_object())
47
+ .unwrap()
48
+ });