itsi 0.1.9 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1542 -43
  3. data/Itsi.rb +125 -0
  4. data/Rakefile +8 -4
  5. data/crates/itsi_error/src/lib.rs +9 -0
  6. data/crates/itsi_rb_helpers/Cargo.toml +1 -0
  7. data/crates/itsi_rb_helpers/src/heap_value.rs +18 -0
  8. data/crates/itsi_rb_helpers/src/lib.rs +59 -9
  9. data/crates/itsi_server/Cargo.toml +70 -28
  10. data/crates/itsi_server/src/lib.rs +80 -80
  11. data/crates/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
  12. data/{gems/server/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs → crates/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs} +22 -3
  13. data/crates/itsi_server/src/ruby_types/itsi_grpc_request.rs +147 -0
  14. data/crates/itsi_server/src/ruby_types/itsi_grpc_response.rs +19 -0
  15. data/crates/itsi_server/src/ruby_types/itsi_grpc_stream/mod.rs +216 -0
  16. data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +282 -0
  17. data/crates/itsi_server/src/{response/itsi_response.rs → ruby_types/itsi_http_response.rs} +72 -41
  18. data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
  19. data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +355 -0
  20. data/crates/itsi_server/src/ruby_types/itsi_server.rs +82 -0
  21. data/crates/itsi_server/src/ruby_types/mod.rs +55 -0
  22. data/crates/itsi_server/src/server/bind.rs +29 -17
  23. data/crates/itsi_server/src/server/byte_frame.rs +32 -0
  24. data/crates/itsi_server/src/server/cache_store.rs +74 -0
  25. data/crates/itsi_server/src/server/itsi_service.rs +172 -0
  26. data/crates/itsi_server/src/server/lifecycle_event.rs +3 -0
  27. data/crates/itsi_server/src/server/listener.rs +111 -11
  28. data/crates/itsi_server/src/server/middleware_stack/middleware.rs +153 -0
  29. data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +47 -0
  30. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +58 -0
  31. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +82 -0
  32. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +321 -0
  33. data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +139 -0
  34. data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +300 -0
  35. data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +287 -0
  36. data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +48 -0
  37. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +127 -0
  38. data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +191 -0
  39. data/crates/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +72 -0
  40. data/crates/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +85 -0
  41. data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +195 -0
  42. data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
  43. data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +82 -0
  44. data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +216 -0
  45. data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +124 -0
  46. data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
  47. data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +43 -0
  48. data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +34 -0
  49. data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +93 -0
  50. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +162 -0
  51. data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +158 -0
  52. data/crates/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
  53. data/crates/itsi_server/src/server/middleware_stack/mod.rs +315 -0
  54. data/crates/itsi_server/src/server/mod.rs +8 -1
  55. data/crates/itsi_server/src/server/process_worker.rs +44 -11
  56. data/crates/itsi_server/src/server/rate_limiter.rs +565 -0
  57. data/crates/itsi_server/src/server/request_job.rs +11 -0
  58. data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +129 -46
  59. data/crates/itsi_server/src/server/serve_strategy/mod.rs +9 -6
  60. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +325 -167
  61. data/crates/itsi_server/src/server/signal.rs +20 -4
  62. data/crates/itsi_server/src/server/static_file_server.rs +984 -0
  63. data/crates/itsi_server/src/server/thread_worker.rs +165 -88
  64. data/crates/itsi_server/src/server/tls.rs +1 -1
  65. data/crates/itsi_server/src/server/types.rs +43 -0
  66. data/crates/itsi_server/test.md +14 -0
  67. data/crates/itsi_tracing/Cargo.toml +1 -0
  68. data/crates/itsi_tracing/src/lib.rs +216 -45
  69. data/docs/.gitignore +7 -0
  70. data/docs/.gitpod.yml +15 -0
  71. data/docs/Itsi.rb +17 -0
  72. data/docs/content/_index.md +17 -0
  73. data/docs/content/about.md +6 -0
  74. data/docs/content/docs/_index.md +18 -0
  75. data/docs/content/docs/first-page.md +9 -0
  76. data/docs/content/docs/folder/_index.md +10 -0
  77. data/docs/content/docs/folder/leaf.md +7 -0
  78. data/docs/go.mod +5 -0
  79. data/docs/go.sum +2 -0
  80. data/docs/hugo.yaml +77 -0
  81. data/examples/static_assets_example.rb +83 -0
  82. data/gems/_index.md +18 -0
  83. data/gems/scheduler/CODE_OF_CONDUCT.md +7 -0
  84. data/gems/scheduler/Cargo.lock +75 -14
  85. data/gems/scheduler/README.md +5 -0
  86. data/gems/scheduler/_index.md +7 -0
  87. data/gems/scheduler/itsi-scheduler.gemspec +4 -1
  88. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  89. data/gems/scheduler/lib/itsi/scheduler.rb +2 -2
  90. data/gems/scheduler/test/test_file_io.rb +0 -1
  91. data/gems/scheduler/test/test_itsi_scheduler.rb +1 -1
  92. data/gems/server/CHANGELOG.md +5 -0
  93. data/gems/server/CODE_OF_CONDUCT.md +7 -0
  94. data/gems/server/Cargo.lock +1543 -43
  95. data/gems/server/README.md +4 -0
  96. data/gems/server/_index.md +6 -0
  97. data/gems/server/exe/itsi +46 -57
  98. data/gems/server/itsi-server.gemspec +3 -2
  99. data/gems/server/lib/itsi/{request.rb → http_request.rb} +29 -5
  100. data/gems/server/lib/itsi/http_response.rb +39 -0
  101. data/gems/server/lib/itsi/server/Itsi.rb +119 -0
  102. data/gems/server/lib/itsi/server/config/dsl.rb +506 -0
  103. data/gems/server/lib/itsi/server/config.rb +131 -0
  104. data/gems/server/lib/itsi/server/default_app/default_app.rb +38 -0
  105. data/gems/server/lib/itsi/server/grpc_interface.rb +213 -0
  106. data/gems/server/lib/itsi/server/rack/handler/itsi.rb +9 -6
  107. data/gems/server/lib/itsi/server/rack_interface.rb +24 -9
  108. data/gems/server/lib/itsi/server/scheduler_interface.rb +1 -1
  109. data/gems/server/lib/itsi/server/scheduler_mode.rb +4 -0
  110. data/gems/server/lib/itsi/server/signal_trap.rb +6 -1
  111. data/gems/server/lib/itsi/server/version.rb +1 -1
  112. data/gems/server/lib/itsi/server.rb +75 -60
  113. data/gems/server/lib/itsi/standard_headers.rb +86 -0
  114. data/gems/server/test/helpers/test_helper.rb +14 -12
  115. data/gems/server/test/test_itsi_server.rb +21 -2
  116. data/lib/itsi/version.rb +1 -1
  117. data/sandbox/itsi_file/Gemfile +11 -0
  118. data/sandbox/itsi_file/Gemfile.lock +69 -0
  119. data/sandbox/itsi_file/Itsi.rb +276 -0
  120. data/sandbox/itsi_file/error.html +2 -0
  121. data/sandbox/itsi_file/organisations_controller.rb +20 -0
  122. data/sandbox/itsi_file/public/assets/image.png +0 -0
  123. data/sandbox/itsi_file/public/assets/index.html +1 -0
  124. data/sandbox/itsi_sandbox_async/Gemfile +1 -1
  125. data/sandbox/itsi_sandbox_hanami/Gemfile.lock +2 -2
  126. data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
  127. data/sandbox/itsi_sandbox_rack/config.ru +2 -15
  128. data/sandbox/itsi_sandbox_rails/.dockerignore +2 -5
  129. data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +1 -1
  130. data/sandbox/itsi_sandbox_rails/.gitignore +2 -1
  131. data/sandbox/itsi_sandbox_rails/Dockerfile +6 -9
  132. data/sandbox/itsi_sandbox_rails/Gemfile +16 -22
  133. data/sandbox/itsi_sandbox_rails/Gemfile.lock +100 -225
  134. data/sandbox/itsi_sandbox_rails/app/assets/config/manifest.js +4 -0
  135. data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +11 -6
  136. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/channel.rb +4 -0
  137. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/connection.rb +4 -0
  138. data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +7 -8
  139. data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +0 -3
  140. data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +2 -7
  141. data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +3 -4
  142. data/sandbox/itsi_sandbox_rails/bin/setup +8 -5
  143. data/sandbox/itsi_sandbox_rails/config/application.rb +1 -35
  144. data/sandbox/itsi_sandbox_rails/config/cable.yml +3 -10
  145. data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -1
  146. data/sandbox/itsi_sandbox_rails/config/database.yml +9 -19
  147. data/sandbox/itsi_sandbox_rails/config/environment.rb +1 -1
  148. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +21 -12
  149. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +49 -34
  150. data/sandbox/itsi_sandbox_rails/config/environments/test.rb +19 -5
  151. data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +5 -0
  152. data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +1 -1
  153. data/sandbox/itsi_sandbox_rails/config/initializers/permissions_policy.rb +13 -0
  154. data/sandbox/itsi_sandbox_rails/config/puma.rb +2 -9
  155. data/sandbox/itsi_sandbox_rails/config.ru +0 -1
  156. data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +1 -1
  157. data/sandbox/itsi_sandbox_rails/db/schema.rb +2 -2
  158. data/sandbox/itsi_sandbox_rails/lib/assets/.keep +0 -0
  159. data/sandbox/itsi_sandbox_rails/public/404.html +66 -113
  160. data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +65 -113
  161. data/sandbox/itsi_sandbox_rails/public/422.html +66 -113
  162. data/sandbox/itsi_sandbox_rails/public/500.html +65 -113
  163. data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
  164. data/sandbox/itsi_sandbox_rails/public/icon.svg +2 -2
  165. data/sandbox/itsi_sandbox_rails/test/channels/application_cable/connection_test.rb +13 -0
  166. data/sandbox/itsi_sandbox_roda/Gemfile.lock +3 -10
  167. data/tasks.txt +72 -12
  168. metadata +94 -139
  169. data/crates/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  170. data/crates/itsi_server/src/body_proxy/mod.rs +0 -2
  171. data/crates/itsi_server/src/request/itsi_request.rs +0 -305
  172. data/crates/itsi_server/src/request/mod.rs +0 -1
  173. data/crates/itsi_server/src/response/mod.rs +0 -1
  174. data/crates/itsi_server/src/server/itsi_server.rs +0 -294
  175. data/gems/scheduler/ext/itsi_error/Cargo.lock +0 -368
  176. data/gems/scheduler/ext/itsi_error/Cargo.toml +0 -11
  177. data/gems/scheduler/ext/itsi_error/src/from.rs +0 -68
  178. data/gems/scheduler/ext/itsi_error/src/lib.rs +0 -24
  179. data/gems/scheduler/ext/itsi_instrument_entry/Cargo.toml +0 -15
  180. data/gems/scheduler/ext/itsi_instrument_entry/src/lib.rs +0 -31
  181. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.lock +0 -355
  182. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.toml +0 -10
  183. data/gems/scheduler/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  184. data/gems/scheduler/ext/itsi_rb_helpers/src/lib.rs +0 -178
  185. data/gems/scheduler/ext/itsi_scheduler/Cargo.toml +0 -24
  186. data/gems/scheduler/ext/itsi_scheduler/extconf.rb +0 -6
  187. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  188. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  189. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  190. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  191. data/gems/scheduler/ext/itsi_scheduler/src/lib.rs +0 -38
  192. data/gems/scheduler/ext/itsi_server/Cargo.lock +0 -2956
  193. data/gems/scheduler/ext/itsi_server/Cargo.toml +0 -47
  194. data/gems/scheduler/ext/itsi_server/extconf.rb +0 -6
  195. data/gems/scheduler/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  196. data/gems/scheduler/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  197. data/gems/scheduler/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  198. data/gems/scheduler/ext/itsi_server/src/env.rs +0 -43
  199. data/gems/scheduler/ext/itsi_server/src/lib.rs +0 -112
  200. data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +0 -305
  201. data/gems/scheduler/ext/itsi_server/src/request/mod.rs +0 -1
  202. data/gems/scheduler/ext/itsi_server/src/response/itsi_response.rs +0 -357
  203. data/gems/scheduler/ext/itsi_server/src/response/mod.rs +0 -1
  204. data/gems/scheduler/ext/itsi_server/src/server/bind.rs +0 -170
  205. data/gems/scheduler/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  206. data/gems/scheduler/ext/itsi_server/src/server/io_stream.rs +0 -104
  207. data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +0 -294
  208. data/gems/scheduler/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  209. data/gems/scheduler/ext/itsi_server/src/server/listener.rs +0 -318
  210. data/gems/scheduler/ext/itsi_server/src/server/mod.rs +0 -11
  211. data/gems/scheduler/ext/itsi_server/src/server/process_worker.rs +0 -196
  212. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -254
  213. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  214. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -263
  215. data/gems/scheduler/ext/itsi_server/src/server/signal.rs +0 -77
  216. data/gems/scheduler/ext/itsi_server/src/server/thread_worker.rs +0 -367
  217. data/gems/scheduler/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  218. data/gems/scheduler/ext/itsi_server/src/server/tls.rs +0 -265
  219. data/gems/scheduler/ext/itsi_tracing/Cargo.lock +0 -274
  220. data/gems/scheduler/ext/itsi_tracing/Cargo.toml +0 -16
  221. data/gems/scheduler/ext/itsi_tracing/src/lib.rs +0 -58
  222. data/gems/server/ext/itsi_error/Cargo.lock +0 -368
  223. data/gems/server/ext/itsi_error/Cargo.toml +0 -11
  224. data/gems/server/ext/itsi_error/src/from.rs +0 -68
  225. data/gems/server/ext/itsi_error/src/lib.rs +0 -24
  226. data/gems/server/ext/itsi_instrument_entry/Cargo.toml +0 -15
  227. data/gems/server/ext/itsi_instrument_entry/src/lib.rs +0 -31
  228. data/gems/server/ext/itsi_rb_helpers/Cargo.lock +0 -355
  229. data/gems/server/ext/itsi_rb_helpers/Cargo.toml +0 -10
  230. data/gems/server/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  231. data/gems/server/ext/itsi_rb_helpers/src/lib.rs +0 -178
  232. data/gems/server/ext/itsi_scheduler/Cargo.toml +0 -24
  233. data/gems/server/ext/itsi_scheduler/extconf.rb +0 -6
  234. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  235. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  236. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  237. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  238. data/gems/server/ext/itsi_scheduler/src/lib.rs +0 -38
  239. data/gems/server/ext/itsi_server/Cargo.lock +0 -2956
  240. data/gems/server/ext/itsi_server/Cargo.toml +0 -47
  241. data/gems/server/ext/itsi_server/extconf.rb +0 -6
  242. data/gems/server/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  243. data/gems/server/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  244. data/gems/server/ext/itsi_server/src/env.rs +0 -43
  245. data/gems/server/ext/itsi_server/src/lib.rs +0 -112
  246. data/gems/server/ext/itsi_server/src/request/itsi_request.rs +0 -305
  247. data/gems/server/ext/itsi_server/src/request/mod.rs +0 -1
  248. data/gems/server/ext/itsi_server/src/response/itsi_response.rs +0 -357
  249. data/gems/server/ext/itsi_server/src/response/mod.rs +0 -1
  250. data/gems/server/ext/itsi_server/src/server/bind.rs +0 -170
  251. data/gems/server/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  252. data/gems/server/ext/itsi_server/src/server/io_stream.rs +0 -104
  253. data/gems/server/ext/itsi_server/src/server/itsi_server.rs +0 -294
  254. data/gems/server/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  255. data/gems/server/ext/itsi_server/src/server/listener.rs +0 -318
  256. data/gems/server/ext/itsi_server/src/server/mod.rs +0 -11
  257. data/gems/server/ext/itsi_server/src/server/process_worker.rs +0 -196
  258. data/gems/server/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -254
  259. data/gems/server/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  260. data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -263
  261. data/gems/server/ext/itsi_server/src/server/signal.rs +0 -77
  262. data/gems/server/ext/itsi_server/src/server/thread_worker.rs +0 -367
  263. data/gems/server/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  264. data/gems/server/ext/itsi_server/src/server/tls.rs +0 -265
  265. data/gems/server/ext/itsi_tracing/Cargo.lock +0 -274
  266. data/gems/server/ext/itsi_tracing/Cargo.toml +0 -16
  267. data/gems/server/ext/itsi_tracing/src/lib.rs +0 -58
  268. data/gems/server/lib/itsi/stream_io.rb +0 -38
  269. data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +0 -3
  270. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +0 -3
  271. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +0 -14
  272. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +0 -3
  273. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +0 -3
  274. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +0 -51
  275. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +0 -47
  276. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +0 -109
  277. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +0 -3
  278. data/sandbox/itsi_sandbox_rails/.kamal/secrets +0 -17
  279. data/sandbox/itsi_sandbox_rails/bin/dev +0 -2
  280. data/sandbox/itsi_sandbox_rails/bin/jobs +0 -6
  281. data/sandbox/itsi_sandbox_rails/bin/kamal +0 -27
  282. data/sandbox/itsi_sandbox_rails/bin/thrust +0 -5
  283. data/sandbox/itsi_sandbox_rails/config/cache.yml +0 -16
  284. data/sandbox/itsi_sandbox_rails/config/deploy.yml +0 -116
  285. data/sandbox/itsi_sandbox_rails/config/queue.yml +0 -18
  286. data/sandbox/itsi_sandbox_rails/config/recurring.yml +0 -10
  287. data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +0 -11
  288. data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +0 -14
  289. data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +0 -129
  290. data/sandbox/itsi_sandbox_rails/public/400.html +0 -114
  291. data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +0 -9
  292. data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +0 -7
  293. /data/{sandbox/itsi_sandbox_rails/script/.keep → crates/_index.md} +0 -0
  294. /data/gems/server/lib/itsi/{index.html → server/default_app/index.html} +0 -0
