itsi-server 0.2.22-aarch64-linux

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 (451) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +8 -0
  3. data/Cargo.lock +4452 -0
  4. data/Cargo.toml +11 -0
  5. data/Rakefile +57 -0
  6. data/exe/itsi +193 -0
  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.lock +368 -0
  30. data/ext/itsi_error/Cargo.toml +12 -0
  31. data/ext/itsi_error/src/lib.rs +140 -0
  32. data/ext/itsi_instrument_entry/Cargo.toml +15 -0
  33. data/ext/itsi_instrument_entry/src/lib.rs +31 -0
  34. data/ext/itsi_rb_helpers/Cargo.lock +355 -0
  35. data/ext/itsi_rb_helpers/Cargo.toml +11 -0
  36. data/ext/itsi_rb_helpers/src/heap_value.rs +139 -0
  37. data/ext/itsi_rb_helpers/src/lib.rs +232 -0
  38. data/ext/itsi_scheduler/Cargo.toml +24 -0
  39. data/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +56 -0
  40. data/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +44 -0
  41. data/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +44 -0
  42. data/ext/itsi_scheduler/src/itsi_scheduler.rs +320 -0
  43. data/ext/itsi_scheduler/src/lib.rs +39 -0
  44. data/ext/itsi_server/Cargo.lock +2956 -0
  45. data/ext/itsi_server/Cargo.toml +94 -0
  46. data/ext/itsi_server/extconf.rb +11 -0
  47. data/ext/itsi_server/src/default_responses/html/401.html +68 -0
  48. data/ext/itsi_server/src/default_responses/html/403.html +68 -0
  49. data/ext/itsi_server/src/default_responses/html/404.html +68 -0
  50. data/ext/itsi_server/src/default_responses/html/413.html +71 -0
  51. data/ext/itsi_server/src/default_responses/html/429.html +68 -0
  52. data/ext/itsi_server/src/default_responses/html/500.html +71 -0
  53. data/ext/itsi_server/src/default_responses/html/502.html +71 -0
  54. data/ext/itsi_server/src/default_responses/html/503.html +68 -0
  55. data/ext/itsi_server/src/default_responses/html/504.html +69 -0
  56. data/ext/itsi_server/src/default_responses/html/index.html +238 -0
  57. data/ext/itsi_server/src/default_responses/json/401.json +6 -0
  58. data/ext/itsi_server/src/default_responses/json/403.json +6 -0
  59. data/ext/itsi_server/src/default_responses/json/404.json +6 -0
  60. data/ext/itsi_server/src/default_responses/json/413.json +6 -0
  61. data/ext/itsi_server/src/default_responses/json/429.json +6 -0
  62. data/ext/itsi_server/src/default_responses/json/500.json +6 -0
  63. data/ext/itsi_server/src/default_responses/json/502.json +6 -0
  64. data/ext/itsi_server/src/default_responses/json/503.json +6 -0
  65. data/ext/itsi_server/src/default_responses/json/504.json +6 -0
  66. data/ext/itsi_server/src/default_responses/mod.rs +14 -0
  67. data/ext/itsi_server/src/env.rs +43 -0
  68. data/ext/itsi_server/src/lib.rs +154 -0
  69. data/ext/itsi_server/src/prelude.rs +2 -0
  70. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/big_bytes.rs +116 -0
  71. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +149 -0
  72. data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +346 -0
  73. data/ext/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +265 -0
  74. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +399 -0
  75. data/ext/itsi_server/src/ruby_types/itsi_http_response.rs +447 -0
  76. data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +545 -0
  77. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +650 -0
  78. data/ext/itsi_server/src/ruby_types/itsi_server.rs +102 -0
  79. data/ext/itsi_server/src/ruby_types/mod.rs +48 -0
  80. data/ext/itsi_server/src/server/binds/bind.rs +204 -0
  81. data/ext/itsi_server/src/server/binds/bind_protocol.rs +37 -0
  82. data/ext/itsi_server/src/server/binds/listener.rs +485 -0
  83. data/ext/itsi_server/src/server/binds/mod.rs +4 -0
  84. data/ext/itsi_server/src/server/binds/tls/locked_dir_cache.rs +132 -0
  85. data/ext/itsi_server/src/server/binds/tls.rs +278 -0
  86. data/ext/itsi_server/src/server/byte_frame.rs +32 -0
  87. data/ext/itsi_server/src/server/frame_stream.rs +143 -0
  88. data/ext/itsi_server/src/server/http_message_types.rs +230 -0
  89. data/ext/itsi_server/src/server/io_stream.rs +128 -0
  90. data/ext/itsi_server/src/server/lifecycle_event.rs +12 -0
  91. data/ext/itsi_server/src/server/middleware_stack/middleware.rs +170 -0
  92. data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +63 -0
  93. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +94 -0
  94. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +93 -0
  95. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +343 -0
  96. data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +151 -0
  97. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +329 -0
  98. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +300 -0
  99. data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +193 -0
  100. data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +64 -0
  101. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +188 -0
  102. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +168 -0
  103. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +183 -0
  104. data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +82 -0
  105. data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +209 -0
  106. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +133 -0
  107. data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
  108. data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +122 -0
  109. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +407 -0
  110. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +155 -0
  111. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +54 -0
  112. data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +54 -0
  113. data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +51 -0
  114. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +138 -0
  115. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +269 -0
  116. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +62 -0
  117. data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +218 -0
  118. data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +31 -0
  119. data/ext/itsi_server/src/server/middleware_stack/mod.rs +381 -0
  120. data/ext/itsi_server/src/server/mod.rs +14 -0
  121. data/ext/itsi_server/src/server/process_worker.rs +247 -0
  122. data/ext/itsi_server/src/server/redirect_type.rs +26 -0
  123. data/ext/itsi_server/src/server/request_job.rs +11 -0
  124. data/ext/itsi_server/src/server/serve_strategy/acceptor.rs +100 -0
  125. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +411 -0
  126. data/ext/itsi_server/src/server/serve_strategy/mod.rs +31 -0
  127. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +449 -0
  128. data/ext/itsi_server/src/server/signal.rs +129 -0
  129. data/ext/itsi_server/src/server/size_limited_incoming.rs +107 -0
  130. data/ext/itsi_server/src/server/thread_worker.rs +504 -0
  131. data/ext/itsi_server/src/services/cache_store.rs +74 -0
  132. data/ext/itsi_server/src/services/itsi_http_service.rs +270 -0
  133. data/ext/itsi_server/src/services/mime_types.rs +2896 -0
  134. data/ext/itsi_server/src/services/mod.rs +6 -0
  135. data/ext/itsi_server/src/services/password_hasher.rs +89 -0
  136. data/ext/itsi_server/src/services/rate_limiter.rs +609 -0
  137. data/ext/itsi_server/src/services/static_file_server.rs +1400 -0
  138. data/ext/itsi_tracing/Cargo.lock +274 -0
  139. data/ext/itsi_tracing/Cargo.toml +17 -0
  140. data/ext/itsi_tracing/src/lib.rs +370 -0
  141. data/lib/itsi/http_request/response_status_shortcodes.rb +76 -0
  142. data/lib/itsi/http_request.rb +228 -0
  143. data/lib/itsi/http_response.rb +49 -0
  144. data/lib/itsi/passfile.rb +108 -0
  145. data/lib/itsi/rack_env_pool.rb +49 -0
  146. data/lib/itsi/server/3.1/itsi_server.so +0 -0
  147. data/lib/itsi/server/3.2/itsi_server.so +0 -0
  148. data/lib/itsi/server/3.3/itsi_server.so +0 -0
  149. data/lib/itsi/server/3.4/itsi_server.so +0 -0
  150. data/lib/itsi/server/4.0/itsi_server.so +0 -0
  151. data/lib/itsi/server/config/config_helpers.rb +116 -0
  152. data/lib/itsi/server/config/dsl.rb +208 -0
  153. data/lib/itsi/server/config/known_paths/KitchensinkDirectories.txt +2346 -0
  154. data/lib/itsi/server/config/known_paths/Randomfiles.txt +24 -0
  155. data/lib/itsi/server/config/known_paths/UnixDotfiles.txt +52 -0
  156. data/lib/itsi/server/config/known_paths/backdoors/ASP_CommonBackdoors.txt +29 -0
  157. data/lib/itsi/server/config/known_paths/backdoors/bot_control_panels.txt +1668 -0
  158. data/lib/itsi/server/config/known_paths/backdoors/shells.txt +1167 -0
  159. data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST.txt +7 -0
  160. data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST_Windows.txt +6 -0
  161. data/lib/itsi/server/config/known_paths/cgi/CGI_Microsoft.txt +79 -0
  162. data/lib/itsi/server/config/known_paths/cgi/CGI_XPlatform.txt +3948 -0
  163. data/lib/itsi/server/config/known_paths/cms/README.md +5 -0
  164. data/lib/itsi/server/config/known_paths/cms/drupal_plugins.txt +6320 -0
  165. data/lib/itsi/server/config/known_paths/cms/drupal_themes.txt +828 -0
  166. data/lib/itsi/server/config/known_paths/cms/joomla_plugins.txt +224 -0
  167. data/lib/itsi/server/config/known_paths/cms/joomla_themes.txt +30 -0
  168. data/lib/itsi/server/config/known_paths/cms/php-nuke.txt +2142 -0
  169. data/lib/itsi/server/config/known_paths/cms/wordpress.txt +1566 -0
  170. data/lib/itsi/server/config/known_paths/cms/wp_common_theme_files.txt +46 -0
  171. data/lib/itsi/server/config/known_paths/cms/wp_plugins.txt +13366 -0
  172. data/lib/itsi/server/config/known_paths/cms/wp_plugins_full.txt +68662 -0
  173. data/lib/itsi/server/config/known_paths/cms/wp_plugins_top225.txt +225 -0
  174. data/lib/itsi/server/config/known_paths/cms/wp_themes.readme +12 -0
  175. data/lib/itsi/server/config/known_paths/cms/wp_themes.txt +7336 -0
  176. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/3CharExtBrute.txt +17576 -0
  177. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/CommonWebExtensions.txt +80 -0
  178. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Backup.txt +14 -0
  179. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Common.txt +865 -0
  180. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Compressed.txt +186 -0
  181. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Mostcommon.txt +30 -0
  182. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Skipfish.txt +93 -0
  183. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/WordlistSkipfish.txt +1918 -0
  184. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/copy_of.txt +8 -0
  185. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories-lowercase.txt +56180 -0
  186. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories.txt +62290 -0
  187. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions-lowercase.txt +2367 -0
  188. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions.txt +2450 -0
  189. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files-lowercase.txt +35323 -0
  190. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files.txt +37037 -0
  191. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words-lowercase.txt +107982 -0
  192. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words.txt +119600 -0
  193. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories-lowercase.txt +26593 -0
  194. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories.txt +30009 -0
  195. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions-lowercase.txt +1233 -0
  196. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions.txt +1289 -0
  197. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files-lowercase.txt +16243 -0
  198. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files.txt +17128 -0
  199. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words-lowercase.txt +56293 -0
  200. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words.txt +63087 -0
  201. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories-lowercase.txt +17776 -0
  202. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories.txt +20122 -0
  203. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions-lowercase.txt +914 -0
  204. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions.txt +963 -0
  205. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files-lowercase.txt +10848 -0
  206. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files.txt +11424 -0
  207. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words-lowercase.txt +38267 -0
  208. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words.txt +43003 -0
  209. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/spanish.txt +445 -0
  210. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/test_demo.txt +36 -0
  211. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/upload_variants.txt +44 -0
  212. data/lib/itsi/server/config/known_paths/login-file-locations/Logins.txt +71 -0
  213. data/lib/itsi/server/config/known_paths/login-file-locations/cfm.txt +294 -0
  214. data/lib/itsi/server/config/known_paths/login-file-locations/html.txt +295 -0
  215. data/lib/itsi/server/config/known_paths/login-file-locations/jsp.txt +294 -0
  216. data/lib/itsi/server/config/known_paths/login-file-locations/php.txt +294 -0
  217. data/lib/itsi/server/config/known_paths/login-file-locations/windows-asp.txt +294 -0
  218. data/lib/itsi/server/config/known_paths/login-file-locations/windows-aspx.txt +294 -0
  219. data/lib/itsi/server/config/known_paths/password-file-locations/Passwords.txt +47 -0
  220. data/lib/itsi/server/config/known_paths/php/PHP.txt +30 -0
  221. data/lib/itsi/server/config/known_paths/php/PHP_CommonBackdoors.txt +5 -0
  222. data/lib/itsi/server/config/known_paths/proxy-conf.txt +31 -0
  223. data/lib/itsi/server/config/known_paths/tftp.txt +79 -0
  224. data/lib/itsi/server/config/known_paths/webservers-appservers/ADFS.txt +86 -0
  225. data/lib/itsi/server/config/known_paths/webservers-appservers/AdobeXML.txt +16 -0
  226. data/lib/itsi/server/config/known_paths/webservers-appservers/Apache.txt +101 -0
  227. data/lib/itsi/server/config/known_paths/webservers-appservers/ApacheTomcat.txt +47 -0
  228. data/lib/itsi/server/config/known_paths/webservers-appservers/Apache_Axis.txt +16 -0
  229. data/lib/itsi/server/config/known_paths/webservers-appservers/ColdFusion.txt +111 -0
  230. data/lib/itsi/server/config/known_paths/webservers-appservers/FatwireCMS.txt +390 -0
  231. data/lib/itsi/server/config/known_paths/webservers-appservers/Frontpage.txt +38 -0
  232. data/lib/itsi/server/config/known_paths/webservers-appservers/HP_System_Mgmt_Homepage.txt +239 -0
  233. data/lib/itsi/server/config/known_paths/webservers-appservers/HTTP_POST_Microsoft.txt +2 -0
  234. data/lib/itsi/server/config/known_paths/webservers-appservers/Hyperion.txt +578 -0
  235. data/lib/itsi/server/config/known_paths/webservers-appservers/IIS.txt +187 -0
  236. data/lib/itsi/server/config/known_paths/webservers-appservers/JBoss.txt +5 -0
  237. data/lib/itsi/server/config/known_paths/webservers-appservers/JRun.txt +13 -0
  238. data/lib/itsi/server/config/known_paths/webservers-appservers/JavaServlets_Common.txt +3 -0
  239. data/lib/itsi/server/config/known_paths/webservers-appservers/Joomla_exploitable.txt +1937 -0
  240. data/lib/itsi/server/config/known_paths/webservers-appservers/LotusNotes.txt +206 -0
  241. data/lib/itsi/server/config/known_paths/webservers-appservers/Netware.txt +18 -0
  242. data/lib/itsi/server/config/known_paths/webservers-appservers/Oracle9i.txt +60 -0
  243. data/lib/itsi/server/config/known_paths/webservers-appservers/OracleAppServer.txt +192 -0
  244. data/lib/itsi/server/config/known_paths/webservers-appservers/README.md +6 -0
  245. data/lib/itsi/server/config/known_paths/webservers-appservers/Ruby_Rails.txt +121 -0
  246. data/lib/itsi/server/config/known_paths/webservers-appservers/SAP.txt +463 -0
  247. data/lib/itsi/server/config/known_paths/webservers-appservers/Sharepoint.txt +1707 -0
  248. data/lib/itsi/server/config/known_paths/webservers-appservers/SiteMinder.txt +19 -0
  249. data/lib/itsi/server/config/known_paths/webservers-appservers/SunAppServerGlassfish.txt +51 -0
  250. data/lib/itsi/server/config/known_paths/webservers-appservers/SuniPlanet.txt +35 -0
  251. data/lib/itsi/server/config/known_paths/webservers-appservers/Vignette.txt +73 -0
  252. data/lib/itsi/server/config/known_paths/webservers-appservers/Weblogic.txt +160 -0
  253. data/lib/itsi/server/config/known_paths/webservers-appservers/Websphere.txt +366 -0
  254. data/lib/itsi/server/config/known_paths/wellknown-rfc5785.txt +30 -0
  255. data/lib/itsi/server/config/known_paths.rb +24 -0
  256. data/lib/itsi/server/config/middleware/_index.md +56 -0
  257. data/lib/itsi/server/config/middleware/allow_list.md +46 -0
  258. data/lib/itsi/server/config/middleware/allow_list.rb +42 -0
  259. data/lib/itsi/server/config/middleware/auth_api_key.md +90 -0
  260. data/lib/itsi/server/config/middleware/auth_api_key.rb +51 -0
  261. data/lib/itsi/server/config/middleware/auth_basic.md +45 -0
  262. data/lib/itsi/server/config/middleware/auth_basic.rb +46 -0
  263. data/lib/itsi/server/config/middleware/auth_jwt.md +82 -0
  264. data/lib/itsi/server/config/middleware/auth_jwt.rb +38 -0
  265. data/lib/itsi/server/config/middleware/cache_control.md +78 -0
  266. data/lib/itsi/server/config/middleware/cache_control.rb +45 -0
  267. data/lib/itsi/server/config/middleware/cidr_to_regex.rb +50 -0
  268. data/lib/itsi/server/config/middleware/compression.md +50 -0
  269. data/lib/itsi/server/config/middleware/compression.rb +37 -0
  270. data/lib/itsi/server/config/middleware/cors.md +93 -0
  271. data/lib/itsi/server/config/middleware/cors.rb +32 -0
  272. data/lib/itsi/server/config/middleware/csp.md +37 -0
  273. data/lib/itsi/server/config/middleware/csp.rb +44 -0
  274. data/lib/itsi/server/config/middleware/deny_list.md +45 -0
  275. data/lib/itsi/server/config/middleware/deny_list.rb +42 -0
  276. data/lib/itsi/server/config/middleware/endpoint/_index.md +160 -0
  277. data/lib/itsi/server/config/middleware/endpoint/controller.md +186 -0
  278. data/lib/itsi/server/config/middleware/endpoint/controller.rb +33 -0
  279. data/lib/itsi/server/config/middleware/endpoint/delete.md +12 -0
  280. data/lib/itsi/server/config/middleware/endpoint/delete.rb +43 -0
  281. data/lib/itsi/server/config/middleware/endpoint/endpoint.rb +106 -0
  282. data/lib/itsi/server/config/middleware/endpoint/get.md +12 -0
  283. data/lib/itsi/server/config/middleware/endpoint/get.rb +43 -0
  284. data/lib/itsi/server/config/middleware/endpoint/http_request.md +44 -0
  285. data/lib/itsi/server/config/middleware/endpoint/http_response.md +39 -0
  286. data/lib/itsi/server/config/middleware/endpoint/patch.md +12 -0
  287. data/lib/itsi/server/config/middleware/endpoint/patch.rb +43 -0
  288. data/lib/itsi/server/config/middleware/endpoint/post.md +12 -0
  289. data/lib/itsi/server/config/middleware/endpoint/post.rb +43 -0
  290. data/lib/itsi/server/config/middleware/endpoint/put.md +12 -0
  291. data/lib/itsi/server/config/middleware/endpoint/put.rb +43 -0
  292. data/lib/itsi/server/config/middleware/endpoint/schemas.md +122 -0
  293. data/lib/itsi/server/config/middleware/error_response.md +74 -0
  294. data/lib/itsi/server/config/middleware/error_response.rb +36 -0
  295. data/lib/itsi/server/config/middleware/etag.md +55 -0
  296. data/lib/itsi/server/config/middleware/etag.rb +25 -0
  297. data/lib/itsi/server/config/middleware/grpc.md +170 -0
  298. data/lib/itsi/server/config/middleware/grpc.rb +54 -0
  299. data/lib/itsi/server/config/middleware/intrusion_protection.md +124 -0
  300. data/lib/itsi/server/config/middleware/intrusion_protection.rb +61 -0
  301. data/lib/itsi/server/config/middleware/location.md +107 -0
  302. data/lib/itsi/server/config/middleware/location.rb +103 -0
  303. data/lib/itsi/server/config/middleware/log_requests.md +67 -0
  304. data/lib/itsi/server/config/middleware/log_requests.rb +31 -0
  305. data/lib/itsi/server/config/middleware/max_body.md +18 -0
  306. data/lib/itsi/server/config/middleware/max_body.rb +21 -0
  307. data/lib/itsi/server/config/middleware/proxy.md +62 -0
  308. data/lib/itsi/server/config/middleware/proxy.rb +42 -0
  309. data/lib/itsi/server/config/middleware/rackup_file.md +72 -0
  310. data/lib/itsi/server/config/middleware/rackup_file.rb +43 -0
  311. data/lib/itsi/server/config/middleware/rate_limit.md +126 -0
  312. data/lib/itsi/server/config/middleware/rate_limit.rb +34 -0
  313. data/lib/itsi/server/config/middleware/rate_limit_store.rb +25 -0
  314. data/lib/itsi/server/config/middleware/redirect.md +55 -0
  315. data/lib/itsi/server/config/middleware/redirect.rb +25 -0
  316. data/lib/itsi/server/config/middleware/request_headers.md +34 -0
  317. data/lib/itsi/server/config/middleware/request_headers.rb +24 -0
  318. data/lib/itsi/server/config/middleware/response_headers.md +33 -0
  319. data/lib/itsi/server/config/middleware/response_headers.rb +25 -0
  320. data/lib/itsi/server/config/middleware/run.md +79 -0
  321. data/lib/itsi/server/config/middleware/run.rb +45 -0
  322. data/lib/itsi/server/config/middleware/static_assets.md +113 -0
  323. data/lib/itsi/server/config/middleware/static_assets.rb +99 -0
  324. data/lib/itsi/server/config/middleware/static_response.md +44 -0
  325. data/lib/itsi/server/config/middleware/static_response.rb +30 -0
  326. data/lib/itsi/server/config/middleware/string_rewrite.md +81 -0
  327. data/lib/itsi/server/config/middleware/token_source.rb +32 -0
  328. data/lib/itsi/server/config/middleware.rb +13 -0
  329. data/lib/itsi/server/config/option.rb +13 -0
  330. data/lib/itsi/server/config/options/_index.md +41 -0
  331. data/lib/itsi/server/config/options/auto_reload_config.md +13 -0
  332. data/lib/itsi/server/config/options/auto_reload_config.rb +46 -0
  333. data/lib/itsi/server/config/options/bind.md +71 -0
  334. data/lib/itsi/server/config/options/bind.rb +26 -0
  335. data/lib/itsi/server/config/options/certificates.md +65 -0
  336. data/lib/itsi/server/config/options/daemonize.md +14 -0
  337. data/lib/itsi/server/config/options/daemonize.rb +19 -0
  338. data/lib/itsi/server/config/options/fiber_scheduler.md +34 -0
  339. data/lib/itsi/server/config/options/fiber_scheduler.rb +21 -0
  340. data/lib/itsi/server/config/options/header_read_timeout.md +17 -0
  341. data/lib/itsi/server/config/options/header_read_timeout.rb +19 -0
  342. data/lib/itsi/server/config/options/hooks/_index.md +11 -0
  343. data/lib/itsi/server/config/options/hooks/after_fork.md +13 -0
  344. data/lib/itsi/server/config/options/hooks/after_fork.rb +28 -0
  345. data/lib/itsi/server/config/options/hooks/after_memory_limit_reached.md +14 -0
  346. data/lib/itsi/server/config/options/hooks/after_memory_limit_reached.rb +28 -0
  347. data/lib/itsi/server/config/options/hooks/after_start.md +12 -0
  348. data/lib/itsi/server/config/options/hooks/after_start.rb +28 -0
  349. data/lib/itsi/server/config/options/hooks/before_fork.md +13 -0
  350. data/lib/itsi/server/config/options/hooks/before_fork.rb +28 -0
  351. data/lib/itsi/server/config/options/hooks/before_restart.md +12 -0
  352. data/lib/itsi/server/config/options/hooks/before_restart.rb +28 -0
  353. data/lib/itsi/server/config/options/hooks/before_shutdown.md +12 -0
  354. data/lib/itsi/server/config/options/hooks/before_shutdown.rb +28 -0
  355. data/lib/itsi/server/config/options/include.md +21 -0
  356. data/lib/itsi/server/config/options/include.rb +41 -0
  357. data/lib/itsi/server/config/options/listen_backlog.md +11 -0
  358. data/lib/itsi/server/config/options/listen_backlog.rb +19 -0
  359. data/lib/itsi/server/config/options/log_format.md +18 -0
  360. data/lib/itsi/server/config/options/log_format.rb +19 -0
  361. data/lib/itsi/server/config/options/log_level.md +34 -0
  362. data/lib/itsi/server/config/options/log_level.rb +20 -0
  363. data/lib/itsi/server/config/options/log_target.md +38 -0
  364. data/lib/itsi/server/config/options/log_target.rb +19 -0
  365. data/lib/itsi/server/config/options/log_target_filters.md +17 -0
  366. data/lib/itsi/server/config/options/log_target_filters.rb +19 -0
  367. data/lib/itsi/server/config/options/multithreaded_reactor.md +27 -0
  368. data/lib/itsi/server/config/options/multithreaded_reactor.rb +24 -0
  369. data/lib/itsi/server/config/options/nodelay.md +16 -0
  370. data/lib/itsi/server/config/options/nodelay.rb +19 -0
  371. data/lib/itsi/server/config/options/oob_gc_responses_threshold.md +19 -0
  372. data/lib/itsi/server/config/options/oob_gc_responses_threshold.rb +18 -0
  373. data/lib/itsi/server/config/options/pin_worker_cores.md +17 -0
  374. data/lib/itsi/server/config/options/pin_worker_cores.rb +19 -0
  375. data/lib/itsi/server/config/options/pipeline_flush.md +16 -0
  376. data/lib/itsi/server/config/options/pipeline_flush.rb +19 -0
  377. data/lib/itsi/server/config/options/preload.md +21 -0
  378. data/lib/itsi/server/config/options/preload.rb +18 -0
  379. data/lib/itsi/server/config/options/recv_buffer_size.md +15 -0
  380. data/lib/itsi/server/config/options/recv_buffer_size.rb +19 -0
  381. data/lib/itsi/server/config/options/redirect_http_to_https.md +21 -0
  382. data/lib/itsi/server/config/options/redirect_http_to_https.rb +30 -0
  383. data/lib/itsi/server/config/options/request_timeout.md +23 -0
  384. data/lib/itsi/server/config/options/request_timeout.rb +19 -0
  385. data/lib/itsi/server/config/options/reuse_address.md +18 -0
  386. data/lib/itsi/server/config/options/reuse_address.rb +19 -0
  387. data/lib/itsi/server/config/options/reuse_port.md +18 -0
  388. data/lib/itsi/server/config/options/reuse_port.rb +17 -0
  389. data/lib/itsi/server/config/options/ruby_thread_request_backlog_size.md +18 -0
  390. data/lib/itsi/server/config/options/ruby_thread_request_backlog_size.rb +19 -0
  391. data/lib/itsi/server/config/options/scheduler_threads.md +41 -0
  392. data/lib/itsi/server/config/options/scheduler_threads.rb +17 -0
  393. data/lib/itsi/server/config/options/send_buffer_size.md +15 -0
  394. data/lib/itsi/server/config/options/send_buffer_size.rb +19 -0
  395. data/lib/itsi/server/config/options/shutdown_timeout.md +17 -0
  396. data/lib/itsi/server/config/options/shutdown_timeout.rb +19 -0
  397. data/lib/itsi/server/config/options/stream_body.md +32 -0
  398. data/lib/itsi/server/config/options/stream_body.rb +18 -0
  399. data/lib/itsi/server/config/options/threads.md +44 -0
  400. data/lib/itsi/server/config/options/threads.rb +17 -0
  401. data/lib/itsi/server/config/options/watch.md +16 -0
  402. data/lib/itsi/server/config/options/watch.rb +28 -0
  403. data/lib/itsi/server/config/options/worker_memory_limit.md +22 -0
  404. data/lib/itsi/server/config/options/worker_memory_limit.rb +18 -0
  405. data/lib/itsi/server/config/options/workers.md +42 -0
  406. data/lib/itsi/server/config/options/workers.rb +17 -0
  407. data/lib/itsi/server/config/options/writev.md +25 -0
  408. data/lib/itsi/server/config/options/writev.rb +19 -0
  409. data/lib/itsi/server/config/typed_struct.rb +239 -0
  410. data/lib/itsi/server/config.rb +321 -0
  411. data/lib/itsi/server/default_app/default_app.rb +34 -0
  412. data/lib/itsi/server/default_app/index.html +115 -0
  413. data/lib/itsi/server/default_config/Itsi.rb +108 -0
  414. data/lib/itsi/server/grpc/grpc_call.rb +247 -0
  415. data/lib/itsi/server/grpc/grpc_interface.rb +106 -0
  416. data/lib/itsi/server/grpc/reflection/v1/reflection_pb.rb +26 -0
  417. data/lib/itsi/server/grpc/reflection/v1/reflection_services_pb.rb +122 -0
  418. data/lib/itsi/server/native_extension.rb +34 -0
  419. data/lib/itsi/server/rack/handler/itsi.rb +29 -0
  420. data/lib/itsi/server/rack_interface.rb +109 -0
  421. data/lib/itsi/server/route_tester.rb +159 -0
  422. data/lib/itsi/server/scheduler_interface.rb +23 -0
  423. data/lib/itsi/server/scheduler_mode.rb +10 -0
  424. data/lib/itsi/server/signal_trap.rb +33 -0
  425. data/lib/itsi/server/typed_handlers/param_parser.rb +221 -0
  426. data/lib/itsi/server/typed_handlers/source_parser.rb +58 -0
  427. data/lib/itsi/server/typed_handlers.rb +25 -0
  428. data/lib/itsi/server/version.rb +7 -0
  429. data/lib/itsi/server.rb +288 -0
  430. data/lib/itsi/standard_headers.rb +86 -0
  431. data/lib/ruby_lsp/itsi/addon.rb +128 -0
  432. data/lib/shell_completions/completions.rb +26 -0
  433. data/vendor/rb-sys-build/.cargo-ok +1 -0
  434. data/vendor/rb-sys-build/.cargo_vcs_info.json +6 -0
  435. data/vendor/rb-sys-build/Cargo.lock +294 -0
  436. data/vendor/rb-sys-build/Cargo.toml +71 -0
  437. data/vendor/rb-sys-build/Cargo.toml.orig +32 -0
  438. data/vendor/rb-sys-build/LICENSE-APACHE +190 -0
  439. data/vendor/rb-sys-build/LICENSE-MIT +21 -0
  440. data/vendor/rb-sys-build/src/bindings/sanitizer.rs +185 -0
  441. data/vendor/rb-sys-build/src/bindings/stable_api.rs +247 -0
  442. data/vendor/rb-sys-build/src/bindings/wrapper.h +71 -0
  443. data/vendor/rb-sys-build/src/bindings.rs +280 -0
  444. data/vendor/rb-sys-build/src/cc.rs +421 -0
  445. data/vendor/rb-sys-build/src/lib.rs +12 -0
  446. data/vendor/rb-sys-build/src/rb_config/flags.rs +101 -0
  447. data/vendor/rb-sys-build/src/rb_config/library.rs +132 -0
  448. data/vendor/rb-sys-build/src/rb_config/search_path.rs +57 -0
  449. data/vendor/rb-sys-build/src/rb_config.rs +906 -0
  450. data/vendor/rb-sys-build/src/utils.rs +53 -0
  451. metadata +569 -0
