itsi-server 0.1.1 → 0.2.2

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 (457) 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 +7 -4
  6. data/exe/itsi +152 -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 +141 -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 +314 -0
  65. data/ext/itsi_scheduler/src/lib.rs +39 -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 +133 -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 +362 -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 +233 -0
  99. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +565 -0
  100. data/ext/itsi_server/src/ruby_types/itsi_server.rs +86 -0
  101. data/ext/itsi_server/src/ruby_types/mod.rs +48 -0
  102. data/ext/itsi_server/src/server/binds/bind.rs +204 -0
  103. data/ext/itsi_server/src/server/binds/bind_protocol.rs +37 -0
  104. data/ext/itsi_server/src/server/binds/listener.rs +444 -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 +278 -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 +63 -0
  114. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +94 -0
  115. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +94 -0
  116. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +343 -0
  117. data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +151 -0
  118. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +316 -0
  119. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +301 -0
  120. data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +193 -0
  121. data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +64 -0
  122. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +192 -0
  123. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +171 -0
  124. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +198 -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 +209 -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 +116 -0
  130. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +411 -0
  131. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +142 -0
  132. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +55 -0
  133. data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +54 -0
  134. data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +51 -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 +187 -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 +173 -0
  139. data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +31 -0
  140. data/ext/itsi_server/src/server/middleware_stack/mod.rs +381 -0
  141. data/ext/itsi_server/src/server/mod.rs +13 -5
  142. data/ext/itsi_server/src/server/process_worker.rs +247 -0
  143. data/ext/itsi_server/src/server/redirect_type.rs +26 -0
  144. data/ext/itsi_server/src/server/request_job.rs +11 -0
  145. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +354 -0
  146. data/ext/itsi_server/src/server/serve_strategy/mod.rs +30 -0
  147. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +481 -0
  148. data/ext/itsi_server/src/server/signal.rs +77 -0
  149. data/ext/itsi_server/src/server/size_limited_incoming.rs +107 -0
  150. data/ext/itsi_server/src/server/thread_worker.rs +479 -0
  151. data/ext/itsi_server/src/services/cache_store.rs +74 -0
  152. data/ext/itsi_server/src/services/itsi_http_service.rs +257 -0
  153. data/ext/itsi_server/src/services/mime_types.rs +1416 -0
  154. data/ext/itsi_server/src/services/mod.rs +6 -0
  155. data/ext/itsi_server/src/services/password_hasher.rs +83 -0
  156. data/ext/itsi_server/src/services/rate_limiter.rs +580 -0
  157. data/ext/itsi_server/src/services/static_file_server.rs +1340 -0
  158. data/ext/itsi_tracing/Cargo.toml +5 -0
  159. data/ext/itsi_tracing/src/lib.rs +366 -7
  160. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0994n8rpvvt9m/s-h510hfz1f6-1kbycmq.lock +0 -0
  161. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0bob7bf4yq34i/s-h5113125h5-0lh4rag.lock +0 -0
  162. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2fcodulrxbbxo/s-h510h2infk-0hp5kjw.lock +0 -0
  163. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2iak63r1woi1l/s-h510h2in4q-0kxfzw1.lock +0 -0
  164. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2kk4qj9gn5dg2/s-h5113124kv-0enwon2.lock +0 -0
  165. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2mwo0yas7dtw4/s-h510hfz1ha-1udgpei.lock +0 -0
  166. data/lib/itsi/http_request/response_status_shortcodes.rb +76 -0
  167. data/lib/itsi/http_request.rb +218 -0
  168. data/lib/itsi/http_response.rb +42 -0
  169. data/lib/itsi/passfile.rb +108 -0
  170. data/lib/itsi/server/config/config_helpers.rb +105 -0
  171. data/lib/itsi/server/config/dsl.rb +211 -0
  172. data/lib/itsi/server/config/known_paths/KitchensinkDirectories.txt +2346 -0
  173. data/lib/itsi/server/config/known_paths/Randomfiles.txt +24 -0
  174. data/lib/itsi/server/config/known_paths/UnixDotfiles.txt +52 -0
  175. data/lib/itsi/server/config/known_paths/backdoors/ASP_CommonBackdoors.txt +29 -0
  176. data/lib/itsi/server/config/known_paths/backdoors/bot_control_panels.txt +1668 -0
  177. data/lib/itsi/server/config/known_paths/backdoors/shells.txt +1167 -0
  178. data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST.txt +7 -0
  179. data/lib/itsi/server/config/known_paths/cgi/CGI_HTTP_POST_Windows.txt +6 -0
  180. data/lib/itsi/server/config/known_paths/cgi/CGI_Microsoft.txt +79 -0
  181. data/lib/itsi/server/config/known_paths/cgi/CGI_XPlatform.txt +3948 -0
  182. data/lib/itsi/server/config/known_paths/cms/README.md +5 -0
  183. data/lib/itsi/server/config/known_paths/cms/drupal_plugins.txt +6320 -0
  184. data/lib/itsi/server/config/known_paths/cms/drupal_themes.txt +828 -0
  185. data/lib/itsi/server/config/known_paths/cms/joomla_plugins.txt +224 -0
  186. data/lib/itsi/server/config/known_paths/cms/joomla_themes.txt +30 -0
  187. data/lib/itsi/server/config/known_paths/cms/php-nuke.txt +2142 -0
  188. data/lib/itsi/server/config/known_paths/cms/wordpress.txt +1566 -0
  189. data/lib/itsi/server/config/known_paths/cms/wp_common_theme_files.txt +46 -0
  190. data/lib/itsi/server/config/known_paths/cms/wp_plugins.txt +13366 -0
  191. data/lib/itsi/server/config/known_paths/cms/wp_plugins_full.txt +68662 -0
  192. data/lib/itsi/server/config/known_paths/cms/wp_plugins_top225.txt +225 -0
  193. data/lib/itsi/server/config/known_paths/cms/wp_themes.readme +12 -0
  194. data/lib/itsi/server/config/known_paths/cms/wp_themes.txt +7336 -0
  195. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/3CharExtBrute.txt +17576 -0
  196. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/CommonWebExtensions.txt +80 -0
  197. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Backup.txt +14 -0
  198. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Common.txt +865 -0
  199. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Compressed.txt +186 -0
  200. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Mostcommon.txt +30 -0
  201. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/Extensions.Skipfish.txt +93 -0
  202. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/WordlistSkipfish.txt +1918 -0
  203. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/copy_of.txt +8 -0
  204. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories-lowercase.txt +56180 -0
  205. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-directories.txt +62290 -0
  206. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions-lowercase.txt +2367 -0
  207. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-extensions.txt +2450 -0
  208. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files-lowercase.txt +35323 -0
  209. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-files.txt +37037 -0
  210. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words-lowercase.txt +107982 -0
  211. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-large-words.txt +119600 -0
  212. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories-lowercase.txt +26593 -0
  213. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-directories.txt +30009 -0
  214. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions-lowercase.txt +1233 -0
  215. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-extensions.txt +1289 -0
  216. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files-lowercase.txt +16243 -0
  217. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-files.txt +17128 -0
  218. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words-lowercase.txt +56293 -0
  219. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-medium-words.txt +63087 -0
  220. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories-lowercase.txt +17776 -0
  221. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-directories.txt +20122 -0
  222. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions-lowercase.txt +914 -0
  223. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-extensions.txt +963 -0
  224. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files-lowercase.txt +10848 -0
  225. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-files.txt +11424 -0
  226. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words-lowercase.txt +38267 -0
  227. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/raft-small-words.txt +43003 -0
  228. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/spanish.txt +445 -0
  229. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/test_demo.txt +36 -0
  230. data/lib/itsi/server/config/known_paths/filename-dirname-bruteforce/upload_variants.txt +44 -0
  231. data/lib/itsi/server/config/known_paths/login-file-locations/Logins.txt +71 -0
  232. data/lib/itsi/server/config/known_paths/login-file-locations/cfm.txt +294 -0
  233. data/lib/itsi/server/config/known_paths/login-file-locations/html.txt +295 -0
  234. data/lib/itsi/server/config/known_paths/login-file-locations/jsp.txt +294 -0
  235. data/lib/itsi/server/config/known_paths/login-file-locations/php.txt +294 -0
  236. data/lib/itsi/server/config/known_paths/login-file-locations/windows-asp.txt +294 -0
  237. data/lib/itsi/server/config/known_paths/login-file-locations/windows-aspx.txt +294 -0
  238. data/lib/itsi/server/config/known_paths/password-file-locations/Passwords.txt +47 -0
  239. data/lib/itsi/server/config/known_paths/php/PHP.txt +30 -0
  240. data/lib/itsi/server/config/known_paths/php/PHP_CommonBackdoors.txt +5 -0
  241. data/lib/itsi/server/config/known_paths/proxy-conf.txt +31 -0
  242. data/lib/itsi/server/config/known_paths/tftp.txt +79 -0
  243. data/lib/itsi/server/config/known_paths/webservers-appservers/ADFS.txt +86 -0
  244. data/lib/itsi/server/config/known_paths/webservers-appservers/AdobeXML.txt +16 -0
  245. data/lib/itsi/server/config/known_paths/webservers-appservers/Apache.txt +101 -0
  246. data/lib/itsi/server/config/known_paths/webservers-appservers/ApacheTomcat.txt +47 -0
  247. data/lib/itsi/server/config/known_paths/webservers-appservers/Apache_Axis.txt +16 -0
  248. data/lib/itsi/server/config/known_paths/webservers-appservers/ColdFusion.txt +111 -0
  249. data/lib/itsi/server/config/known_paths/webservers-appservers/FatwireCMS.txt +390 -0
  250. data/lib/itsi/server/config/known_paths/webservers-appservers/Frontpage.txt +38 -0
  251. data/lib/itsi/server/config/known_paths/webservers-appservers/HP_System_Mgmt_Homepage.txt +239 -0
  252. data/lib/itsi/server/config/known_paths/webservers-appservers/HTTP_POST_Microsoft.txt +2 -0
  253. data/lib/itsi/server/config/known_paths/webservers-appservers/Hyperion.txt +578 -0
  254. data/lib/itsi/server/config/known_paths/webservers-appservers/IIS.txt +187 -0
  255. data/lib/itsi/server/config/known_paths/webservers-appservers/JBoss.txt +5 -0
  256. data/lib/itsi/server/config/known_paths/webservers-appservers/JRun.txt +13 -0
  257. data/lib/itsi/server/config/known_paths/webservers-appservers/JavaServlets_Common.txt +3 -0
  258. data/lib/itsi/server/config/known_paths/webservers-appservers/Joomla_exploitable.txt +1937 -0
  259. data/lib/itsi/server/config/known_paths/webservers-appservers/LotusNotes.txt +206 -0
  260. data/lib/itsi/server/config/known_paths/webservers-appservers/Netware.txt +18 -0
  261. data/lib/itsi/server/config/known_paths/webservers-appservers/Oracle9i.txt +60 -0
  262. data/lib/itsi/server/config/known_paths/webservers-appservers/OracleAppServer.txt +192 -0
  263. data/lib/itsi/server/config/known_paths/webservers-appservers/README.md +6 -0
  264. data/lib/itsi/server/config/known_paths/webservers-appservers/Ruby_Rails.txt +121 -0
  265. data/lib/itsi/server/config/known_paths/webservers-appservers/SAP.txt +463 -0
  266. data/lib/itsi/server/config/known_paths/webservers-appservers/Sharepoint.txt +1707 -0
  267. data/lib/itsi/server/config/known_paths/webservers-appservers/SiteMinder.txt +19 -0
  268. data/lib/itsi/server/config/known_paths/webservers-appservers/SunAppServerGlassfish.txt +51 -0
  269. data/lib/itsi/server/config/known_paths/webservers-appservers/SuniPlanet.txt +35 -0
  270. data/lib/itsi/server/config/known_paths/webservers-appservers/Vignette.txt +73 -0
  271. data/lib/itsi/server/config/known_paths/webservers-appservers/Weblogic.txt +160 -0
  272. data/lib/itsi/server/config/known_paths/webservers-appservers/Websphere.txt +366 -0
  273. data/lib/itsi/server/config/known_paths/wellknown-rfc5785.txt +30 -0
  274. data/lib/itsi/server/config/known_paths.rb +20 -0
  275. data/lib/itsi/server/config/middleware/_index.md +56 -0
  276. data/lib/itsi/server/config/middleware/allow_list.md +46 -0
  277. data/lib/itsi/server/config/middleware/allow_list.rb +42 -0
  278. data/lib/itsi/server/config/middleware/auth_api_key.md +90 -0
  279. data/lib/itsi/server/config/middleware/auth_api_key.rb +51 -0
  280. data/lib/itsi/server/config/middleware/auth_basic.md +45 -0
  281. data/lib/itsi/server/config/middleware/auth_basic.rb +44 -0
  282. data/lib/itsi/server/config/middleware/auth_jwt.md +82 -0
  283. data/lib/itsi/server/config/middleware/auth_jwt.rb +38 -0
  284. data/lib/itsi/server/config/middleware/cache_control.md +78 -0
  285. data/lib/itsi/server/config/middleware/cache_control.rb +45 -0
  286. data/lib/itsi/server/config/middleware/cidr_to_regex.rb +50 -0
  287. data/lib/itsi/server/config/middleware/compression.md +50 -0
  288. data/lib/itsi/server/config/middleware/compression.rb +37 -0
  289. data/lib/itsi/server/config/middleware/cors.md +93 -0
  290. data/lib/itsi/server/config/middleware/cors.rb +32 -0
  291. data/lib/itsi/server/config/middleware/csp.md +37 -0
  292. data/lib/itsi/server/config/middleware/csp.rb +44 -0
  293. data/lib/itsi/server/config/middleware/deny_list.md +45 -0
  294. data/lib/itsi/server/config/middleware/deny_list.rb +42 -0
  295. data/lib/itsi/server/config/middleware/endpoint/_index.md +159 -0
  296. data/lib/itsi/server/config/middleware/endpoint/controller.md +186 -0
  297. data/lib/itsi/server/config/middleware/endpoint/controller.rb +33 -0
  298. data/lib/itsi/server/config/middleware/endpoint/delete.md +12 -0
  299. data/lib/itsi/server/config/middleware/endpoint/delete.rb +42 -0
  300. data/lib/itsi/server/config/middleware/endpoint/endpoint.rb +99 -0
  301. data/lib/itsi/server/config/middleware/endpoint/get.md +12 -0
  302. data/lib/itsi/server/config/middleware/endpoint/get.rb +42 -0
  303. data/lib/itsi/server/config/middleware/endpoint/http_request.md +44 -0
  304. data/lib/itsi/server/config/middleware/endpoint/http_response.md +39 -0
  305. data/lib/itsi/server/config/middleware/endpoint/patch.md +12 -0
  306. data/lib/itsi/server/config/middleware/endpoint/patch.rb +42 -0
  307. data/lib/itsi/server/config/middleware/endpoint/post.md +12 -0
  308. data/lib/itsi/server/config/middleware/endpoint/post.rb +42 -0
  309. data/lib/itsi/server/config/middleware/endpoint/put.md +12 -0
  310. data/lib/itsi/server/config/middleware/endpoint/put.rb +42 -0
  311. data/lib/itsi/server/config/middleware/endpoint/schemas.md +122 -0
  312. data/lib/itsi/server/config/middleware/error_response.md +61 -0
  313. data/lib/itsi/server/config/middleware/error_response.rb +36 -0
  314. data/lib/itsi/server/config/middleware/etag.md +59 -0
  315. data/lib/itsi/server/config/middleware/etag.rb +27 -0
  316. data/lib/itsi/server/config/middleware/grpc.md +172 -0
  317. data/lib/itsi/server/config/middleware/grpc.rb +54 -0
  318. data/lib/itsi/server/config/middleware/intrusion_protection.md +124 -0
  319. data/lib/itsi/server/config/middleware/intrusion_protection.rb +61 -0
  320. data/lib/itsi/server/config/middleware/location.md +107 -0
  321. data/lib/itsi/server/config/middleware/location.rb +99 -0
  322. data/lib/itsi/server/config/middleware/log_requests.md +65 -0
  323. data/lib/itsi/server/config/middleware/log_requests.rb +31 -0
  324. data/lib/itsi/server/config/middleware/max_body.md +18 -0
  325. data/lib/itsi/server/config/middleware/max_body.rb +21 -0
  326. data/lib/itsi/server/config/middleware/proxy.md +62 -0
  327. data/lib/itsi/server/config/middleware/proxy.rb +41 -0
  328. data/lib/itsi/server/config/middleware/rackup_file.md +54 -0
  329. data/lib/itsi/server/config/middleware/rackup_file.rb +44 -0
  330. data/lib/itsi/server/config/middleware/rate_limit.md +126 -0
  331. data/lib/itsi/server/config/middleware/rate_limit.rb +34 -0
  332. data/lib/itsi/server/config/middleware/rate_limit_store.rb +25 -0
  333. data/lib/itsi/server/config/middleware/redirect.md +55 -0
  334. data/lib/itsi/server/config/middleware/redirect.rb +25 -0
  335. data/lib/itsi/server/config/middleware/request_headers.md +34 -0
  336. data/lib/itsi/server/config/middleware/request_headers.rb +24 -0
  337. data/lib/itsi/server/config/middleware/response_headers.md +33 -0
  338. data/lib/itsi/server/config/middleware/response_headers.rb +25 -0
  339. data/lib/itsi/server/config/middleware/run.md +60 -0
  340. data/lib/itsi/server/config/middleware/run.rb +43 -0
  341. data/lib/itsi/server/config/middleware/static_assets.md +73 -0
  342. data/lib/itsi/server/config/middleware/static_assets.rb +87 -0
  343. data/lib/itsi/server/config/middleware/static_response.md +44 -0
  344. data/lib/itsi/server/config/middleware/static_response.rb +29 -0
  345. data/lib/itsi/server/config/middleware/string_rewrite.md +67 -0
  346. data/lib/itsi/server/config/middleware/token_source.rb +32 -0
  347. data/lib/itsi/server/config/middleware.rb +13 -0
  348. data/lib/itsi/server/config/option.rb +14 -0
  349. data/lib/itsi/server/config/options/_index.md +37 -0
  350. data/lib/itsi/server/config/options/auto_reload_config.md +13 -0
  351. data/lib/itsi/server/config/options/auto_reload_config.rb +41 -0
  352. data/lib/itsi/server/config/options/bind.md +71 -0
  353. data/lib/itsi/server/config/options/bind.rb +26 -0
  354. data/lib/itsi/server/config/options/certificates.md +65 -0
  355. data/lib/itsi/server/config/options/daemonize.md +14 -0
  356. data/lib/itsi/server/config/options/daemonize.rb +19 -0
  357. data/lib/itsi/server/config/options/fiber_scheduler.md +34 -0
  358. data/lib/itsi/server/config/options/fiber_scheduler.rb +21 -0
  359. data/lib/itsi/server/config/options/header_read_timeout.md +17 -0
  360. data/lib/itsi/server/config/options/header_read_timeout.rb +19 -0
  361. data/lib/itsi/server/config/options/hooks/_index.md +11 -0
  362. data/lib/itsi/server/config/options/hooks/after_fork.md +13 -0
  363. data/lib/itsi/server/config/options/hooks/after_fork.rb +28 -0
  364. data/lib/itsi/server/config/options/hooks/after_memory_limit_reached.md +14 -0
  365. data/lib/itsi/server/config/options/hooks/after_memory_limit_reached.rb +28 -0
  366. data/lib/itsi/server/config/options/hooks/after_start.md +12 -0
  367. data/lib/itsi/server/config/options/hooks/after_start.rb +28 -0
  368. data/lib/itsi/server/config/options/hooks/before_fork.md +13 -0
  369. data/lib/itsi/server/config/options/hooks/before_fork.rb +28 -0
  370. data/lib/itsi/server/config/options/hooks/before_restart.md +12 -0
  371. data/lib/itsi/server/config/options/hooks/before_restart.rb +28 -0
  372. data/lib/itsi/server/config/options/hooks/before_shutdown.md +12 -0
  373. data/lib/itsi/server/config/options/hooks/before_shutdown.rb +28 -0
  374. data/lib/itsi/server/config/options/include.md +20 -0
  375. data/lib/itsi/server/config/options/include.rb +36 -0
  376. data/lib/itsi/server/config/options/listen_backlog.md +11 -0
  377. data/lib/itsi/server/config/options/listen_backlog.rb +19 -0
  378. data/lib/itsi/server/config/options/log_format.md +18 -0
  379. data/lib/itsi/server/config/options/log_format.rb +19 -0
  380. data/lib/itsi/server/config/options/log_level.md +34 -0
  381. data/lib/itsi/server/config/options/log_level.rb +20 -0
  382. data/lib/itsi/server/config/options/log_target.md +38 -0
  383. data/lib/itsi/server/config/options/log_target.rb +19 -0
  384. data/lib/itsi/server/config/options/log_target_filters.md +17 -0
  385. data/lib/itsi/server/config/options/log_target_filters.rb +19 -0
  386. data/lib/itsi/server/config/options/multithreaded_reactor.md +27 -0
  387. data/lib/itsi/server/config/options/multithreaded_reactor.rb +24 -0
  388. data/lib/itsi/server/config/options/nodelay.md +16 -0
  389. data/lib/itsi/server/config/options/nodelay.rb +19 -0
  390. data/lib/itsi/server/config/options/oob_gc_responses_threshold.md +19 -0
  391. data/lib/itsi/server/config/options/oob_gc_responses_threshold.rb +18 -0
  392. data/lib/itsi/server/config/options/pin_worker_cores.md +17 -0
  393. data/lib/itsi/server/config/options/pin_worker_cores.rb +19 -0
  394. data/lib/itsi/server/config/options/preload.md +21 -0
  395. data/lib/itsi/server/config/options/preload.rb +18 -0
  396. data/lib/itsi/server/config/options/recv_buffer_size.md +15 -0
  397. data/lib/itsi/server/config/options/recv_buffer_size.rb +19 -0
  398. data/lib/itsi/server/config/options/redirect_http_to_https.md +21 -0
  399. data/lib/itsi/server/config/options/redirect_http_to_https.rb +30 -0
  400. data/lib/itsi/server/config/options/request_timeout.md +23 -0
  401. data/lib/itsi/server/config/options/request_timeout.rb +19 -0
  402. data/lib/itsi/server/config/options/reuse_address.md +16 -0
  403. data/lib/itsi/server/config/options/reuse_address.rb +19 -0
  404. data/lib/itsi/server/config/options/reuse_port.md +16 -0
  405. data/lib/itsi/server/config/options/reuse_port.rb +19 -0
  406. data/lib/itsi/server/config/options/scheduler_threads.md +34 -0
  407. data/lib/itsi/server/config/options/scheduler_threads.rb +17 -0
  408. data/lib/itsi/server/config/options/shutdown_timeout.md +17 -0
  409. data/lib/itsi/server/config/options/shutdown_timeout.rb +19 -0
  410. data/lib/itsi/server/config/options/stream_body.md +32 -0
  411. data/lib/itsi/server/config/options/stream_body.rb +18 -0
  412. data/lib/itsi/server/config/options/threads.md +44 -0
  413. data/lib/itsi/server/config/options/threads.rb +17 -0
  414. data/lib/itsi/server/config/options/watch.md +16 -0
  415. data/lib/itsi/server/config/options/watch.rb +28 -0
  416. data/lib/itsi/server/config/options/worker_memory_limit.md +22 -0
  417. data/lib/itsi/server/config/options/worker_memory_limit.rb +18 -0
  418. data/lib/itsi/server/config/options/workers.md +42 -0
  419. data/lib/itsi/server/config/options/workers.rb +17 -0
  420. data/lib/itsi/server/config/typed_struct.rb +242 -0
  421. data/lib/itsi/server/config.rb +289 -0
  422. data/lib/itsi/server/default_app/default_app.rb +34 -0
  423. data/lib/itsi/server/default_app/index.html +115 -0
  424. data/lib/itsi/server/default_config/Itsi.rb +107 -0
  425. data/lib/itsi/server/grpc/grpc_call.rb +246 -0
  426. data/lib/itsi/server/grpc/grpc_interface.rb +107 -0
  427. data/lib/itsi/server/grpc/reflection/v1/reflection_pb.rb +26 -0
  428. data/lib/itsi/server/grpc/reflection/v1/reflection_services_pb.rb +122 -0
  429. data/lib/itsi/server/rack/handler/itsi.rb +27 -0
  430. data/lib/itsi/server/rack_interface.rb +94 -0
  431. data/lib/itsi/server/route_tester.rb +157 -0
  432. data/lib/itsi/server/scheduler_interface.rb +21 -0
  433. data/lib/itsi/server/scheduler_mode.rb +10 -0
  434. data/lib/itsi/server/signal_trap.rb +33 -0
  435. data/lib/itsi/server/typed_handlers/param_parser.rb +196 -0
  436. data/lib/itsi/server/typed_handlers/source_parser.rb +56 -0
  437. data/lib/itsi/server/typed_handlers.rb +25 -0
  438. data/lib/itsi/server/version.rb +1 -1
  439. data/lib/itsi/server.rb +265 -9
  440. data/lib/itsi/standard_headers.rb +86 -0
  441. data/lib/ruby_lsp/itsi/addon.rb +129 -0
  442. data/lib/shell_completions/completions.rb +26 -0
  443. metadata +454 -28
  444. data/CHANGELOG.md +0 -5
  445. data/CODE_OF_CONDUCT.md +0 -132
  446. data/LICENSE.txt +0 -21
  447. data/ext/itsi_server/src/request/itsi_request.rs +0 -143
  448. data/ext/itsi_server/src/request/mod.rs +0 -1
  449. data/ext/itsi_server/src/server/bind.rs +0 -138
  450. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -32
  451. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -52
  452. data/ext/itsi_server/src/server/itsi_server.rs +0 -182
  453. data/ext/itsi_server/src/server/listener.rs +0 -218
  454. data/ext/itsi_server/src/server/tls.rs +0 -138
  455. data/ext/itsi_server/src/server/transfer_protocol.rs +0 -23
  456. data/ext/itsi_server/src/stream_writer/mod.rs +0 -21
  457. data/lib/itsi/request.rb +0 -39