data/Itsi.rb ADDED
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+ # This is the default Itsi configuration file, installed when you run `itsi init`
3
+ # It contains a sane starting point for configuring your Itsi server.
4
+ # You can use this file in both development and production environments.
5
+ # Most of the options in this file can be overridden by command line options.
6
+ # Check out itsi -h to learn more about the command line options available to you.
7
+
8
+ env = ENV.fetch("APP_ENV") { ENV.fetch("RACK_ENV", "development") }
9
+
10
+ # Number of worker processes to spawn
11
+ # If more than 1, Itsi will be booted in Cluster mode
12
+ workers ENV.fetch("ITSI_WORKERS") {
13
+ require "etc"
14
+ env == "development" ? 1 : Etc.nprocessors
15
+ }
16
+
17
+ # Number of threads to spawn per worker process
18
+ # For pure CPU bound applicationss, you'll get the best results keeping this number low
19
+ # Setting a value of 1 is great for superficial benchmarks, but in reality
20
+ # it's better to set this a bit higher to allow expensive requests to get overtaken and minimize head-of-line blocking
21
+ threads ENV.fetch("ITSI_THREADS", 1)
22
+
23
+ # If your application is IO bound (e.g. performing a lot of proxied HTTP requests, or heavy queries etc)
24
+ # you can see *substantial* benefits from enabling this option.
25
+ # To set this option, pass a string, not a class (as we will not have loaded the class yet)
26
+ # E.g.
27
+ # `fiber_scheduler "Itsi::Scheduler"` - The default fast and light-weight scheduler that comes with Itsi
28
+ # `fiber_scheduler "Async::Scheduler"` - Bring your own scheduler!
29
+ fiber_scheduler nil
30
+
31
+ # By default Itsi will run the Rack app from config.ru.
32
+ # You can provide an alternative Rack app file name here
33
+ # Or you can inline the app directly inside Itsi.rb.
34
+ # Only one of `run` and `rackup_file` can be used.
35
+ # E.g.
36
+ # require 'rack'
37
+ # run(Rack::Builder.app do
38
+ # use Rack::CommonLogger
39
+ # run ->(env) { [200, { 'content-type' => 'text/plain' }, ['OK']] }
40
+ # end)
41
+ # rackup_file "config.ru"
42
+
43
+ watch "*.rb", [%w[bundle exec itsi reload]]
44
+ location "/*" do
45
+ get "" do |req|
46
+ req.respond("Hello")
47
+ end
48
+ end
49
+ # run ->(env) { [200, { 'content-type' => 'text/plain' }, ['OK']] }
50
+ # If you bind to https, without specifying a certificate, Itsi will use a self-signed certificate.
51
+ # The self-signed certificate will use a CA generated for your host and stored inside `ITSI_LOCAL_CA_DIR` (Defaults to ~/.itsi)
52
+ # bind "https://localhost:3000"
53
+ # bind "https://localhost:3000?domains=dev.itsi.fyi"
54
+ #
55
+ # If you want to use let's encrypt to generate you a real certificate you and pass cert=acme and an acme_email address to generate one.
56
+ # bind "https://itsi.fyi?cert=acme&acme_email=admin@itsi.fyi"
57
+ # You can generate certificates for multiple domains at once, by passing a comma-separated list of domains
58
+ # bind "https://0.0.0.0?domains=foo.itsi.fyi,bar.itsi.fyi&cert=acme&acme_email=admin@itsi.fyi"
59
+ #
60
+ # If you already have a certificate you can specify it using the cert and key parameters
61
+ # bind "https://itsi.fyi?cert=/path/to/cert.pem&key=/path/to/key.pem"
62
+ #
63
+ # You can also bind to a unix socket or a tls unix socket. E.g.
64
+ # bind "unix:///tmp/itsi.sock"
65
+ # bind "tls:///tmp/itsi.secure.sock"
66
+
67
+ if env == "development"
68
+ bind "http://127.0.0.1:3001"
69
+ else
70
+ bind "https://0.0.0.0?domains=#{ENV["PRODUCTION_DOMAINS"]}&cert=acme&acme_email=admin@itsi.fyi"
71
+ end
72
+
73
+ # If you want to preload the application, set preload to true
74
+ # to load the entire rack-app defined in rack_file_name before forking.
75
+ # Alternatively, you can preload just a specific set of gems in a group in your gemfile,
76
+ # by providing the group name here.
77
+ # E.g.
78
+ #
79
+ # preload :preload # Load gems inside the preload group
80
+ # preload false # Don't preload.
81
+ #
82
+ # If you want to be able to perform zero-downtime deploys using a single itsi process,
83
+ # you should disable preloads, so that the application is loaded fresh each time a new worker boots
84
+ preload true
85
+
86
+ # Set the maximum memory limit for each worker process in bytes
87
+ # When this limit is reached, the worker will be gracefully restarted.
88
+ # Only one worker is restarted at a time to ensure we don't take down
89
+ # all of them at once, if they reach the threshold simultaneously.
90
+ worker_memory_limit 1024 * 1024 * 1024
91
+
92
+ # You can provide an optional block of code to run, when a worker hits its memory threshold (Use this to send yourself an alert,
93
+ # write metrics to disk etc. etc.)
94
+ after_memory_threshold_reached do |pid|
95
+ puts "Worker #{pid} has reached its memory threshold and will restart"
96
+ end
97
+
98
+ # Do clean up of any non-threadsafe resources before forking a new worker here.
99
+ before_fork {}
100
+
101
+ # Reinitialize any non-threadsafe resources after forking a new worker here.
102
+ after_fork {}
103
+
104
+ # Shutdown timeout
105
+ # Number of seconds to wait for workers to gracefully shutdown before killing them.
106
+ shutdown_timeout 5
107
+
108
+ # Set this to false for application environments that require rack.input to be a rewindable body
109
+ # (like Rails). For rack applications that can stream inputs, you can set this to true for a more memory-efficient approach.
110
+ stream_body false
111
+
112
+ # OOB GC responses threshold
113
+ # Specifies how frequently OOB gc should be triggered during periods where there is a gap in queued requests.
114
+ # Setting this too low can substantially worsen performance
115
+ oob_gc_responses_threshold 512
116
+
117
+ # Log level
118
+ # Set this to one of the following values: debug, info, warn, error, fatal
119
+ # Can also be set using the ITSI_LOG environment variable
120
+ log_level :info
121
+
122
+ # Log Format
123
+ # Set this to be either :ansi or :json. If you leave it blank Itsi will try
124
+ # and auto-detect the format based on the TTY environment.
125
+ log_format :auto
data/Rakefile CHANGED
@@ -34,6 +34,7 @@ GEMS.each do |gem|
34
34
 