@@ -0,0 +1,650 @@
1
+ use super::file_watcher::{self, WatcherCommand};
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 itsi_error::ItsiError;
11
+ use itsi_rb_helpers::{call_with_gvl, print_rb_backtrace, HeapValue};
12
+ use itsi_tracing::{error, 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, TryConvert, Value,
18
+ };
19
+ use nix::{
20
+ fcntl::{fcntl, FcntlArg, FdFlag},
21
+ unistd::dup,
22
+ };
23
+ use parking_lot::{Mutex, RwLock};
24
+ use std::{
25
+ collections::HashMap,
26
+ os::fd::RawFd,
27
+ path::PathBuf,
28
+ str::FromStr,
29
+ sync::{
30
+ atomic::{AtomicBool, Ordering::Relaxed},
31
+ Arc, OnceLock,
32
+ },
33
+ time::Duration,
34
+ };
35
+ use tracing::debug;
36
+ static DEFAULT_BIND: &str = "http://localhost:3000";
37
+ static ID_BUILD_CONFIG: LazyId = LazyId::new("build_config");
38
+ static ID_RELOAD_EXEC: LazyId = LazyId::new("reload_exec");
39
+
40
+ #[derive(Debug, Clone)]
41
+ pub struct ItsiServerConfig {
42
+ pub cli_params: Arc<HeapValue<RHash>>,
43
+ pub itsifile_path: Option<PathBuf>,
44
+ pub itsi_config_proc: Arc<Option<HeapValue<Proc>>>,
45
+ #[debug(skip)]
46
+ pub server_params: Arc<RwLock<Arc<ServerParams>>>,
47
+ pub watcher_fd: Arc<Option<file_watcher::WatcherPipes>>,
48
+ }
49
+
50
+ #[derive(Debug)]
51
+ pub struct ServerParams {
52
+ /// Cluster params
53
+ pub workers: u8,
54
+ pub worker_memory_limit: Option<u64>,
55
+ pub silence: bool,
56
+ pub shutdown_timeout: f64,
57
+ pub hooks: HashMap<String, HeapValue<Proc>>,
58
+ pub preload: bool,
59
+
60
+ pub request_timeout: Option<Duration>,
61
+ pub header_read_timeout: Duration,
62
+ pub notify_watchers: Option<Vec<(String, Vec<Vec<String>>)>>,
63
+
64
+ /// Worker params
65
+ pub threads: u8,
66
+ pub scheduler_threads: Option<u8>,
67
+ pub streamable_body: bool,
68
+ pub multithreaded_reactor: bool,
69
+ pub pin_worker_cores: bool,
70
+ pub scheduler_class: Option<String>,
71
+ pub oob_gc_responses_threshold: Option<u64>,
72
+ pub ruby_thread_request_backlog_size: Option<usize>,
73
+ pub middleware_loader: HeapValue<Proc>,
74
+ pub middleware: OnceLock<MiddlewareSet>,
75
+ pub pipeline_flush: bool,
76
+ pub writev: Option<bool>,
77
+ pub max_concurrent_streams: Option<u32>,
78
+ pub max_local_error_reset_streams: Option<usize>,
79
+ pub max_header_list_size: u32,
80
+ pub max_send_buf_size: usize,
81
+ pub binds: Vec<Bind>,
82
+ #[debug(skip)]
83
+ pub(crate) listeners: Mutex<Vec<Listener>>,
84
+ listener_info: Mutex<HashMap<String, i32>>,
85
+ pub itsi_server_token_preference: ItsiServerTokenPreference,
86
+ pub preloaded: AtomicBool,
87
+ pub socket_opts: SocketOpts,
88
+ preexisting_listeners: Option<String>,
89
+ }
90
+
91
+ #[derive(Debug, Clone, Copy)]
92
+ pub enum ItsiServerTokenPreference {
93
+ Version,
94
+ Name,
95
+ None,
96
+ }
97
+
98
+ impl FromStr for ItsiServerTokenPreference {
99
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
100
+ Ok(match s {
101
+ "version" => ItsiServerTokenPreference::Version,
102
+ "name" => ItsiServerTokenPreference::Name,
103
+ "none" => ItsiServerTokenPreference::None,
104
+ _ => ItsiServerTokenPreference::Version,
105
+ })
106
+ }
107
+
108
+ type Err = ItsiError;
109
+ }
110
+
111
+ #[derive(Debug, Clone)]
112
+ pub struct SocketOpts {
113
+ pub reuse_address: bool,
114
+ pub reuse_port: bool,
115
+ pub listen_backlog: usize,
116
+ pub nodelay: bool,
117
+ pub recv_buffer_size: usize,
118
+ pub send_buffer_size: usize,
119
+ }
120
+
121
+ impl ServerParams {
122
+ pub fn preload_ruby(self: &Arc<Self>) -> Result<()> {
123
+ if self.preloaded.load(Relaxed) {
124
+ return Ok(());
125
+ }
126
+ call_with_gvl(|ruby| -> Result<()> {
127
+ if self
128
+ .scheduler_class
129
+ .as_ref()
130
+ .is_some_and(|t| t == "Itsi::Scheduler")
131
+ {
132
+ debug!("Loading Itsi Scheduler");
133
+ ruby.require("itsi/scheduler")?;
134
+ }
135
+ let result_pair = self
136
+ .middleware_loader
137
+ .call::<(), RArray>(())
138
+ .inspect_err(|e| {
139
+ eprintln!("Error loading middleware: {:?}", e);
140
+ if let Some(err_value) = e.value() {
141
+ print_rb_backtrace(err_value);
142
+ }
143
+ })?;
144
+ let routes_raw = result_pair
145
+ .entry::<Option<Value>>(0)
146
+ .inspect_err(|e| {
147
+ eprintln!("Error loading middleware: {:?}", e);
148
+ if let Some(err_value) = e.value() {
149
+ print_rb_backtrace(err_value);
150
+ }
151
+ })?
152
+ .map(|mw| mw.into());
153
+ let error_lines = result_pair.entry::<Option<RArray>>(1).inspect_err(|e| {
154
+ eprintln!("Error loading middleware: {:?}", e);
155
+ if let Some(err_value) = e.value() {
156
+ print_rb_backtrace(err_value);
157
+ }
158
+ })?;
159
+ if error_lines.is_some_and(|r| !r.is_empty()) {
160
+ let errors: Vec<String> =
161
+ Vec::<String>::try_convert(error_lines.unwrap().as_value())?;
162
+ ItsiServerConfig::print_config_errors(errors);
163
+ return Err(magnus::Error::new(
164
+ magnus::Ruby::get().unwrap().exception_runtime_error(),
165
+ "Failed to set middleware",
166
+ ));
167
+ }
168
+ let middleware = MiddlewareSet::new(routes_raw)?;
169
+ self.middleware.set(middleware).map_err(|_| {
170
+ magnus::Error::new(
171
+ magnus::Ruby::get().unwrap().exception_runtime_error(),
172
+ "Failed to set middleware",
173
+ )
174
+ })?;
175
+ Ok(())
176
+ })?;
177
+ self.preloaded.store(true, Relaxed);
178
+ Ok(())
179
+ }
180
+
181
+ pub async fn initialize_middleware(self: &Arc<Self>) -> Result<()> {
182
+ self.middleware.get().unwrap().initialize_layers().await?;
183
+ Ok(())
184
+ }
185
+
186
+ fn from_rb_hash(rb_param_hash: RHash) -> Result<ServerParams> {
187
+ let num_cpus = num_cpus::get_physical() as u8;
188
+ let workers = rb_param_hash
189
+ .fetch::<_, Option<u8>>("workers")?
190
+ .unwrap_or(num_cpus);
191
+ let worker_memory_limit: Option<u64> = rb_param_hash.fetch("worker_memory_limit")?;
192
+ let silence: bool = rb_param_hash.fetch("silence")?;
193
+ let multithreaded_reactor: bool = rb_param_hash
194
+ .fetch::<_, Option<bool>>("multithreaded_reactor")?
195
+ .unwrap_or(workers <= (num_cpus / 3));
196
+ let pin_worker_cores: bool = rb_param_hash
197
+ .fetch::<_, Option<bool>>("pin_worker_cores")?
198
+ .unwrap_or(false);
199
+ let shutdown_timeout: f64 = rb_param_hash.fetch("shutdown_timeout")?;
200
+ let hooks: Option<RHash> = rb_param_hash.fetch("hooks")?;
201
+ let hooks = hooks
202
+ .map(|rhash| -> Result<HashMap<String, HeapValue<Proc>>> {
203
+ let mut hook_map: HashMap<String, HeapValue<Proc>> = HashMap::new();
204
+ for pair in rhash.enumeratorize::<_, ()>("each", ()) {
205
+ if let Some(pair_value) = RArray::from_value(pair?) {
206
+ if let (Ok(key), Ok(value)) =
207
+ (pair_value.entry::<Value>(0), pair_value.entry::<Proc>(1))
208
+ {
209
+ hook_map.insert(key.to_string(), HeapValue::from(value));
210
+ }
211
+ }
212
+ }
213
+ Ok(hook_map)
214
+ })
215
+ .transpose()?
216
+ .unwrap_or_default();
217
+ let preload: bool = rb_param_hash.fetch("preload")?;
218
+ let request_timeout: Option<f64> = rb_param_hash.fetch("request_timeout")?;
219
+ let request_timeout = request_timeout.map(Duration::from_secs_f64);
220
+ let header_read_timeout: Duration = rb_param_hash
221
+ .fetch::<_, Option<f64>>("header_read_timeout")?
222
+ .map(Duration::from_secs_f64)
223
+ .unwrap_or(Duration::from_secs(1));
224
+
225
+ let notify_watchers: Option<Vec<(String, Vec<Vec<String>>)>> =
226
+ rb_param_hash.fetch("notify_watchers")?;
227
+ let threads: u8 = rb_param_hash.fetch("threads")?;
228
+ let scheduler_threads: Option<u8> = rb_param_hash.fetch("scheduler_threads")?;
229
+ let streamable_body: bool = rb_param_hash.fetch("streamable_body")?;
230
+ let scheduler_class: Option<String> = rb_param_hash.fetch("scheduler_class")?;
231
+ let oob_gc_responses_threshold: Option<u64> =
232
+ rb_param_hash.fetch("oob_gc_responses_threshold")?;
233
+
234
+ let ruby_thread_request_backlog_size: Option<usize> =
235
+ rb_param_hash.fetch("ruby_thread_request_backlog_size")?;
236
+
237
+ let middleware_loader: Proc = rb_param_hash.fetch("middleware_loader")?;
238
+ let log_level: Option<String> = rb_param_hash.fetch("log_level")?;
239
+ let log_target: Option<String> = rb_param_hash.fetch("log_target")?;
240
+ let log_format: Option<String> = rb_param_hash.fetch("log_format")?;
241
+ let log_target_filters: Option<Vec<String>> = rb_param_hash.fetch("log_target_filters")?;
242
+
243
+ let reuse_address: bool = rb_param_hash
244
+ .fetch::<_, Option<bool>>("reuse_address")?
245
+ .unwrap_or(true);
246
+ let reuse_port: bool = rb_param_hash
247
+ .fetch::<_, Option<bool>>("reuse_port")?
248
+ .unwrap_or(true);
249
+ let listen_backlog: usize = rb_param_hash
250
+ .fetch::<_, Option<usize>>("listen_backlog")?
251
+ .unwrap_or(1024);
252
+ let nodelay: bool = rb_param_hash
253
+ .fetch::<_, Option<bool>>("nodelay")?
254
+ .unwrap_or(true);
255
+ let recv_buffer_size: usize = rb_param_hash
256
+ .fetch::<_, Option<usize>>("recv_buffer_size")?
257
+ .unwrap_or(262_144);
258
+ let send_buffer_size: usize = rb_param_hash
259
+ .fetch::<_, Option<usize>>("send_buffer_size")?
260
+ .unwrap_or(262_144);
261
+
262
+ if let Some(level) = log_level {
263
+ set_level(&level);
264
+ }
265
+
266
+ if let Some(target) = log_target {
267
+ set_target(&target);
268
+ }
269
+
270
+ if let Some(format) = log_format {
271
+ set_format(&format);
272
+ }
273
+
274
+ if let Some(target_filters) = log_target_filters {
275
+ let target_filters = target_filters
276
+ .iter()
277
+ .filter_map(|filter| {
278
+ let mut parts = filter.splitn(2, '=');
279
+ if let (Some(target), Some(level_str)) = (parts.next(), parts.next()) {
280
+ if let Ok(level) = level_str.parse::<tracing::Level>() {
281
+ return Some((target, level));
282
+ }
283
+ }
284
+ None
285
+ })
286
+ .collect::<Vec<(&str, tracing::Level)>>();
287
+ set_target_filters(target_filters);
288
+ }
289
+
290
+ let pipeline_flush: bool = rb_param_hash.fetch("pipeline_flush")?;
291
+ let writev: Option<bool> = rb_param_hash.fetch("writev")?;
292
+ let max_concurrent_streams: Option<u32> = rb_param_hash.fetch("max_concurrent_streams")?;
293
+ let max_local_error_reset_streams: Option<usize> =
294
+ rb_param_hash.fetch("max_local_error_reset_streams")?;
295
+ let max_header_list_size: u32 = rb_param_hash.fetch("max_header_list_size")?;
296
+ let max_send_buf_size: usize = rb_param_hash.fetch("max_send_buf_size")?;
297
+
298
+ let binds: Option<Vec<String>> = rb_param_hash.fetch("binds")?;
299
+ let binds = binds
300
+ .unwrap_or_else(|| vec![DEFAULT_BIND.to_string()])
301
+ .into_iter()
302
+ .map(|s| s.parse())
303
+ .collect::<itsi_error::Result<Vec<Bind>>>()?;
304
+
305
+ let itsi_server_token_preference: String = rb_param_hash
306
+ .fetch("itsi_server_token_preference")
307
+ .unwrap_or_default();
308
+ let itsi_server_token_preference: ItsiServerTokenPreference =
309
+ itsi_server_token_preference.parse()?;
310
+
311
+ let socket_opts = SocketOpts {
312
+ reuse_address,
313
+ reuse_port,
314
+ listen_backlog,
315
+ nodelay,
316
+ recv_buffer_size,
317
+ send_buffer_size,
318
+ };
319
+ let preexisting_listeners = rb_param_hash.delete::<_, Option<String>>("listeners")?;
320
+
321
+ let params = ServerParams {
322
+ workers,
323
+ worker_memory_limit,
324
+ silence,
325
+ multithreaded_reactor,
326
+ pin_worker_cores,
327
+ shutdown_timeout,
328
+ hooks,
329
+ preload,
330
+ request_timeout,
331
+ header_read_timeout,
332
+ notify_watchers,
333
+ threads,
334
+ scheduler_threads,
335
+ streamable_body,
336
+ scheduler_class,
337
+ ruby_thread_request_backlog_size,
338
+ oob_gc_responses_threshold,
339
+ pipeline_flush,
340
+ writev,
341
+ max_concurrent_streams,
342
+ max_local_error_reset_streams,
343
+ max_header_list_size,
344
+ max_send_buf_size,
345
+ binds,
346
+ itsi_server_token_preference,
347
+ socket_opts,
348
+ preexisting_listeners,
349
+ listener_info: Mutex::new(HashMap::new()),
350
+ listeners: Mutex::new(Vec::new()),
351
+ middleware_loader: middleware_loader.into(),
352
+ middleware: OnceLock::new(),
353
+ preloaded: AtomicBool::new(false),
354
+ };
355
+
356
+ Ok(params)
357
+ }
358
+
359
+ pub fn setup_listeners(&self) -> Result<()> {
360
+ let listeners = if let Some(preexisting_listeners) = self.preexisting_listeners.as_ref() {
361
+ let bind_to_fd_map: HashMap<String, i32> = serde_json::from_str(preexisting_listeners)
362
+ .map_err(|e| {
363
+ magnus::Error::new(
364
+ magnus::Ruby::get().unwrap().exception_standard_error(),
365
+ format!("Invalid listener info: {}", e),
366
+ )
367
+ })?;
368
+
369
+ self.binds
370
+ .iter()
371
+ .cloned()
372
+ .map(|bind| {
373
+ if let Some(fd) = bind_to_fd_map.get(&bind.listener_address_string()) {
374
+ Listener::inherit_fd(bind, *fd, &self.socket_opts)
375
+ } else {
376
+ Listener::build(bind, &self.socket_opts)
377
+ }
378
+ })
379
+ .collect::<std::result::Result<Vec<Listener>, _>>()?
380
+ .into_iter()
381
+ .collect::<Vec<_>>()
382
+ } else {
383
+ self.binds
384
+ .iter()
385
+ .cloned()
386
+ .map(|b| Listener::build(b, &self.socket_opts))
387
+ .collect::<std::result::Result<Vec<Listener>, _>>()?
388
+ .into_iter()
389
+ .collect::<Vec<_>>()
390
+ };
391
+
392
+ let listener_info = listeners
393
+ .iter()
394
+ .map(|listener| {
395
+ listener.handover().map_err(|e| {
396
+ magnus::Error::new(
397
+ magnus::Ruby::get().unwrap().exception_runtime_error(),
398
+ e.to_string(),
399
+ )
400
+ })
401
+ })
402
+ .collect::<Result<HashMap<String, i32>>>()?;
403
+
404
+ *self.listener_info.lock() = listener_info;
405
+ *self.listeners.lock() = listeners;
406
+ Ok(())
407
+ }
408
+ }
409
+
410
+ impl ItsiServerConfig {
411
+ pub fn new(
412
+ ruby: &Ruby,
413
+ cli_params: RHash,
414
+ itsifile_path: Option<PathBuf>,
415
+ itsi_config_proc: Option<Proc>,
416
+ ) -> Result<Self> {
417
+ let itsi_config_proc = Arc::new(itsi_config_proc.map(HeapValue::from));
418
+ match Self::combine_params(
419
+ ruby,
420
+ cli_params,
421
+ itsifile_path.as_ref(),
422
+ itsi_config_proc.clone(),
423
+ ) {
424
+ Ok(server_params) => {
425
+ cli_params
426
+ .delete::<_, Value>(magnus::Ruby::get().unwrap().to_symbol("listeners"))?;
427
+
428
+ let watcher_fd = if let Some(watchers) = server_params.notify_watchers.clone() {
429
+ file_watcher::watch_groups(watchers)?
430
+ } else {
431
+ None
432
+ };
433
+
434
+ Ok(ItsiServerConfig {
435
+ cli_params: Arc::new(cli_params.into()),
436
+ server_params: RwLock::new(server_params.clone()).into(),
437
+ itsi_config_proc,
438
+ itsifile_path,
439
+ watcher_fd: watcher_fd.into(),
440
+ })
441
+ }
442
+ Err(err) => Err(magnus::Error::new(
443
+ magnus::Ruby::get().unwrap().exception_standard_error(),
444
+ format!("Error loading initial configuration {:?}", err),
445
+ )),
446
+ }
447
+ }
448
+
449
+ pub fn use_reuse_port_load_balancing(&self) -> bool {
450
+ cfg!(target_os = "linux") && self.server_params.read().socket_opts.reuse_port
451
+ }
452
+
453
+ /// Reload
454
+ pub fn reload(self: Arc<Self>, cluster_worker: bool) -> Result<bool> {
455
+ let server_params = call_with_gvl(|ruby| {
456
+ Self::combine_params(
457
+ &ruby,
458
+ self.cli_params.cloned(),
459
+ self.itsifile_path.as_ref(),
460
+ self.itsi_config_proc.clone(),
461
+ )
462
+ })?;
463
+ let is_single_mode = self.server_params.read().workers == 1;
464
+
465
+ let requires_exec = if !is_single_mode && !server_params.preload {
466
+ // In cluster mode children are cycled during a reload
467
+ // and if preload is disabled, will get a clean memory slate,
468
+ // so we don't need to exec. We do need to rebind our listeners here.
469
+ server_params.setup_listeners()?;
470
+ false
471
+ } else {
472
+ // In non-cluster mode, or when preloading is enabled, we shouldn't try to
473
+ // reload inside the existing process (as new code may conflict with old),
474
+ // and should re-exec instead.
475
+ true
476
+ };
477
+
478
+ *self.server_params.write() = server_params.clone();
479
+ Ok(requires_exec && (cluster_worker || is_single_mode))
480
+ }
481
+
482
+ fn combine_params(
483
+ ruby: &Ruby,
484
+ cli_params: RHash,
485
+ itsifile_path: Option<&PathBuf>,
486
+ itsi_config_proc: Arc<Option<HeapValue<Proc>>>,
487
+ ) -> Result<Arc<ServerParams>> {
488
+ let inner = itsi_config_proc
489
+ .as_ref()
490
+ .clone()
491
+ .map(|hv| hv.clone().inner());
492
+ let (rb_param_hash, errors): (RHash, Vec<String>) =
493
+ ruby.get_inner_ref(&ITSI_SERVER_CONFIG).funcall(
494
+ *ID_BUILD_CONFIG,
495
+ (cli_params, itsifile_path.cloned(), inner),
496
+ )?;
497
+ if !errors.is_empty() {
498
+ Self::print_config_errors(errors);
499
+ return Err(magnus::Error::new(
500
+ magnus::Ruby::get().unwrap().exception_standard_error(),
501
+ "Invalid server config",
502
+ ));
503
+ }
504
+ Ok(Arc::new(ServerParams::from_rb_hash(rb_param_hash)?))
505
+ }
506
+
507
+ fn clear_cloexec(fd: RawFd) -> nix::Result<()> {
508
+ let current_flags = fcntl(fd, FcntlArg::F_GETFD)?;
509
+ let mut flags = FdFlag::from_bits_truncate(current_flags);
510
+ // Remove the FD_CLOEXEC flag
511
+ flags.remove(FdFlag::FD_CLOEXEC);
512
+ // Set the new flags back on the file descriptor
513
+ fcntl(fd, FcntlArg::F_SETFD(flags))?;
514
+ Ok(())
515
+ }
516
+
517
+ pub async fn get_config_errors(&self) -> Option<Vec<String>> {
518
+ let rb_param_hash = call_with_gvl(|ruby| {
519
+ let inner = self
520
+ .itsi_config_proc
521
+ .as_ref()
522
+ .clone()
523
+ .map(|hv| hv.clone().inner());
524
+ let cli_params = self.cli_params.cloned();
525
+ let itsifile_path = self.itsifile_path.clone();
526
+
527
+ let (rb_param_hash, errors): (RHash, Vec<String>) = ruby
528
+ .get_inner_ref(&ITSI_SERVER_CONFIG)
529
+ .funcall(*ID_BUILD_CONFIG, (cli_params, itsifile_path, inner))
530
+ .unwrap();
531
+ if !errors.is_empty() {
532
+ return Err(errors);
533
+ }
534
+ Ok(rb_param_hash)
535
+ });
536
+ match rb_param_hash {
537
+ Ok(rb_param_hash) => match ServerParams::from_rb_hash(rb_param_hash) {
538
+ Ok(test_params) => {
539
+ let params_arc = Arc::new(test_params);
540
+ if let Err(err) = params_arc.clone().preload_ruby() {
541
+ let err_val = call_with_gvl(|_| format!("{}", err));
542
+ return Some(vec![err_val]);
543
+ }
544
+
545
+ if let Err(err) = params_arc
546
+ .middleware
547
+ .get()
548
+ .unwrap()
549
+ .initialize_layers()
550
+ .await
551
+ {
552
+ let err_val = call_with_gvl(|_| format!("{}", err));
553
+ return Some(vec![err_val]);
554
+ }
555
+ None
556
+ }
557
+ Err(err) => Some(vec![format!("{:?}", err)]),
558
+ },
559
+ Err(err) => Some(err),
560
+ }
561
+ }
562
+
563
+ pub fn dup_fds(self: &Arc<Self>) -> Result<()> {
564
+ // Ensure the watcher is already stopped before duplicating file descriptors
565
+ // to prevent race conditions between closing the watcher FD and duplicating socket FDs
566
+
567
+ let binding = self.server_params.read();
568
+ let mut listener_info_guard = binding.listener_info.lock();
569
+ let dupped_fd_map = listener_info_guard
570
+ .iter()
571
+ .map(|(str, fd)| {
572
+ let dupped_fd = dup(*fd).map_err(|errno| {
573
+ magnus::Error::new(
574
+ magnus::Ruby::get().unwrap().exception_standard_error(),
575
+ format!("Errno {} while trying to dup {}", errno, fd),
576
+ )
577
+ })?;
578
+ Self::clear_cloexec(dupped_fd).map_err(|e| {
579
+ magnus::Error::new(
580
+ magnus::Ruby::get().unwrap().exception_standard_error(),
581
+ format!("Failed to clear cloexec flag for fd {}: {}", dupped_fd, e),
582
+ )
583
+ })?;
584
+ Ok((str.clone(), dupped_fd))
585
+ })
586
+ .collect::<Result<HashMap<String, i32>>>()?;
587
+ *listener_info_guard = dupped_fd_map;
588
+ Ok(())
589
+ }
590
+
591
+ pub fn stop_watcher(self: &Arc<Self>) -> Result<()> {
592
+ if let Some(pipes) = self.watcher_fd.as_ref() {
593
+ // Send explicit stop command to the watcher process
594
+ file_watcher::send_watcher_command(&pipes.write_fd, WatcherCommand::Stop)?;
595
+ // We don't close the pipes here - they'll be closed when the WatcherPipes is dropped
596
+ }
597
+ Ok(())
598
+ }
599
+
600
+ pub fn print_config_errors(errors: Vec<String>) {
601
+ error!("Refusing to reload configuration due to fatal errors:");
602
+ for error in errors {
603
+ eprintln!("{}", error);
604
+ }
605
+ }
606
+
607
+ pub async fn check_config(&self) -> bool {
608
+ if let Some(errors) = self.get_config_errors().await {
609
+ Self::print_config_errors(errors);
610
+ // Notify watcher that config check failed
611
+ if let Some(pipes) = self.watcher_fd.as_ref() {
612
+ if let Err(e) =
613
+ file_watcher::send_watcher_command(&pipes.write_fd, WatcherCommand::ConfigError)
614
+ {
615
+ error!("Failed to notify watcher of config error: {}", e);
616
+ }
617
+ }
618
+ return false;
619
+ }
620
+ // If we reach here, the config is valid
621
+ if let Some(pipes) = self.watcher_fd.as_ref() {
622
+ if let Err(e) =
623
+ file_watcher::send_watcher_command(&pipes.write_fd, WatcherCommand::Continue)
624
+ {
625
+ error!("Failed to notify watcher to continue: {}", e);
626
+ }
627
+ }
628
+ true
629
+ }
630
+
631
+ pub fn reload_exec(self: &Arc<Self>) -> Result<()> {
632
+ let listener_json =
633
+ serde_json::to_string(&self.server_params.read().listener_info.lock().clone())
634
+ .map_err(|e| {
635
+ magnus::Error::new(
636
+ magnus::Ruby::get().unwrap().exception_standard_error(),
637
+ format!("Invalid listener info: {}", e),
638
+ )
639
+ })?;
640
+
641
+ // Make sure we're not calling stop_watcher here to avoid double-stopping
642
+ // The watcher should be stopped earlier in the restart sequence
643
+ call_with_gvl(|ruby| -> Result<()> {
644
+ ruby.get_inner_ref(&ITSI_SERVER_CONFIG)
645
+ .funcall::<_, _, Value>(*ID_RELOAD_EXEC, (listener_json,))?;
646
+ Ok(())
647
+ })?;
648
+ Ok(())
649
+ }
650
+ }