@@ -0,0 +1,126 @@
1
+ ---
2
+ title: Rate Limiter
3
+ url: /middleware/rate_limit
4
+ ---
5
+
6
+ The **Rate Limiter** middleware enforces a fixed‑window rate limit on incoming requests. You configure a maximum number of requests allowed in a given time span, along with how to identify the client and where to store counters (in‑memory or Redis).
7
+
8
+ By default it limits per IP address using an in‑memory store, but you can:
9
+
10
+ - Change the window size (`requests` per `seconds`)
11
+ - Limit based on other attributes (header or query parameter)
12
+ - Swap to a Redis backend for cross‑process rate limiting
13
+ - Customize the error response when the limit is exceeded
14
+
15
+ ## Configuration
16
+
17
+ ```ruby
18
+ rate_limit \
19
+ requests: 100, # max 100 requests
20
+ seconds: 60, # per 60‑second window
21
+ key: "address", # limit by client IP
22
+ store_config: "in_memory", # use local in‑memory store
23
+ error_response: "too_many_requests"
24
+ ```
25
+
26
+ ### `requests` / `seconds`
27
+
28
+ - **`requests`**: Number of allowed requests in each window (positive integer).
29
+ - **`seconds`**: Length of each fixed window in seconds (positive integer).
30
+
31
+ ### `key`
32
+
33
+ How to identify the client:
34
+
35
+ - **`"address"`** (default): use the client’s socket IP.
36
+ - **Header or query parameter**:
37
+ ```ruby
38
+ key: { parameter: { header: { name: "X-Api-Key-Id" } } }
39
+ ```
40
+ or
41
+ ```ruby
42
+ key: { parameter: { query: { name: "user_id" } } }
43
+ ```
44
+
45
+ ### `store_config`
46
+
47
+ Where to keep counters:
48
+
49
+ - **`"in_memory"`** (default): per‑process, reset when server restarts.
50
+ - **Redis** (shared across workers):
51
+ ```ruby
52
+ store_config: { redis: { connection_url: "redis://localhost:6379/1" } }
53
+ ```
54
+
55
+ ### `error_response`
56
+
57
+ Customizes the response when the limit is reached (default is built‑in `too_many_requests`):
58
+
59
+ ```ruby
60
+ error_response: {
61
+ code: 429,
62
+ plaintext: { inline: "Rate limit exceeded" },
63
+ default: "plaintext"
64
+ }
65
+ ```
66
+
67
+ ## Rate Limit Response Headers
68
+
69
+ When a request **exceeds** the allowed rate, the middleware returns your configured error response **plus** these headers:
70
+
71
+ | Header | Meaning |
72
+ |---------------------------|------------------------------------------------------------------------------------------|
73
+ | **X-RateLimit-Limit** | The maximum number of requests allowed per window (`requests` value). |
74
+ | **X-RateLimit-Remaining** | How many requests remain in the current window (will be `0` once the limit is hit). |
75
+ | **X-RateLimit-Reset** | Seconds until the current window resets (time until your counter zeroes out). |
76
+ | **Retry-After** | Same value as `X-RateLimit-Reset` — suggests when clients should retry their request. |
77
+
78
+ > **Example**
79
+ > With `requests: 5, seconds: 60`, after 5 calls the 6th returns:
80
+ > ```
81
+ > 429 Too Many Requests
82
+ > X-RateLimit-Limit: 5
83
+ > X-RateLimit-Remaining: 0
84
+ > X-RateLimit-Reset: 42
85
+ > Retry-After: 42
86
+ > ```
87
+
88
+ ## How It Works
89
+
90
+ 1. **On each request**
91
+ - Compute the client key (IP, header, or query).
92
+ - Increment a counter for the current time window.
93
+
94
+ 2. **Fixed‑window logic**
95
+ - If the counter ≤ `requests`, allow through.
96
+ - Otherwise, immediately return the configured `error_response` plus the **X-RateLimit** headers.
97
+
98
+ 3. **Store options**
99
+ - **In‑memory**: simple hash, fast but not shared across processes.
100
+ - **Redis**: atomic `INCR` + `EXPIRE` commands, shared across all workers.
101
+
102
+ Place `rate_limit` anywhere in your routing DSL to apply it to all downstream handlers in that scope.
103
+
104
+
105
+ ## Trusted Proxies
106
+
107
+ By default, a rate limiter middleware uses the IP address from the underlying socket (remote_addr). However, if your server is behind a reverse proxy, all requests will appear to come from the proxy’s IP address. This can break IP-based rules or cause rate-limiting to group all users together.
108
+
109
+ To address this, you can declare trusted proxies and instruct the server to extract the original client IP from forwarded headers only if the request came from one of these proxies.
110
+
111
+
112
+ ### Configuring trusted_proxies
113
+
114
+ To trust one or more upstream proxies, provide a trusted_proxies map in the middleware configuration.
115
+ E.g.
116
+ ```ruby {filename=Itsi.rb}
117
+ rate_limit \
118
+ requests: 100, # max 100 requests
119
+ seconds: 60, # per 60‑second window
120
+ key: "address", # limit by client IP
121
+ store_config: "in_memory", # use local in‑memory store
122
+ error_response: "too_many_requests",
123
+ trusted_proxies: {
124
+ "192.168.1.1" => { header: { name: "X-Forwarded-For" } }
125
+ }
126
+ ```
@@ -0,0 +1,34 @@
1
+ module Itsi
2
+ class Server
3
+ module Config
4
+ class RateLimit < Middleware
5
+ require_relative "rate_limit_store"
6
+ require_relative "token_source"
7
+
8
+ insert_text <<~SNIPPET
9
+ rate_limit \\
10
+ requests: ${1|1,5,100|},
11
+ seconds: ${2|1,5,100|},
12
+ key: ${3|"address",{parameter:{header:{name:"X-Forwarded-For"}}}|},
13
+ store_config: ${4|"in_memory",{redis:{connection_url: "redis://localhost:6379"}}|},
14
+ error_response: ${5|"too_many_requests", { code: 429\\, default_format: "html"\\, html: { inline: "<h1>Unauthorized</h1>" } }|}
15
+ SNIPPET
16
+
17
+ detail "Automatically limits the number of requests a client can make within a given time period."
18
+
19
+
20
+ schema do
21
+ {
22
+ requests: Required() & Type(Integer) & Range(1..2**32),
23
+ seconds: Required() & Type(Integer) & Range(1..2**32),
24
+ key: (Required() & Or(Enum(["address"]), Type(RateLimitKey))).default("address"),
25
+ store_config: (Required() & Or(Enum(["in_memory"]), Type(RateLimitStore))).default("in_memory"),
26
+ error_response: Type(ErrorResponseDef).default("too_many_requests"),
27
+ trusted_proxies: (Hash(Type(String), Type(TokenSource)) & Required()).default({})
28
+ }
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,25 @@
1
+ module Itsi
2
+ class Server
3
+ module Config
4
+
5
+ RateLimitKey = TypedStruct.new do
6
+ {
7
+ parameter: Or(
8
+ Hash(Enum(["header"]), Hash(Enum(["name"]), Type(String))) & Required(),
9
+ Hash(Enum(["query"]), Type(String)) & Required()
10
+ )
11
+ }
12
+ end
13
+
14
+ RateLimitStore = TypedStruct.new do
15
+ {
16
+ redis: Type(TypedStruct.new do
17
+ {
18
+ connection_url: Type(String)& Required()
19
+ }
20
+ end) & Required()
21
+ }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,55 @@
1
+ ---
2
+ title: Redirect
3
+ url: /middleware/redirect
4
+ ---
5
+
6
+ The Redirect middleware enables automatic redirection of incoming requests to a different URL. It computes the target URL using a string rewrite rule and responds with an HTTP redirect status code based on the configuration. Once the middleware processes a request, it immediately returns a redirection response without further processing.
7
+
8
+ ## Redirect configuration
9
+
10
+ ```ruby
11
+ redirect \
12
+ to: "https://example.com/new-path", \
13
+ type: "permanent"
14
+ ```
15
+
16
+ ## Redirect Applied to a sub-location
17
+
18
+ ```ruby
19
+ location "/old-path" do
20
+ redirect \
21
+ to: "https://example.com/new-path", \
22
+ type: "temporary"
23
+ # No further route processing occurs for /old-path.
24
+ end
25
+ ```
26
+ ## Redirect HTTP to HTTPS
27
+
28
+ ```ruby
29
+ location protocols: [:http] do
30
+ redirect \
31
+ to: "https://{host}{path_and_query}", \
32
+ type: "moved_permanently"
33
+ end
34
+ ```
35
+ > A shorthand for the above exists, call `redirect_http_to_https!`. Note that this is
36
+ an alias for the above, and as such is subject to ordinary [location](/middleware/location) resolution rules.
37
+ To make sure this rule takes precedence, place it above other locations in the `Itsi.rb` file.
38
+
39
+
40
+
41
+ ## Configuration Options
42
+
43
+ - **to**:
44
+ A [string rewrite rule](/middleware/string_rewrites) (or literal string) specifying the target URL for the redirection. This value can incorporate dynamic portions of the incoming request.
45
+
46
+ - **type**:
47
+ Specifies the type of redirection. Allowed values include:
48
+ - `"permanent"`: Responds with a 308 Permanent Redirect.
49
+ - `"temporary"`: Responds with a 307 Temporary Redirect.
50
+ - `"moved_permanently"`: Responds with a 301 Moved Permanently.
51
+ - `"found"`: Responds with a 302 Found.
52
+
53
+ ## How It Works
54
+
55
+ When a request is received, the Redirect middleware immediately intercepts it and builds a redirect response. The target URL is computed via the provided rewrite rule (`to`), and the response is sent with the appropriate HTTP status code as determined by the `type` option. No further handling is performed on the request.
@@ -0,0 +1,25 @@
1
+ module Itsi
2
+ class Server
3
+ module Config
4
+ class Redirect < Middleware
5
+
6
+ insert_text <<~SNIPPET
7
+ redirect \\
8
+ to: "${1:https://example.com/new-path}",
9
+ type: ${2|"permanent","temporary","found","moved_permanently"|}
10
+ SNIPPET
11
+
12
+ detail "Automatically redirects incoming requests to a new URL based on a string rewrite rule."
13
+
14
+ Redirect = TypedStruct.new do
15
+ {
16
+ to: (Required() & Type(String)),
17
+ type: Enum(["permanent", "temporary", "found", "moved_permanently"]).default("moved_permanently")
18
+ }
19
+ end
20
+
21
+ schema Redirect
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,34 @@
1
+ ---
2
+ title: Request Headers
3
+ url: /middleware/request_headers
4
+ ---
5
+
6
+ The **Request Headers** middleware lets you add, override or remove HTTP headers **before** your application handler sees the request. You can inject static values or use the full power of [String Rewrite](/middleware/string_rewrite) to generate header values based on path, query, method, etc.
7
+
8
+ ## Configuration
9
+ ```ruby {filename=Itsi.rb}
10
+ request_headers \
11
+ additions: {
12
+ "X-Correlation-ID" => ["{request_id_full}"],
13
+ "X-Env" => ["production"]
14
+ },
15
+ removals: ["X-Forwarded-For"]
16
+ ```
17
+
18
+ - **additions** (`Hash(String,Array(StringRewrite))`)
19
+ A map of header names to an array of StringRewrite templates. Each template is rendered **after** removals.
20
+ - **removals** `Array(String)`
21
+ A list of header names to delete outright. If you want to override an existing header, include it in **both** removals and additions.
22
+
23
+ ## Examples
24
+ ```ruby {filename=Itsi.rb}
25
+ # Add a per‑request UUID and drop any X‑Forwarded‑For header
26
+ request_headers \
27
+ additions: { "X-Correlation-ID" => ["{request_id}"] },
28
+ removals: ["X-Forwarded-For"]
29
+
30
+ # Inject the full request path and query
31
+ request_headers \
32
+ additions: { "X-Full-URL" => ["{path_and_query}"] },
33
+ removals: []
34
+ ```
@@ -0,0 +1,24 @@
1
+ module Itsi
2
+ class Server
3
+ module Config
4
+ class RequestHeaders < Middleware
5
+
6
+ insert_text <<~SNIPPET
7
+ request_headers \\
8
+ additions: { ${1:"X-Correlation-ID" => ["{request_id_full\\}"]} },
9
+ removals: [${2:"X-Forwarded-For"}]
10
+ SNIPPET
11
+
12
+ detail "Add, override or remove request headers before reaching your handler."
13
+
14
+ schema do
15
+ {
16
+ additions: Hash(Type(String), Array(Type(String))).default({}),
17
+ removals: Array(Type(String)).default([]),
18
+ combine: Bool().default(true)
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: Response Headers
3
+ url: /middleware/response_headers
4
+ ---
5
+
6
+ The **Response Headers** middleware lets you add, override or remove HTTP headers **after** your application handler has produced a response. You can attach static values or dynamically compute them via [String Rewrite](/middleware/string_rewrite).
7
+
8
+ ## Configuration
9
+ ```ruby {filename=Itsi.rb}
10
+ response_headers \
11
+ additions: {
12
+ "X-Processed-By" => ["Itsi"],
13
+ "X-Response-Time-Millis" => ["{response_time}"]
14
+ },
15
+ removals: ["Server"]
16
+ ```
17
+ - **additions** `Hash(String,Array(StringRewrite))`
18
+ A map of header names to StringRewrite templates. Templates are evaluated against the final response and context in **after**.
19
+ - **removals** `Array(String)`
20
+ A list of header names to delete before adding new ones.
21
+
22
+ ## Examples
23
+ ```ruby {filename=Itsi.rb}
24
+ # Stamp every response with our server name
25
+ response_headers \
26
+ additions: { "X-Powered-By" => ["Itsi"] },
27
+ removals: []
28
+
29
+ # Remove the Server header and add timing info
30
+ response_headers \
31
+ additions: { "X-Response-Time" => ["{response_time}"] },
32
+ removals: ["Server"]
33
+ ```
@@ -0,0 +1,25 @@
1
+ module Itsi
2
+ class Server
3
+ module Config
4
+ class ResponseHeaders < Middleware
5
+
6
+ insert_text <<~SNIPPET
7
+ response_headers \\
8
+ additions: { ${1:"X-Powered-By" => ["Itsi"]} },
9
+ removals: [${2:"Server"}]
10
+ SNIPPET
11
+
12
+
13
+ detail "Add, override or remove response headers before sending to the client."
14
+
15
+ schema do
16
+ {
17
+ additions: Hash(Type(String), Array(Type(String))).default({}),
18
+ removals: Array(Type(String)).default([]),
19
+ combine: Bool().default(true)
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,60 @@
1
+ ---
2
+ title: Run
3
+ url: /middleware/run
4
+ ---
5
+
6
+ You can use the `run` middleware to run an inline rack application.
7
+ The alternative way to mount a rack application is to use a [`rackup_file`](/middleware/rackup_file) middleware.
8
+
9
+ You can mount several rack applications to run simultaneously within a single Itsi application, using different location blocks.
10
+ Depending on *where* you mount the app, the application will receive different values for `PATH_INFO`, `SCRIPT_NAME`.
11
+
12
+ ## Configuration
13
+
14
+ ### Simple inline Rack app.
15
+ ```ruby {filename=Itsi.rb}
16
+ run ->(env){ [200, { 'content-type' => 'text/plain' }, ['OK']] }
17
+ ```
18
+
19
+ ### Rack app using Rack::Builder
20
+ ```ruby {filename=Itsi.rb}
21
+ run(Rack::Builder.app do
22
+ use Rack::CommonLogger
23
+ run ->(env) { [200, { 'content-type' => 'text/plain' }, ['OK']] }
24
+ end)
25
+ ```
26
+
27
+
28
+ ### Rack app mounted at a subpath
29
+ ```ruby {filename=Itsi.rb}
30
+ require 'rack'
31
+ location "/subpath/*" do
32
+ run(Rack::Builder.app do
33
+ use Rack::CommonLogger
34
+ run ->(env) { [200, { 'content-type' => 'text/plain' }, [[env['SCRIPT_NAME'], env['PATH_INFO']].join(":") ] ] }
35
+ end)
36
+ end
37
+
38
+ run(Rack::Builder.app do
39
+ use Rack::CommonLogger
40
+ run ->(env) { [200, { 'content-type' => 'text/plain' }, [[env['SCRIPT_NAME'], env['PATH_INFO']].join(":") ] ] }
41
+ end)
42
+
43
+ ```
44
+
45
+ ```bash
46
+ $ curl http://0.0.0.0:3000/subpath/child_path
47
+ /subpath:/child_path
48
+
49
+ $ curl http://0.0.0.0:3000/root/child_path
50
+ :/root/child_path
51
+ ```
52
+
53
+ ### Options
54
+ * `nonblocking` (default false). Determines whether requests sent to this Rack application should be run on non-blocking threads. Only applies if running in hybrid (non-blocking and blocking thread pool) mode. Otherwise this is a no-op and will run in whatever mode is set globally.
55
+ * `sendfile` (default true). Determines whether Itsi should respect the `X-Sendfile` header set by the Rack application and use the `sendfile` function to efficiently send files. (Despite the name, this does not use the OS-level `sendfile` system call). Note. Itsi enforces the restriction that the referenced file must be within a child directory of the application root.
56
+
57
+ e.g.
58
+ ```ruby {filename=Itsi.rb}
59
+ run ->(env){ [200, { 'content-type' => 'text/plain' }, ['OK']] }, nonblocking: true, sendfile: false
60
+ ```
@@ -0,0 +1,43 @@
1
+ module Itsi
2
+ class Server
3
+ module Config
4
+ class Run < Middleware
5
+
6
+ insert_text <<~SNIPPET
7
+ run \\
8
+ ${1:->(env){[200, {"Content-Type" => "text/plain"\\}, ["Hello, World!"]]}},
9
+ nonblocking: ${2|true,false|},
10
+ sendfile: ${3|true,false|}
11
+ SNIPPET
12
+
13
+ detail "Define an inline Rack Application"
14
+
15
+ schema do
16
+ {
17
+ nonblocking: Bool().default(false),
18
+ sendfile: Bool().default(true)
19
+ }
20
+ end
21
+
22
+ def initialize(location, app, params={})
23
+ super(location, params)
24
+ raise "App must be a Rack application" unless app.respond_to?(:call)
25
+ @app = app
26
+ end
27
+
28
+ def build!
29
+ app_args = {
30
+ preloader: -> { Itsi::Server::RackInterface.for(@app) },
31
+ sendfile: @params[:sendfile],
32
+ nonblocking: @params[:nonblocking],
33
+ base_path: "^(?<base_path>#{location.paths_from_parent.gsub(/\.\*\)$/, ')')}).*$"
34
+ }
35
+ location.middleware[:app] = app_args
36
+ location.location("*") do
37
+ @middleware[:app] = app_args
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,73 @@
1
+ ---
2
+ title: Static Assets
3
+ url: /middleware/static_assets
4
+ ---
5
+
6
+ The Static Assets middleware serves files from a specified root directory. It is capable of optimized delivery of static content such as HTML, CSS, JavaScript, images, as well as large assets, such as video files using streaming bodies and range requests.
7
+ It can auto-index directories for simple directory listings.
8
+
9
+ ## Key Features
10
+ - **Auto Indexing**: Optionally generate directory listings when an index file is missing.
11
+ - **HTML Fallback**: When enabled, the middleware attempts to serve a file with a `.html` extension if the requested file is not found.
12
+ - **In-Memory Caching**: Files under a certain size (and up to a configurable count) are cached in memory for performance.
13
+ - **Custom Headers**: User-supplied headers (e.g., for caching) can be added to responses.
14
+ - **Relative Path Processing**: When enabled, the middleware rewrites request paths relative to a configured base path.
15
+ - **Partial Content**: Supports Range requests for serving partial file content.
16
+
17
+ ## Example
18
+
19
+ ```ruby {filename=Itsi.rb}
20
+ static_assets root_dir: "./"
21
+ ```
22
+
23
+ ## Configuration Options
24
+
25
+
26
+ | Option | Description |
27
+ |--------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
28
+ | **`root_dir`** (Default ".") | The relative or absolute disk path where static files reside. |
29
+ | **`not_found_behavior`** (Default `{error: "not_found"}`) | Determines what to do when a file isn’t found. See [Not Found Behavior](#not-found-behavior) below. |
30
+ | **`auto_index`** (Default `false`) | If <code>true</code>, directory listings are automatically generated when no index file is found. Defaults to <code>false</code>. |
31
+ | **`try_html_extension`** (Default `true`) | If <code>true</code>, when the requested file isn’t found, the middleware attempts to serve the same path with a <code>.html</code> extension. Defaults to <code>true</code>. |
32
+ | **`max_file_size_in_memory`** (Default `1048576`) | Maximum file size (in bytes) for caching files in memory. Files larger than this will be served from disk. Defaults to <code>1048576</code> (1 MB). |
33
+ | **`max_files_in_memory`** (Default `100`) | Maximum number of files to cache in memory. Defaults to <code>100</code>. |
34
+ | **`file_check_interval`** (Default `1`) | Max time (in seconds) a file stays in cache before the file-system is checked for modifications. Defaults to <code>1</code>. |
35
+ | **`headers`** (Default `nil`) | A hash of additional headers to include in responses (e.g. <code>{"Cache-Control" => "max-age=3600"}</code>). |
36
+ | **`allowed_extensions`** (Default `[]`) | An array of permitted file extensions (e.g. <code>["html", "css", "js", "png", "jpg"]</code>). If a requested file’s extension isn’t in this list, it won’t be served. An empty list (default) means all extensions are allowed. |
37
+ | **`relative_path`** (Default `true`) | If <code>true</code>, the effective file lookup path is computed relative to the base path at which the middleware is mounted (See [location](/middleware/location) to understand mounting options). Defaults to <code>true</code>. |
38
+ | **`serve_hidden_files`** (Default `false`) | If <code>false</code>, files whose names start with a dot (".") are not served. Defaults to <code>false</code>. |
39
+
40
+
41
+ ## Not Found Behavior
42
+ The static assets middleware supports many configuration options when a file is not found.
43
+ * **`fallthrough`**: The request is *not* handled by this middleware and is instead served by the next middleware in the chain. The option is given as a string. E.g.
44
+ ```ruby
45
+ error_response: "fallthrough"
46
+ ```
47
+ * **`index`**: Unsatisfiable requests instead result in serving an index file. (Useful for SPAs with client-side routing).
48
+ ```ruby
49
+ error_response: {index: "./path/to/index.html" }
50
+ ```
51
+ * **`redirect`**: Unsatisfiable requests are redirected. Options for type are the same as defined for the [redirect](/middleware/redirect) middleware.
52
+ ```ruby
53
+ error_response: {redirect: { to: "http://example.com/redirect_path", type: "permanent" }}
54
+ ```
55
+ * **`error`**: Provide an overridden error response. See [`error_response`](/middleware/error_response) for details.
56
+ e.g.
57
+ ```ruby
58
+ error_response: {error: "not_found"}
59
+ ```
60
+
61
+ ```ruby
62
+ error_response: \
63
+ {
64
+ error:
65
+ {
66
+ code: 404,
67
+ plaintext: {inline: "File not found"},
68
+ json: {inline: "{\"message\": \"File not found\"}"},
69
+ html: {file: "./path/to/not_found.html"},
70
+ default: "plaintext"
71
+ }
72
+ }
73
+ ```
@@ -0,0 +1,87 @@
1
+ module Itsi
2
+ class Server
3
+ module Config
4
+ class StaticAssets < Middleware
5
+
6
+ insert_text <<~SNIPPET
7
+ static_assets \\
8
+ root_dir: "${1|./,/var/www,|}",
9
+ not_found_behavior: ${2|"fallthrough",{index: "index.html"},{error: "not_found"}|},
10
+ auto_index: ${3|true,false|},
11
+ try_html_extension: ${4|true,false|},
12
+ max_file_size_in_memory: ${5|1048576,2097152|},
13
+ max_files_in_memory: ${6|100,500,1000|},
14
+ file_check_interval: ${7|1,60,120|},
15
+ headers: { ${8|,"Cache-Control" => "max-age=3600",|} },
16
+ allowed_extensions: ${9|%w[html css js png jpg],[]|},
17
+ relative_path: ${10|true,false|},
18
+ serve_hidden_files: ${11|true,false|}
19
+ SNIPPET
20
+
21
+ detail "Serves static files from a designated directory with options for auto indexing, in-memory caching, and custom header support. Supports relative path rewriting and file range requests."
22
+
23
+ ErrorResponse = TypedStruct.new do
24
+ {
25
+ error: Type(ErrorResponseDef) & Required()
26
+ }
27
+ end
28
+
29
+ IndexResponse = TypedStruct.new do
30
+ {
31
+ index: Type(String) & Required()
32
+ }
33
+ end
34
+
35
+ RedirectResponse = TypedStruct.new do
36
+ {
37
+ redirect: Type(Redirect::Redirect) & Required()
38
+ }
39
+ end
40
+
41
+ schema do
42
+ {
43
+ root_dir: (Type(String) & Required()).default("./"),
44
+ not_found_behavior: Or(
45
+ Enum(["fallthrough", "index", "redirect", "internal_server_error"]),
46
+ Type(IndexResponse),
47
+ Type(RedirectResponse),
48
+ Type(ErrorResponse)
49
+ ).default({error: "not_found"}),
50
+ allowed_extensions: (Array(Type(String)) & Required()).default([]),
51
+ auto_index: Bool().default(false),
52
+ try_html_extension: Bool().default(true),
53
+ max_file_size_in_memory: Type(Integer).default(1048576),
54
+ max_files_in_memory: Type(Integer).default(100),
55
+ file_check_interval: Type(Integer).default(1),
56
+ headers: Hash(Type(String), Type(String)).default({}),
57
+ relative_path: Bool().default(true),
58
+ serve_hidden_files: Bool().default(false)
59
+ }
60
+ end
61
+
62
+ def build!
63
+ root_dir = @params[:root_dir] || "."
64
+
65
+ if !File.exist?(root_dir)
66
+ warn "Warning: static_assets root_dir '#{root_dir}' does not exist!"
67
+ elsif !File.directory?(root_dir)
68
+ warn "Warning: static_assets root_dir '#{root_dir}' is not a directory!"
69
+ end
70
+
71
+ @params[:relative_path] = true unless @params.key?(:relative_path)
72
+ @params[:allowed_extensions] ||= []
73
+
74
+ if @params[:try_html_extension] && @params[:allowed_extensions].include?("html")
75
+ @params[:allowed_extensions] << ""
76
+ end
77
+
78
+ @params[:base_path] = "^(?<base_path>#{location.paths_from_parent}).*$"
79
+ params = @params
80
+ location.location("*", extensions: @params[:allowed_extensions]) do
81
+ @middleware[:static_assets] = params
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end