35
35
  SHARED_TASKS.each do |task|
36
36
  task task do
37
+ Rake::Task[:sync_crates].invoke
37
38
  sh "cd #{gem[:dir]} && rake #{task}"
38
39
  end
39
40
  end
@@ -57,6 +58,8 @@ task :sync_crates do
57
58
  GEMS.each do |gem_info|
58
59
  Dir.chdir('crates') do
59
60
  to_sync = Dir['*'].each do |to_sync|
61
+ next unless File.directory?(to_sync)
62
+
60
63
  system("rsync -q -av #{to_sync}/ ../#{gem_info[:dir]}/ext/#{to_sync} --delete")
61
64
  system("cp ../Cargo.lock ../#{gem_info[:dir]}/Cargo.lock")
62
65
  end
@@ -77,19 +80,20 @@ task :build_all do
77
80
  end
78
81
 
79
82
  task :test_env_up do
80
- system("terraform -chdir=sandbox/deploy apply")
83
+ system('terraform -chdir=sandbox/deploy apply')
81
84
  end
82
85
 
83
86
  task :test_env_down do
84
- system("terraform -chdir=sandbox/deploy destroy")
87
+ system('terraform -chdir=sandbox/deploy destroy')
85
88
  end
86
-
87
89
  %i[itsi puma iodine falcon unicorn].each do |server|
88
90
  namespace server do
89
91
  %i[hanami roda async rack rack_lint rails sinatra].each do |sandbox|
90
92
  namespace sandbox do
91
93
  task :serve do |args|
92
- sh "(cd sandbox/itsi_sandbox_#{sandbox} && bundle exec #{server} #{ARGV[2..]&.join(" ")} )"
94
+ system("(cd sandbox/itsi_sandbox_#{sandbox} && bundle exec #{server} #{ARGV[2..]&.join(' ')} )")
95
+ rescue Interrupt
96
+ # Suppress the stacktrace and message for Interrupt
93
97
  end
94
98
  end
95
99
  end
@@ -22,3 +22,12 @@ pub enum ItsiError {
22
22
  #[error("Pass")]
23
23
  Pass(),
24
24
  }
25
+
26
+ impl ItsiError {
27
+ pub fn default(error: impl Send + Sync + 'static + std::fmt::Display) -> Self {
28
+ ItsiError::InvalidInput(format!("{}", error))
29
+ }
30
+ }
31
+
32
+ unsafe impl Send for ItsiError {}
33
+ unsafe impl Sync for ItsiError {}
@@ -8,3 +8,4 @@ cfg-if = "1.0.0"
8
8
  magnus = { version = "0.7.1", features = ["rb-sys", "bytes"] }
9
9
  nix = "0.29.0"
10
10
  rb-sys = "0.9.105"
11
+ serde = "1.0.219"
@@ -23,6 +23,24 @@ where
23
23
  }
24
24
  }
25
25
 
26
+ impl<T> HeapValue<T>
27
+ where
28
+ T: ReprValue,
29
+ {
30
+ pub fn into_inner(self) -> T {
31
+ *self.0
32
+ }
33
+ }
34
+
35
+ impl<T> HeapValue<T>
36
+ where
37
+ T: ReprValue,
38
+ {
39
+ pub fn cloned(&self) -> T {
40
+ *self.0
41
+ }
42
+ }
43
+
26
44
  impl<T> Deref for HeapValue<T>
27
45
  where
28
46
  T: ReprValue,
@@ -1,13 +1,14 @@
1
- use std::{os::raw::c_void, ptr::null_mut, sync::Arc};
1
+ use std::{ffi::c_int, os::raw::c_void, ptr::null_mut};
2
2
 
3
3
  use magnus::{
4
- RArray, Ruby, Thread, Value,
5
- rb_sys::FromRawValue,
6
- value::{LazyId, ReprValue},
4
+ ArgList, RArray, Ruby, Thread, Value,
5
+ block::Proc,
6
+ rb_sys::{AsRawId, FromRawValue, protect},
7
+ value::{IntoId, LazyId, ReprValue},
7
8
  };
8
9
  use rb_sys::{
9
- rb_thread_call_with_gvl, rb_thread_call_without_gvl, rb_thread_create, rb_thread_schedule,
10
- rb_thread_wakeup,
10
+ VALUE, rb_funcallv, rb_thread_call_with_gvl, rb_thread_call_without_gvl, rb_thread_create,
11
+ rb_thread_schedule, rb_thread_wakeup,
11
12
  };
12
13
 
13
14
  mod heap_value;
@@ -17,6 +18,7 @@ static ID_LIST: LazyId = LazyId::new("list");
17
18
  static ID_EQ: LazyId = LazyId::new("==");
18
19
  static ID_ALIVE: LazyId = LazyId::new("alive?");
19
20
  static ID_THREAD_VARIABLE_GET: LazyId = LazyId::new("thread_variable_get");
21
+ static ID_BACKTRACE: LazyId = LazyId::new("backtrace");
20
22
 
21
23
  pub fn schedule_thread() {
22
24
  unsafe {
@@ -120,20 +122,30 @@ where
120
122
  *result_box
121
123
  }
122
124
 
123
- pub fn fork(after_fork: Arc<Option<impl Fn()>>) -> Option<i32> {
125
+ pub fn fork(after_fork: Option<HeapValue<Proc>>) -> Option<i32> {
124
126
  let ruby = Ruby::get().unwrap();
125
127
  let fork_result = ruby
126
128
  .module_kernel()
127
129
  .funcall::<_, _, Option<i32>>(*ID_FORK, ())
128
130
  .unwrap();
129
131
  if fork_result.is_none() {
130
- if let Some(f) = &*after_fork {
131
- f()
132
+ if let Some(proc) = after_fork {
133
+ call_proc_and_log_errors(proc)
132
134
  }
133
135
  }
134
136
  fork_result
135
137
  }
136
138
 
139
+ pub fn call_proc_and_log_errors(proc: HeapValue<Proc>) {
140
+ if let Err(e) = proc.call::<_, Value>(()) {
141
+ if let Some(value) = e.value() {
142
+ print_rb_backtrace(value);
143
+ } else {
144
+ eprintln!("Error occurred {:?}", e);
145
+ }
146
+ }
147
+ }
148
+
137
149
  pub fn kill_threads<T>(threads: Vec<T>)
138
150
  where
139
151
  T: ReprValue,
@@ -176,3 +188,41 @@ pub fn terminate_non_fork_safe_threads() {
176
188
 
177
189
  kill_threads(non_fork_safe_threads);
178
190
  }
191
+
192
+ pub fn print_rb_backtrace(rb_err: Value) {
193
+ let backtrace = rb_err
194
+ .funcall::<_, _, Vec<String>>(*ID_BACKTRACE, ())
195
+ .unwrap_or_default();
196
+ let rust_backtrace = std::backtrace::Backtrace::capture().to_string();
197
+ eprintln!("Ruby exception {:?}", rb_err);
198
+ for line in backtrace {
199
+ eprintln!("{}", line);
200
+ }
201
+ for line in rust_backtrace.lines() {
202
+ eprintln!("{}", line);
203
+ }
204
+ }
205
+
206
+ pub fn funcall_no_ret<T, M, A>(target: T, method: M, args: A) -> magnus::error::Result<()>
207
+ where
208
+ T: ReprValue,
209
+ M: IntoId,
210
+ A: ArgList,
211
+ {
212
+ protect(|| {
213
+ let handle = Ruby::get().unwrap();
214
+ let method = method.into_id_with(&handle);
215
+ let args = args.into_arg_list_with(&handle);
216
+ let slice = args.as_ref();
217
+ unsafe {
218
+ rb_funcallv(
219
+ target.as_rb_value(),
220
+ method.as_raw(),
221
+ slice.len() as c_int,
222
+ slice.as_ptr() as *const VALUE,
223
+ );
224
+ }
225
+ 0
226
+ })?;
227
+ Ok(())
228
+ }
@@ -10,38 +10,80 @@ publish = false
10
10
  crate-type = ["cdylib"]
11
11
 
12
12
  [dependencies]
13
- magnus = { version = "0.7.1", features = ["bytes", "rb-sys"] }
14
- itsi_tracing = { path = "../itsi_tracing" }
15
- itsi_rb_helpers = { path = "../itsi_rb_helpers" }
16
- itsi_error = { path = "../itsi_error" }
17
- socket2 = "0.5.8"
18
- parking_lot = "0.12.3"
19
- rustls-pemfile = "2.2.0"
20
- tokio-rustls = "0.26.2"
21
- bytes = "1.3"
22
- tokio-rustls-acme = "0.6.0"
23
- rcgen = { version = "0.13.2", features = ["x509-parser", "pem"] }
13
+ async-compression = { version = "0.4.21", features = [
14
+ "tokio",
15
+ "zstd",
16
+ "brotli",
17
+ "deflate",
18
+ "gzip",
19
+ ] }
20
+ async-channel = "2.3.1"
21
+ async-trait = "0.1.87"
24
22
  base64 = "0.22.1"
23
+ bytes = "1.3"
24
+ chrono = "0.4.35"
25
+ crossbeam = "0.8.4"
26
+ dashmap = "6.1.0"
27
+ derive_more = { version = "2.0.1", features = ["debug"] }
28
+ dirs = "6.0.0"
29
+ either = "1.15.0"
30
+ fnv = "1.0.7"
31
+ fs2 = "0.4.3"
32
+ futures = "0.3.31"
33
+ globset = "0.4.16"
34
+ hmac = "0.12.1"
35
+ http = "1.3.1"
25
36
  http-body-util = "0.1.2"
37
+ httpdate = "1.0.3"
38
+ httparse = "1.10.1"
26
39
  hyper = { version = "1.5.0", features = ["full", "server", "http1", "http2"] }
27
- tokio = { version = "1", features = ["full"] }
40
+ hyper-staticfile = "0.10.1"
28
41
  hyper-util = { version = "0.1.10", features = ["full"] }
29
- derive_more = { version = "2.0.1", features = ["debug"] }
30
- http = "1.3.1"
31
- crossbeam = "0.8.4"
32
- futures = "0.3.31"
33
- nix = { version = "0.29.0", features = ["socket", "uio", "signal"] }
42
+ itsi_error = { path = "../itsi_error" }
43
+ itsi_rb_helpers = { path = "../itsi_rb_helpers" }
44
+ itsi_tracing = { path = "../itsi_tracing" }
45
+ jwt-simple = "0.12.12"
46
+ magnus = { version = "0.7.1", features = ["bytes", "rb-sys"] }
47
+ moka = { version = "0.12.10", features = ["sync"] }
48
+ notify = { version = "8.0.0" }
49
+ nix = { version = "0.29.0", features = [
50
+ "socket",
51
+ "uio",
52
+ "signal",
53
+ "fs",
54
+ "process",
55
+ ] }
56
+ num_cpus = "1.16.0"
57
+ parking_lot = "0.12.3"
34
58
  pin-project = "1.1.9"
59
+ rand = "0.9.0"
35
60
  rb-sys = "0.9.111"
36
- tracing = "0.1.41"
37
- tokio-util = "0.7.13"
38
- tokio-stream = "0.1.17"
39
- httparse = "1.10.1"
40
- async-channel = "2.3.1"
41
- tempfile = "3.18.0"
42
- sysinfo = "0.33.1"
43
- rustls = "0.23.23"
44
- fs2 = "0.4.3"
61
+ rcgen = { version = "0.13.2", features = ["x509-parser", "pem"] }
62
+ regex = "1.11.1"
63
+ reqwest = { version = "0.12.15", features = ["stream"] }
45
64
  ring = "0.17.14"
46
- async-trait = "0.1.87"
47
- dirs = "6.0.0"
65
+ route-recognizer = "0.3.1"
66
+ redis = { version = "0.29.2", features = [
67
+ "tokio-comp",
68
+ "r2d2",
69
+ "tokio-rustls-comp",
70
+ "connection-manager",
71
+ ] }
72
+ rustls = "0.23.23"
73
+ rustls-pemfile = "2.2.0"
74
+ serde = "1.0.219"
75
+ serde_json = "1.0.140"
76
+ serde_magnus = "0.9.0"
77
+ sha2 = "0.10.8"
78
+ socket2 = "0.5.8"
79
+ sysinfo = "0.33.1"
80
+ tempfile = "3.18.0"
81
+ tokio = { version = "1.44.1", features = ["full"] }
82
+ tokio-rustls = "0.26.2"
83
+ tokio-rustls-acme = "0.6.0"
84
+ tokio-stream = "0.1.17"
85
+ tokio-util = "0.7.13"
86
+ tracing = "0.1.41"
87
+ url = "2.5.4"
88
+ uuid = "1.16.0"
89
+ md5 = "0.7.0"
@@ -1,59 +1,17 @@
1
- use body_proxy::itsi_body_proxy::ItsiBodyProxy;
2
- use magnus::{error::Result, function, method, value::Lazy, Module, Object, RClass, RModule, Ruby};
3
- use request::itsi_request::ItsiRequest;
4
- use response::itsi_response::ItsiResponse;
5
- use server::{itsi_server::Server, signal::reset_signal_handlers};
1
+ use magnus::{error::Result, function, method, Module, Object, Ruby};
2
+ use ruby_types::{
3
+ itsi_body_proxy::ItsiBodyProxy, itsi_grpc_request::ItsiGrpcRequest,
4
+ itsi_grpc_stream::ItsiGrpcStream, itsi_http_request::ItsiHttpRequest,
5
+ itsi_http_response::ItsiHttpResponse, itsi_server::ItsiServer, ITSI_BODY_PROXY,
6
+ ITSI_GRPC_REQUEST, ITSI_GRPC_RESPONSE, ITSI_GRPC_STREAM, ITSI_MODULE, ITSI_REQUEST,
7
+ ITSI_RESPONSE, ITSI_SERVER,
8
+ };
9
+ use server::signal::reset_signal_handlers;
6
10
  use tracing::*;
7
-
8
- pub mod body_proxy;
9
11
  pub mod env;
10
- pub mod request;
11
- pub mod response;
12
+ pub mod ruby_types;
12
13
  pub mod server;
13
14
 
14
- pub static ITSI_MODULE: Lazy<RModule> = Lazy::new(|ruby| ruby.define_module("Itsi").unwrap());
15
- pub static ITSI_SERVER: Lazy<RClass> = Lazy::new(|ruby| {
16
- ruby.get_inner(&ITSI_MODULE)
17
- .define_class("Server", ruby.class_object())
18
- .unwrap()
19
- });
20
- pub static ITSI_REQUEST: Lazy<RClass> = Lazy::new(|ruby| {
21
- ruby.get_inner(&ITSI_MODULE)
22
- .define_class("Request", ruby.class_object())
23
- .unwrap()
24
- });
25
-
26
- pub static ITSI_RESPONSE: Lazy<RClass> = Lazy::new(|ruby| {
27
- ruby.get_inner(&ITSI_MODULE)
28
- .define_class("Response", ruby.class_object())
29
- .unwrap()
30
- });
31
-
32
- pub static ITSI_BODY_PROXY: Lazy<RClass> = Lazy::new(|ruby| {
33
- ruby.get_inner(&ITSI_MODULE)
34
- .define_class("BodyProxy", ruby.class_object())
35
- .unwrap()
36
- });
37
-
38
- pub static ITSI_SERVER_SCHEDULER_TASK: Lazy<RClass> = Lazy::new(|ruby| {
39
- ruby.get_inner(&ITSI_MODULE)
40
- .define_class("ServerSchedulerTask", ruby.class_object())
41
- .unwrap()
42
- });
43
-
44
- pub fn log_debug(msg: String) {
45
- debug!(msg);
46
- }
47
- pub fn log_info(msg: String) {
48
- info!(msg);
49
- }
50
- pub fn log_warn(msg: String) {
51
- warn!(msg);
52
- }
53
- pub fn log_error(msg: String) {
54
- error!(msg);
55
- }
56
-
57
15
  #[magnus::init]
58
16
  fn init(ruby: &Ruby) -> Result<()> {
59
17
  itsi_tracing::init();
@@ -68,27 +26,29 @@ fn init(ruby: &Ruby) -> Result<()> {
68
26
  itsi.define_singleton_method("log_error", function!(log_error, 1))?;
69
27
 
70
28
  let server = ruby.get_inner(&ITSI_SERVER);
71
- server.define_singleton_method("new", function!(Server::new, -1))?;
29
+ server.define_singleton_method("new", function!(ItsiServer::new, 3))?;
72
30
  server.define_singleton_method("reset_signal_handlers", function!(reset_signal_handlers, 0))?;
73
- server.define_method("start", method!(Server::start, 0))?;
74
- server.define_method("stop", method!(Server::stop, 0))?;
31
+ server.define_method("start", method!(ItsiServer::start, 0))?;
32
+ server.define_method("stop", method!(ItsiServer::stop, 0))?;
75
33
 
76
34
  let request = ruby.get_inner(&ITSI_REQUEST);
77
- request.define_method("path", method!(ItsiRequest::path, 0))?;
78
- request.define_method("script_name", method!(ItsiRequest::script_name, 0))?;
79
- request.define_method("query_string", method!(ItsiRequest::query_string, 0))?;
80
- request.define_method("method", method!(ItsiRequest::method, 0))?;
81
- request.define_method("version", method!(ItsiRequest::version, 0))?;
82
- request.define_method("rack_protocol", method!(ItsiRequest::rack_protocol, 0))?;
83
- request.define_method("host", method!(ItsiRequest::host, 0))?;
84
- request.define_method("headers", method!(ItsiRequest::headers, 0))?;
85
- request.define_method("scheme", method!(ItsiRequest::scheme, 0))?;
86
- request.define_method("remote_addr", method!(ItsiRequest::remote_addr, 0))?;
87
- request.define_method("port", method!(ItsiRequest::port, 0))?;
88
- request.define_method("body", method!(ItsiRequest::body, 0))?;
89
- request.define_method("response", method!(ItsiRequest::response, 0))?;
90
- request.define_method("json?", method!(ItsiRequest::is_json, 0))?;
91
- request.define_method("html?", method!(ItsiRequest::is_html, 0))?;
35
+ request.define_method("path", method!(ItsiHttpRequest::path, 0))?;
36
+ request.define_method("script_name", method!(ItsiHttpRequest::script_name, 0))?;
37
+ request.define_method("query_string", method!(ItsiHttpRequest::query_string, 0))?;
38
+ request.define_method("method", method!(ItsiHttpRequest::method, 0))?;
39
+ request.define_method("version", method!(ItsiHttpRequest::version, 0))?;
40
+ request.define_method("rack_protocol", method!(ItsiHttpRequest::rack_protocol, 0))?;
41
+ request.define_method("host", method!(ItsiHttpRequest::host, 0))?;
42
+ request.define_method("headers", method!(ItsiHttpRequest::headers, 0))?;
43
+ request.define_method("header", method!(ItsiHttpRequest::header, 1))?;
44
+ request.define_method("[]", method!(ItsiHttpRequest::header, 1))?;
45
+ request.define_method("scheme", method!(ItsiHttpRequest::scheme, 0))?;
46
+ request.define_method("remote_addr", method!(ItsiHttpRequest::remote_addr, 0))?;
47
+ request.define_method("port", method!(ItsiHttpRequest::port, 0))?;
48
+ request.define_method("body", method!(ItsiHttpRequest::body, 0))?;
49
+ request.define_method("response", method!(ItsiHttpRequest::response, 0))?;
50
+ request.define_method("json?", method!(ItsiHttpRequest::is_json, 0))?;
51
+ request.define_method("html?", method!(ItsiHttpRequest::is_html, 0))?;
92
52
 
93
53
  let body_proxy = ruby.get_inner(&ITSI_BODY_PROXY);
94
54
  body_proxy.define_method("gets", method!(ItsiBodyProxy::gets, 0))?;
@@ -97,16 +57,56 @@ fn init(ruby: &Ruby) -> Result<()> {
97
57
  body_proxy.define_method("close", method!(ItsiBodyProxy::close, 0))?;
98
58
 
99
59
  let response = ruby.get_inner(&ITSI_RESPONSE);
100
- response.define_method("add_header", method!(ItsiResponse::add_header, 2))?;
101
- response.define_method("status=", method!(ItsiResponse::set_status, 1))?;
102
- response.define_method("send_frame", method!(ItsiResponse::send_frame, 1))?;
103
- response.define_method("send_and_close", method!(ItsiResponse::send_and_close, 1))?;
104
- response.define_method("close_write", method!(ItsiResponse::close_write, 0))?;
105
- response.define_method("close_read", method!(ItsiResponse::close_read, 0))?;
106
- response.define_method("close", method!(ItsiResponse::close, 0))?;
107
- response.define_method("hijack", method!(ItsiResponse::hijack, 1))?;
108
- response.define_method("json?", method!(ItsiResponse::is_json, 0))?;
109
- response.define_method("html?", method!(ItsiResponse::is_html, 0))?;
60
+ response.define_method("[]=", method!(ItsiHttpResponse::add_header, 2))?;
61
+ response.define_method("add_header", method!(ItsiHttpResponse::add_header, 2))?;
62
+ response.define_method("add_headers", method!(ItsiHttpResponse::add_headers, 1))?;
63
+ response.define_method("status=", method!(ItsiHttpResponse::set_status, 1))?;
64
+ response.define_method("send_frame", method!(ItsiHttpResponse::send_frame, 1))?;
65
+ response.define_method("<<", method!(ItsiHttpResponse::send_frame, 1))?;
66
+ response.define_method("write", method!(ItsiHttpResponse::send_frame, 1))?;
67
+ response.define_method("read", method!(ItsiHttpResponse::recv_frame, 0))?;
68
+ response.define_method(
69
+ "send_and_close",
70
+ method!(ItsiHttpResponse::send_and_close, 1),
71
+ )?;
72
+ response.define_method("close_write", method!(ItsiHttpResponse::close_write, 0))?;
73
+ response.define_method("close_read", method!(ItsiHttpResponse::close_read, 0))?;
74
+ response.define_method("close", method!(ItsiHttpResponse::close, 0))?;
75
+ response.define_method("hijack", method!(ItsiHttpResponse::hijack, 1))?;
76
+ response.define_method("json?", method!(ItsiHttpResponse::is_json, 0))?;
77
+ response.define_method("html?", method!(ItsiHttpResponse::is_html, 0))?;
78
+
79
+ let grpc_request = ruby.get_inner(&ITSI_GRPC_REQUEST);
80
+
81
+ grpc_request.define_method("service_name", method!(ItsiGrpcRequest::service_name, 0))?;
82
+ grpc_request.define_method("method_name", method!(ItsiGrpcRequest::method_name, 0))?;
83
+ grpc_request.define_method("stream", method!(ItsiGrpcRequest::stream, 0))?;
84
+ grpc_request.define_method("json?", method!(ItsiGrpcRequest::is_json, 0))?;
85
+ grpc_request.define_method(
86
+ "content_type",
87
+ method!(ItsiGrpcRequest::content_type_str, 0),
88
+ )?;
89
+
90
+ let grpc_stream = ruby.get_inner(&ITSI_GRPC_STREAM);
91
+ grpc_stream.define_method("read", method!(ItsiGrpcStream::read, 1))?;
92
+ grpc_stream.define_method("write", method!(ItsiGrpcStream::write, 1))?;
93
+ grpc_stream.define_method("flush", method!(ItsiGrpcStream::flush, 0))?;
94
+ grpc_stream.define_method("send_trailers", method!(ItsiGrpcStream::send_trailers, 1))?;
95
+
96
+ let _grpc_response = ruby.get_inner(&ITSI_GRPC_RESPONSE);
110
97
 
111
98
  Ok(())
112
99
  }
100
+
101
+ pub fn log_debug(msg: String) {
102
+ debug!(msg);
103
+ }
104
+ pub fn log_info(msg: String) {
105
+ info!(msg);
106
+ }
107
+ pub fn log_warn(msg: String) {
108
+ warn!(msg);
109
+ }
110
+ pub fn log_error(msg: String) {
111
+ error!(msg);
112
+ }
@@ -6,7 +6,7 @@ use tempfile::NamedTempFile;
6
6
 
7
7
  const THRESHOLD: usize = 1024 * 1024; // 1 MB
8
8
 
9
- /// An container that holds data in memory if it’s small, or in a temporary file on disk if it exceeds THRESHOLD.
9
+ /// A container that will hold data in memory if it’s small, or in a temporary file on disk if it exceeds THRESHOLD.
10
10
  /// Used for providing Rack input data.
11
11
  pub enum BigBytes {
12
12
  InMemory(Vec<u8>),
@@ -27,7 +27,7 @@ impl BigBytes {
27
27
  BigBytes::InMemory(Vec::new())
28
28
  }
29
29
 
30
- /// Reads the entire contents that have been written.
30
+ /// Returns either the raw bytes, or the file path of the BigBytes
31
31
  ///
32
32
  /// - If stored in memory, returns a clone of the bytes.
33
33
  /// - If stored on disk, returns the file path of the temporary file.
@@ -42,17 +42,22 @@ impl BigBytes {
42
42
  }
43
43
  }
44
44
 
45
- pub fn as_value(&self) -> Value {
45
+ /// Turn this into a value that can be used in Ruby.
46
+ pub fn as_value(&self) -> Option<Value> {
46
47
  match self {
47
48
  BigBytes::InMemory(bytes) => {
48
49
  let bytes = Bytes::from(bytes.to_owned());
49
- bytes.into_value()
50
+ if bytes.is_empty() {
51
+ None
52
+ } else {
53
+ Some(bytes.into_value())
54
+ }
50
55
  }
51
56
  BigBytes::OnDisk(path) => {
52
57
  let ruby = Ruby::get().unwrap();
53
58
  let rarray = ruby.ary_new();
54
59
  rarray.push(path.path().to_str().unwrap().into_value()).ok();
55
- rarray.into_value()
60
+ Some(rarray.into_value())
56
61
  }
57
62
  }
58
63
  }