itsi 0.1.20 → 0.2.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -8
- data/Cargo.lock +29 -30
- data/LICENSE.txt +698 -0
- data/README.md +16 -4
- data/Rakefile +9 -5
- data/crates/itsi_acme/.gitignore +4 -0
- data/crates/itsi_acme/Cargo.toml +86 -0
- data/crates/itsi_acme/LICENSE-APACHE +201 -0
- data/crates/itsi_acme/LICENSE-MIT +23 -0
- data/crates/itsi_acme/README.md +9 -0
- data/crates/itsi_acme/examples/high_level.rs +63 -0
- data/crates/itsi_acme/examples/high_level_warp.rs +52 -0
- data/crates/itsi_acme/examples/low_level.rs +87 -0
- data/crates/itsi_acme/examples/low_level_axum.rs +66 -0
- data/crates/itsi_acme/src/acceptor.rs +81 -0
- data/crates/itsi_acme/src/acme.rs +354 -0
- data/crates/itsi_acme/src/axum.rs +86 -0
- data/crates/itsi_acme/src/cache.rs +39 -0
- data/crates/itsi_acme/src/caches/boxed.rs +80 -0
- data/crates/itsi_acme/src/caches/composite.rs +69 -0
- data/crates/itsi_acme/src/caches/dir.rs +106 -0
- data/crates/itsi_acme/src/caches/mod.rs +11 -0
- data/crates/itsi_acme/src/caches/no.rs +78 -0
- data/crates/itsi_acme/src/caches/test.rs +136 -0
- data/crates/itsi_acme/src/config.rs +172 -0
- data/crates/itsi_acme/src/https_helper.rs +69 -0
- data/crates/itsi_acme/src/incoming.rs +142 -0
- data/crates/itsi_acme/src/jose.rs +161 -0
- data/crates/itsi_acme/src/lib.rs +142 -0
- data/crates/itsi_acme/src/resolver.rs +59 -0
- data/crates/itsi_acme/src/state.rs +424 -0
- data/crates/itsi_rb_helpers/src/lib.rs +4 -3
- data/crates/itsi_scheduler/Cargo.toml +1 -1
- data/crates/itsi_scheduler/src/itsi_scheduler.rs +8 -2
- data/crates/itsi_scheduler/src/lib.rs +1 -0
- data/crates/itsi_server/Cargo.toml +1 -1
- data/crates/itsi_server/src/lib.rs +2 -1
- data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +18 -1
- data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +11 -3
- data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +148 -66
- data/crates/itsi_server/src/ruby_types/itsi_server.rs +2 -0
- data/crates/itsi_server/src/server/binds/bind.rs +3 -0
- data/crates/itsi_server/src/server/binds/listener.rs +12 -5
- data/crates/itsi_server/src/server/binds/tls.rs +13 -5
- data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +12 -5
- data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +8 -1
- data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +9 -1
- data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +48 -43
- data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +11 -2
- data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +39 -12
- data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +36 -27
- data/crates/itsi_server/src/server/middleware_stack/middlewares/csp.rs +25 -11
- data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +12 -3
- data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +74 -72
- data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +15 -1
- data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +11 -8
- data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +19 -11
- data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +5 -5
- data/crates/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +2 -2
- data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +11 -5
- data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +17 -20
- data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +19 -8
- data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +16 -37
- data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +22 -12
- data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +26 -11
- data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +7 -1
- data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +14 -4
- data/crates/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +19 -0
- data/crates/itsi_server/src/server/middleware_stack/mod.rs +49 -13
- data/crates/itsi_server/src/server/mod.rs +1 -0
- data/crates/itsi_server/src/server/redirect_type.rs +26 -0
- data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +22 -16
- data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +49 -12
- data/crates/itsi_server/src/server/signal.rs +1 -0
- data/crates/itsi_server/src/server/size_limited_incoming.rs +6 -0
- data/crates/itsi_server/src/server/thread_worker.rs +5 -1
- data/crates/itsi_server/src/services/itsi_http_service.rs +20 -2
- data/crates/itsi_server/src/services/rate_limiter.rs +15 -4
- data/crates/itsi_server/src/services/static_file_server.rs +33 -19
- data/crates/itsi_tracing/src/lib.rs +42 -22
- data/docs/content/_index.md +2 -3
- data/docs/content/acknowledgements/_index.md +5 -2
- data/docs/content/configuration/_index.md +8 -5
- data/docs/content/contact/_index.md +8 -1
- data/docs/content/directory_listing.jpg +0 -0
- data/docs/content/error_page.jpg +0 -0
- data/docs/content/faqs/_index.md +5 -3
- data/docs/content/features/_index.md +56 -50
- data/docs/content/getting_started/_index.md +8 -5
- data/docs/content/getting_started/local_development.md +76 -9
- data/docs/content/getting_started/logging.md +15 -9
- data/docs/content/getting_started/running_itsi_in_production.md +5 -3
- data/docs/content/getting_started/signals.md +37 -0
- data/docs/content/itsi_scheduler/_index.md +8 -7
- data/docs/content/utilities/_index.md +13 -0
- data/docs/content/utilities/config_file_testing.md +17 -0
- data/docs/content/utilities/passfile_generator.md +41 -0
- data/docs/content/utilities/route_testing.md +27 -0
- data/docs/content/utilities/secrets_management.md +30 -0
- data/docs/hugo.yaml +4 -1
- data/fairytale.txt +3 -4
- data/gems/scheduler/Cargo.lock +74 -17
- data/gems/scheduler/README.md +4 -5
- data/gems/scheduler/Rakefile +0 -4
- data/gems/scheduler/itsi-scheduler.gemspec +2 -2
- data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
- data/gems/scheduler/lib/itsi/scheduler.rb +9 -4
- data/gems/scheduler/test/test_active_record.rb +12 -7
- data/gems/server/Cargo.lock +28 -29
- data/gems/server/Rakefile +0 -4
- data/gems/server/exe/itsi +13 -2
- data/gems/server/itsi-server.gemspec +2 -2
- data/gems/server/lib/itsi/http_request/response_status_shortcodes.rb +2 -0
- data/gems/server/lib/itsi/http_request.rb +58 -30
- data/gems/server/lib/itsi/http_response.rb +10 -7
- data/gems/server/lib/itsi/passfile.rb +6 -7
- data/gems/server/lib/itsi/server/config/config_helpers.rb +41 -29
- data/gems/server/lib/itsi/server/config/dsl.rb +22 -442
- data/gems/server/lib/itsi/server/config/known_paths.rb +14 -7
- data/gems/server/lib/itsi/server/config/middleware/_index.md +6 -4
- data/gems/server/lib/itsi/server/config/middleware/allow_list.md +46 -0
- data/gems/server/lib/itsi/server/config/middleware/allow_list.rb +42 -0
- data/gems/server/lib/itsi/server/config/middleware/auth_api_key.md +90 -0
- data/gems/server/lib/itsi/server/config/middleware/auth_api_key.rb +51 -0
- data/gems/server/lib/itsi/server/config/middleware/auth_basic.md +45 -0
- data/gems/server/lib/itsi/server/config/middleware/auth_basic.rb +44 -0
- data/gems/server/lib/itsi/server/config/middleware/auth_jwt.md +82 -0
- data/gems/server/lib/itsi/server/config/middleware/auth_jwt.rb +38 -0
- data/gems/server/lib/itsi/server/config/middleware/cache_control.md +78 -0
- data/gems/server/lib/itsi/server/config/middleware/cache_control.rb +45 -0
- data/gems/server/lib/itsi/server/config/middleware/cidr_to_regex.rb +50 -0
- data/gems/server/lib/itsi/server/config/middleware/compression.md +50 -0
- data/gems/server/lib/itsi/server/config/middleware/compression.rb +37 -0
- data/gems/server/lib/itsi/server/config/middleware/cors.md +93 -0
- data/gems/server/lib/itsi/server/config/middleware/cors.rb +32 -0
- data/gems/server/lib/itsi/server/config/middleware/csp.md +37 -0
- data/gems/server/lib/itsi/server/config/middleware/csp.rb +44 -0
- data/gems/server/lib/itsi/server/config/middleware/deny_list.md +45 -0
- data/gems/server/lib/itsi/server/config/middleware/deny_list.rb +42 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/_index.md +159 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/controller.md +186 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/controller.rb +33 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/delete.md +12 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/delete.rb +42 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/endpoint.rb +99 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/get.md +12 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/get.rb +42 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/http_request.md +44 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/http_response.md +39 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/patch.md +12 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/patch.rb +42 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/post.md +12 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/post.rb +42 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/put.md +12 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/put.rb +42 -0
- data/gems/server/lib/itsi/server/config/middleware/endpoint/schemas.md +122 -0
- data/gems/server/lib/itsi/server/config/middleware/error_response.md +74 -0
- data/gems/server/lib/itsi/server/config/middleware/error_response.rb +36 -0
- data/gems/server/lib/itsi/server/config/middleware/etag.md +59 -0
- data/gems/server/lib/itsi/server/config/middleware/etag.rb +27 -0
- data/gems/server/lib/itsi/server/config/middleware/grpc.md +172 -0
- data/gems/server/lib/itsi/server/config/middleware/grpc.rb +54 -0
- data/gems/server/lib/itsi/server/config/middleware/intrusion_protection.md +124 -0
- data/gems/server/lib/itsi/server/config/middleware/intrusion_protection.rb +61 -0
- data/gems/server/lib/itsi/server/config/middleware/location.md +107 -0
- data/gems/server/lib/itsi/server/config/middleware/location.rb +99 -0
- data/gems/server/lib/itsi/server/config/middleware/log_requests.md +13 -11
- data/gems/server/lib/itsi/server/config/middleware/log_requests.rb +1 -3
- data/gems/server/lib/itsi/server/config/middleware/max_body.md +18 -0
- data/gems/server/lib/itsi/server/config/middleware/max_body.rb +21 -0
- data/gems/server/lib/itsi/server/config/middleware/proxy.md +62 -0
- data/gems/server/lib/itsi/server/config/middleware/proxy.rb +41 -0
- data/gems/server/lib/itsi/server/config/middleware/rackup_file.md +54 -0
- data/gems/server/lib/itsi/server/config/middleware/rackup_file.rb +44 -0
- data/gems/server/lib/itsi/server/config/middleware/rate_limit.md +126 -0
- data/gems/server/lib/itsi/server/config/middleware/rate_limit.rb +34 -0
- data/gems/server/lib/itsi/server/config/middleware/rate_limit_store.rb +25 -0
- data/gems/server/lib/itsi/server/config/middleware/redirect.md +55 -0
- data/gems/server/lib/itsi/server/config/middleware/redirect.rb +25 -0
- data/gems/server/lib/itsi/server/config/middleware/request_headers.md +34 -0
- data/gems/server/lib/itsi/server/config/middleware/request_headers.rb +24 -0
- data/gems/server/lib/itsi/server/config/middleware/response_headers.md +33 -0
- data/gems/server/lib/itsi/server/config/middleware/response_headers.rb +25 -0
- data/gems/server/lib/itsi/server/config/middleware/run.md +60 -0
- data/gems/server/lib/itsi/server/config/middleware/run.rb +43 -0
- data/gems/server/lib/itsi/server/config/middleware/static_assets.md +113 -0
- data/gems/server/lib/itsi/server/config/middleware/static_assets.rb +87 -0
- data/gems/server/lib/itsi/server/config/middleware/static_response.md +44 -0
- data/gems/server/lib/itsi/server/config/middleware/static_response.rb +29 -0
- data/gems/server/lib/itsi/server/config/middleware/string_rewrite.md +67 -0
- data/gems/server/lib/itsi/server/config/middleware/token_source.rb +32 -0
- data/gems/server/lib/itsi/server/config/middleware.rb +4 -0
- data/gems/server/lib/itsi/server/config/option.rb +4 -0
- data/gems/server/lib/itsi/server/config/options/_index.md +3 -2
- data/gems/server/lib/itsi/server/config/options/auto_reload_config.md +13 -0
- data/gems/server/lib/itsi/server/config/options/auto_reload_config.rb +41 -0
- data/gems/server/lib/itsi/server/config/options/bind.md +71 -0
- data/gems/server/lib/itsi/server/config/options/bind.rb +26 -0
- data/gems/server/lib/itsi/server/config/options/certificates.md +65 -0
- data/gems/server/lib/itsi/server/config/options/daemonize.md +14 -0
- data/gems/server/lib/itsi/server/config/options/daemonize.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/fiber_scheduler.md +1 -2
- data/gems/server/lib/itsi/server/config/options/fiber_scheduler.rb +6 -3
- data/gems/server/lib/itsi/server/config/options/header_read_timeout.md +17 -0
- data/gems/server/lib/itsi/server/config/options/header_read_timeout.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/hooks/_index.md +11 -0
- data/gems/server/lib/itsi/server/config/options/hooks/after_fork.md +13 -0
- data/gems/server/lib/itsi/server/config/options/hooks/after_fork.rb +28 -0
- data/gems/server/lib/itsi/server/config/options/hooks/after_memory_limit_reached.md +14 -0
- data/gems/server/lib/itsi/server/config/options/hooks/after_memory_limit_reached.rb +28 -0
- data/gems/server/lib/itsi/server/config/options/hooks/after_start.md +12 -0
- data/gems/server/lib/itsi/server/config/options/hooks/after_start.rb +28 -0
- data/gems/server/lib/itsi/server/config/options/hooks/before_fork.md +13 -0
- data/gems/server/lib/itsi/server/config/options/hooks/before_fork.rb +28 -0
- data/gems/server/lib/itsi/server/config/options/hooks/before_restart.md +12 -0
- data/gems/server/lib/itsi/server/config/options/hooks/before_restart.rb +28 -0
- data/gems/server/lib/itsi/server/config/options/hooks/before_shutdown.md +12 -0
- data/gems/server/lib/itsi/server/config/options/hooks/before_shutdown.rb +28 -0
- data/gems/server/lib/itsi/server/config/options/include.md +20 -0
- data/gems/server/lib/itsi/server/config/options/include.rb +36 -0
- data/gems/server/lib/itsi/server/config/options/listen_backlog.md +11 -0
- data/gems/server/lib/itsi/server/config/options/listen_backlog.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/log_format.md +18 -0
- data/gems/server/lib/itsi/server/config/options/log_format.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/log_level.md +34 -0
- data/gems/server/lib/itsi/server/config/options/log_level.rb +20 -0
- data/gems/server/lib/itsi/server/config/options/log_target.md +38 -0
- data/gems/server/lib/itsi/server/config/options/log_target.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/log_target_filters.md +17 -0
- data/gems/server/lib/itsi/server/config/options/log_target_filters.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/multithreaded_reactor.md +27 -0
- data/gems/server/lib/itsi/server/config/options/multithreaded_reactor.rb +24 -0
- data/gems/server/lib/itsi/server/config/options/nodelay.md +16 -0
- data/gems/server/lib/itsi/server/config/options/nodelay.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/oob_gc_responses_threshold.md +19 -0
- data/gems/server/lib/itsi/server/config/options/oob_gc_responses_threshold.rb +18 -0
- data/gems/server/lib/itsi/server/config/options/pin_worker_cores.md +17 -0
- data/gems/server/lib/itsi/server/config/options/pin_worker_cores.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/preload.md +21 -0
- data/gems/server/lib/itsi/server/config/options/preload.rb +18 -0
- data/gems/server/lib/itsi/server/config/options/recv_buffer_size.md +15 -0
- data/gems/server/lib/itsi/server/config/options/recv_buffer_size.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/redirect_http_to_https.md +21 -0
- data/gems/server/lib/itsi/server/config/options/redirect_http_to_https.rb +30 -0
- data/gems/server/lib/itsi/server/config/options/request_timeout.md +23 -0
- data/gems/server/lib/itsi/server/config/options/request_timeout.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/reuse_address.md +16 -0
- data/gems/server/lib/itsi/server/config/options/reuse_address.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/reuse_port.md +16 -0
- data/gems/server/lib/itsi/server/config/options/reuse_port.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/scheduler_threads.md +34 -0
- data/gems/server/lib/itsi/server/config/options/scheduler_threads.rb +17 -0
- data/gems/server/lib/itsi/server/config/options/shutdown_timeout.md +17 -0
- data/gems/server/lib/itsi/server/config/options/shutdown_timeout.rb +19 -0
- data/gems/server/lib/itsi/server/config/options/stream_body.md +32 -0
- data/gems/server/lib/itsi/server/config/options/stream_body.rb +18 -0
- data/gems/server/lib/itsi/server/config/options/threads.md +7 -2
- data/gems/server/lib/itsi/server/config/options/threads.rb +1 -1
- data/gems/server/lib/itsi/server/config/options/watch.md +16 -0
- data/gems/server/lib/itsi/server/config/options/watch.rb +28 -0
- data/gems/server/lib/itsi/server/config/options/worker_memory_limit.md +22 -0
- data/gems/server/lib/itsi/server/config/options/worker_memory_limit.rb +18 -0
- data/gems/server/lib/itsi/server/config/options/workers.md +1 -2
- data/gems/server/lib/itsi/server/config/options/workers.rb +1 -1
- data/gems/server/lib/itsi/server/config/typed_struct.rb +68 -32
- data/gems/server/lib/itsi/server/config.rb +163 -119
- data/gems/server/lib/itsi/server/default_app/default_app.rb +1 -1
- data/gems/server/lib/itsi/server/default_config/Itsi.rb +3 -3
- data/gems/server/lib/itsi/server/grpc/grpc_call.rb +4 -5
- data/gems/server/lib/itsi/server/grpc/grpc_interface.rb +10 -4
- data/gems/server/lib/itsi/server/rack/handler/itsi.rb +2 -3
- data/gems/server/lib/itsi/server/rack_interface.rb +0 -1
- data/gems/server/lib/itsi/server/route_tester.rb +61 -9
- data/gems/server/lib/itsi/server/signal_trap.rb +1 -1
- data/gems/server/lib/itsi/server/typed_handlers/param_parser.rb +14 -18
- data/gems/server/lib/itsi/server/typed_handlers/source_parser.rb +13 -10
- data/gems/server/lib/itsi/server/typed_handlers.rb +12 -4
- data/gems/server/lib/itsi/server/version.rb +1 -1
- data/gems/server/lib/itsi/server.rb +111 -27
- data/gems/server/lib/itsi/standard_headers.rb +80 -80
- data/gems/server/lib/ruby_lsp/itsi/addon.rb +20 -18
- data/gems/server/test/helpers/test_helper.rb +90 -29
- data/gems/server/test/middleware/allow_list.rb +128 -0
- data/gems/server/test/middleware/auth_api_key.rb +141 -0
- data/gems/server/test/middleware/auth_basic.rb +91 -0
- data/gems/server/test/middleware/auth_jwt.rb +214 -0
- data/gems/server/test/middleware/cache_control.rb +82 -0
- data/gems/server/test/middleware/cidr_to_regex.rb +46 -0
- data/gems/server/test/middleware/compression.rb +89 -0
- data/gems/server/test/middleware/cors.rb +113 -0
- data/gems/server/test/middleware/csp.rb +62 -0
- data/gems/server/test/middleware/deny_list.rb +131 -0
- data/gems/server/test/middleware/endpoint.rb +300 -0
- data/gems/server/test/middleware/etag.rb +75 -0
- data/gems/server/test/middleware/grpc/grpc.rb +158 -0
- data/gems/server/test/middleware/grpc/test_service.proto +32 -0
- data/gems/server/test/middleware/grpc/test_service_impl.rb +28 -0
- data/gems/server/test/middleware/grpc/test_service_pb.rb +18 -0
- data/gems/server/test/middleware/grpc/test_service_services_pb.rb +30 -0
- data/gems/server/test/middleware/header_interpolation.rb +35 -0
- data/gems/server/test/middleware/intrusion_protection.rb +259 -0
- data/gems/server/test/middleware/location.rb +220 -0
- data/gems/server/test/middleware/max_body.rb +20 -0
- data/gems/server/test/middleware/proxy.rb +415 -0
- data/gems/server/test/middleware/rate_limit.rb +211 -0
- data/gems/server/test/middleware/redirect.rb +85 -0
- data/gems/server/test/middleware/request_headers.rb +50 -0
- data/gems/server/test/middleware/response_headers.rb +50 -0
- data/gems/server/test/middleware/static_assets.rb +374 -0
- data/gems/server/test/middleware/static_response.rb +56 -0
- data/gems/server/test/middleware/string_rewrite.rb +112 -0
- data/gems/server/test/middleware/test_log_requests.rb +54 -2
- data/gems/server/test/options/bind.rb +47 -0
- data/gems/server/test/options/header_read_timeout.rb +23 -0
- data/gems/server/test/options/test_request_timeout.rb +16 -0
- data/gems/server/test/options/test_workers.rb +11 -6
- data/gems/server/test/{test_itsi_server.rb → rack/test_rack_server.rb} +2 -2
- data/lib/itsi/version.rb +1 -1
- data/tasks.txt +15 -72
- metadata +209 -10
- data/examples/static_assets_example.rb +0 -83
- data/gems/server/lib/itsi/server/default_config/Itsi-rackup.rb +0 -119
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
require "time"
|
3
5
|
|
4
6
|
module Itsi
|
5
7
|
class Server
|
@@ -10,18 +12,19 @@ module Itsi
|
|
10
12
|
|
11
13
|
def self.new(defaults = nil, &defaults_blk)
|
12
14
|
defaults = TypedStruct.module_eval(&defaults_blk) if defaults_blk
|
13
|
-
unless defaults.is_a?(Hash)
|
14
|
-
|
15
|
-
end
|
15
|
+
return defaults unless defaults.is_a?(Hash)
|
16
|
+
|
16
17
|
defaults.transform_values! { _1.is_a?(Validation) ? _1.default(nil) : _1 }
|
17
18
|
Struct.new(*defaults.keys, keyword_init: true) do
|
18
19
|
define_method(:initialize) do |*input, validate: true, **raw_input|
|
19
|
-
|
20
|
-
|
20
|
+
raise "─ Invalid input to #{self}: #{input.last}" if input.last && !input.last.is_a?(Hash)
|
21
|
+
|
22
|
+
raw_input.transform_keys! { |k| k.to_s.downcase.to_sym }
|
23
|
+
raw_input.merge!(input.pop.transform_keys! { |k| k.to_s.downcase.to_sym }) if input.last.is_a?(Hash)
|
21
24
|
|
22
25
|
excess_keys = raw_input.keys - defaults.keys
|
23
26
|
|
24
|
-
raise "Unsupported keys #{excess_keys}" if excess_keys.any?
|
27
|
+
raise "─ Unsupported keys #{excess_keys}" if excess_keys.any?
|
25
28
|
|
26
29
|
initial_values = defaults.each_with_object({}) do |(k, default_config), inputs|
|
27
30
|
value = raw_input.key?(k) ? raw_input[k] : default_config[VALUE].dup
|
@@ -30,7 +33,7 @@ module Itsi
|
|
30
33
|
begin
|
31
34
|
inputs[k] = default_config[VALIDATE].validate!(value)
|
32
35
|
rescue StandardError => e
|
33
|
-
raise ArgumentError, e.message
|
36
|
+
raise ArgumentError, "─ #{k}: #{e.message}"
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
@@ -97,11 +100,9 @@ module Itsi
|
|
97
100
|
"#{@name}"
|
98
101
|
end
|
99
102
|
|
100
|
-
def
|
103
|
+
def &(other)
|
101
104
|
tail = self
|
102
|
-
while tail.next
|
103
|
-
tail = tail.next
|
104
|
-
end
|
105
|
+
tail = tail.next while tail.next
|
105
106
|
tail.next = other
|
106
107
|
self
|
107
108
|
end
|
@@ -115,40 +116,51 @@ module Itsi
|
|
115
116
|
@validations.each do |validation|
|
116
117
|
case validation
|
117
118
|
when Proc
|
118
|
-
|
119
|
-
raise ArgumentError,
|
120
|
-
"─ `#{@name}` validation failed. Invalid value: #{value.inspect}"
|
121
|
-
end
|
119
|
+
validation.call(value)
|
122
120
|
when Array
|
123
121
|
unless !value || validation.include?(value)
|
124
122
|
raise ArgumentError,
|
125
|
-
"─
|
123
|
+
"─ `#{@name}` validation failed. Invalid #{validation} value: #{value.inspect}"
|
126
124
|
end
|
127
125
|
when Range
|
128
126
|
unless !value || validation.include?(value)
|
129
127
|
raise ArgumentError,
|
130
|
-
"─
|
128
|
+
"─ `#{@name}` validation failed. Invalid #{validation} value: #{value.inspect}"
|
131
129
|
end
|
132
130
|
when Regexp
|
133
131
|
unless !value || validation.match?(value)
|
134
132
|
raise ArgumentError,
|
135
|
-
"─
|
133
|
+
"─ `#{@name}` validation failed. Invalid #{validation} value: #{value.inspect}"
|
136
134
|
end
|
135
|
+
when Validation
|
136
|
+
validation.validate!(value)
|
137
137
|
when Class
|
138
|
-
|
139
138
|
if value && !value.is_a?(validation)
|
140
139
|
begin
|
141
140
|
value = \
|
142
141
|
if validation.eql?(Time) then Time.parse(value.to_s)
|
143
142
|
elsif validation.eql?(::Date) then Date.parse(value.to_s)
|
144
143
|
elsif validation.eql?(Float) then Float(value)
|
145
|
-
elsif validation.eql?(
|
146
|
-
elsif validation.eql?(
|
147
|
-
|
144
|
+
elsif validation.eql?(Integer) then Integer(value)
|
145
|
+
elsif validation.eql?(Proc)
|
146
|
+
raise ArgumentError, "Invalid #{validation} value: #{value.inspect}" unless value.is_a?(Proc)
|
147
|
+
elsif validation.eql?(String) || validation.eql?(Symbol)
|
148
|
+
unless value.is_a?(String) || value.is_a?(Symbol)
|
149
|
+
raise ArgumentError,
|
150
|
+
"Invalid #{validation} value: #{value.inspect}"
|
151
|
+
end
|
152
|
+
|
153
|
+
if validation.eql?(String)
|
154
|
+
value.to_s
|
155
|
+
elsif validation.eql?(Symbol)
|
156
|
+
value.to_s.to_sym
|
157
|
+
end
|
158
|
+
else
|
159
|
+
validation.new(value)
|
148
160
|
end
|
149
161
|
rescue StandardError => e
|
150
162
|
raise ArgumentError,
|
151
|
-
"─ `#{@name}` Validation Failed. Invalid #{validation.to_s.split("::").last} value: #{value.inspect}. Failure reason: \n
|
163
|
+
"─ `#{@name}` Validation Failed. Invalid #{validation.to_s.split("::").last} value: #{value.inspect}. Failure reason: \n └─ #{e.message}"
|
152
164
|
end
|
153
165
|
end
|
154
166
|
end
|
@@ -164,23 +176,47 @@ module Itsi
|
|
164
176
|
{
|
165
177
|
Bool: Validation.new(:Bool, [[true, false]]),
|
166
178
|
Required: Validation.new(:Required, ->(value) { !value.nil? }),
|
167
|
-
Or:
|
168
|
-
Validation.new(:Or,
|
169
|
-
|
179
|
+
Or: lambda { |*validations|
|
180
|
+
Validation.new(:Or, lambda { |v|
|
181
|
+
return true if v.nil?
|
182
|
+
|
183
|
+
errs = []
|
184
|
+
validations.each do |validation|
|
185
|
+
v = validation.validate!(v)
|
186
|
+
return v
|
187
|
+
rescue StandardError => e
|
188
|
+
errs << e.message
|
189
|
+
end
|
190
|
+
raise StandardError.new("─ Validation failed (None match:) \n └#{errs.join("\n └")}")
|
170
191
|
})
|
171
192
|
},
|
172
|
-
Range:
|
193
|
+
Range: lambda { |input_range|
|
173
194
|
Validation.new(:Range, [input_range])
|
174
195
|
},
|
175
196
|
Length: lambda { |input_length|
|
176
197
|
Validation.new(:Length, ->(value) { input_length === value.length })
|
177
198
|
},
|
199
|
+
Hash: lambda { |key_type, value_type|
|
200
|
+
Validation.new(:Hash, lambda { |hash|
|
201
|
+
return true if hash.nil?
|
202
|
+
raise StandardError.new("Expected hash got #{hash.class}") unless hash.is_a?(Hash)
|
203
|
+
|
204
|
+
hash.map do |k, v|
|
205
|
+
[
|
206
|
+
key_type.validate!(k),
|
207
|
+
value_type.validate!(v)
|
208
|
+
]
|
209
|
+
end.to_h
|
210
|
+
})
|
211
|
+
},
|
178
212
|
Type: ->(input_type) { Validation.new(:Type, input_type) },
|
179
|
-
Enum: ->(allowed_values) { Validation.new(:Enum, [allowed_values.map{|v| v.
|
213
|
+
Enum: ->(allowed_values) { Validation.new(:Enum, [allowed_values.map { |v| v.is_a?(Symbol) ? v.to_s : v }]) },
|
180
214
|
Array: lambda { |*value_validations|
|
181
215
|
Validation.new(:Array, [::Array, lambda { |value|
|
182
216
|
return true unless value
|
183
217
|
|
218
|
+
raise StandardError.new("Expected Array got #{value.class}") unless value.is_a?(Array)
|
219
|
+
|
184
220
|
value&.map! do |v|
|
185
221
|
value_validations.all? { v = _1.validate!(v) }
|
186
222
|
v
|
@@ -193,8 +229,8 @@ module Itsi
|
|
193
229
|
define_singleton_method(name.to_s.downcase, &factory)
|
194
230
|
else
|
195
231
|
const_set(name, factory)
|
196
|
-
define_singleton_method(name, -> { factory })
|
197
|
-
define_singleton_method(name.to_s.downcase, -> { factory })
|
232
|
+
define_singleton_method(name, -> { factory.dup })
|
233
|
+
define_singleton_method(name.to_s.downcase, -> { factory.dup })
|
198
234
|
end
|
199
235
|
end
|
200
236
|
end
|
@@ -41,16 +41,18 @@ module Itsi
|
|
41
41
|
elsif args[:static]
|
42
42
|
DSL.evaluate do
|
43
43
|
location "/" do
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
log_requests before: { level: "INFO", format: "[{request_id}] {method} {path_and_query} - {addr} " },
|
44
|
+
rate_limit key: "address", store_config: "in_memory", requests: 2, seconds: 5
|
45
|
+
etag type: "strong", algorithm: "md5", min_body_size: 1024 * 1024
|
46
|
+
compress min_size: 1024 * 1024, level: "fastest", algorithms: %w[zstd gzip br deflate],
|
47
|
+
mime_types: %w[all], compress_streams: true
|
48
|
+
log_requests before: { level: "INFO", format: "[{request_id}] {method} {path_and_query} - {addr} " },
|
49
|
+
after: { level: "INFO",
|
50
|
+
format: "[{request_id}] └─ {status} in {response_time}" }
|
49
51
|
static_assets \
|
50
52
|
relative_path: true,
|
51
53
|
allowed_extensions: [],
|
52
|
-
root_dir:
|
53
|
-
not_found_behavior: {error:
|
54
|
+
root_dir: ".",
|
55
|
+
not_found_behavior: { error: "not_found" },
|
54
56
|
auto_index: true,
|
55
57
|
try_html_extension: true,
|
56
58
|
max_file_size_in_memory: 1024 * 1024, # 1MB
|
@@ -58,7 +60,7 @@ module Itsi
|
|
58
60
|
file_check_interval: 1,
|
59
61
|
serve_hidden_files: false,
|
60
62
|
headers: {
|
61
|
-
|
63
|
+
"X-Content-Type-Options" => "nosniff"
|
62
64
|
}
|
63
65
|
end
|
64
66
|
end
|
@@ -70,7 +72,7 @@ module Itsi
|
|
70
72
|
rackup_file args.fetch(:rackup_file, "./config.ru")
|
71
73
|
end
|
72
74
|
else
|
73
|
-
DSL.evaluate{}
|
75
|
+
DSL.evaluate {}
|
74
76
|
end
|
75
77
|
|
76
78
|
itsifile_config.transform_keys!(&:to_sym)
|
@@ -82,78 +84,84 @@ module Itsi
|
|
82
84
|
case preload
|
83
85
|
# If we preload everything, then we'll load middleware and default rack app ahead of time
|
84
86
|
when true
|
85
|
-
|
86
|
-
|
87
|
+
begin
|
88
|
+
Itsi.log_debug("Preloading middleware and default rack app")
|
89
|
+
preloaded_middleware = middleware_loader.call
|
90
|
+
middleware_loader = -> { preloaded_middleware }
|
91
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
92
|
+
errors << [e, e.backtrace[0]]
|
93
|
+
end
|
87
94
|
# If we're just preloading a specific gem group, we'll do that here too
|
88
95
|
when Symbol
|
96
|
+
Itsi.log_debug("Preloading gem group #{preload}")
|
89
97
|
Bundler.require(preload)
|
90
98
|
end
|
91
99
|
|
92
|
-
[
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
preload: !!preload,
|
100
|
-
request_timeout: itsifile_config.fetch(:request_timeout, nil),
|
101
|
-
header_read_timeout: args.fetch(:header_read_timeout) { itsifile_config.fetch(:header_read_timeout, nil) },
|
102
|
-
notify_watchers: itsifile_config.fetch(:notify_watchers, nil),
|
103
|
-
threads: args.fetch(:threads) { itsifile_config.fetch(:threads, 1) },
|
104
|
-
scheduler_threads: args.fetch(:scheduler_threads) { itsifile_config.fetch(:scheduler_threads, nil) },
|
105
|
-
streamable_body: args.fetch(:streamable_body) { itsifile_config.fetch(:streamable_body, false) },
|
106
|
-
multithreaded_reactor: args.fetch(:multithreaded_reactor) do
|
107
|
-
itsifile_config.fetch(:multithreaded_reactor, nil)
|
108
|
-
end,
|
109
|
-
pin_worker_cores: args.fetch(:pin_worker_cores) { itsifile_config.fetch(:pin_worker_cores, true) },
|
110
|
-
scheduler_class: args.fetch(:scheduler_class) { itsifile_config.fetch(:scheduler_class, nil) },
|
111
|
-
oob_gc_responses_threshold: args.fetch(:oob_gc_responses_threshold) do
|
112
|
-
itsifile_config.fetch(:oob_gc_responses_threshold, nil)
|
113
|
-
end,
|
114
|
-
log_level: args.fetch(:log_level) { itsifile_config.fetch(:log_level, nil) },
|
115
|
-
log_format: args.fetch(:log_format) { itsifile_config.fetch(:log_format, nil) },
|
116
|
-
log_target: args.fetch(:log_target) { itsifile_config.fetch(:log_target, nil) },
|
117
|
-
log_target_filters: args.fetch(:log_target_filters) { itsifile_config.fetch(:log_target_filters, nil) },
|
118
|
-
binds: args.fetch(:binds) { itsifile_config.fetch(:binds, ["http://0.0.0.0:3000"]) },
|
119
|
-
middleware_loader: middleware_loader,
|
120
|
-
listeners: args.fetch(:listeners) { nil },
|
121
|
-
reuse_address: itsifile_config.fetch(:reuse_address, true),
|
122
|
-
reuse_port: itsifile_config.fetch(:reuse_port, true),
|
123
|
-
listen_backlog: itsifile_config.fetch(:listen_backlog, 1024 ),
|
124
|
-
nodelay: itsifile_config.fetch(:nodelay, true),
|
125
|
-
recv_buffer_size: itsifile_config.fetch(:recv_buffer_size, 262_144)
|
126
|
-
}.transform_keys(&:to_s),
|
100
|
+
if itsifile_config[:daemonize] && !@daemonized
|
101
|
+
@daemonized = true
|
102
|
+
Itsi.log_info("Itsi is running in the background. Writing pid to #{Itsi::Server::Config.pid_file_path}")
|
103
|
+
Itsi.log_info("To stop Itsi, run 'itsi stop' from this directory.")
|
104
|
+
Process.daemon(true, false)
|
105
|
+
Server.write_pid
|
106
|
+
end
|
127
107
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
108
|
+
srv_config = {
|
109
|
+
workers: args.fetch(:workers) { itsifile_config.fetch(:workers, 1) },
|
110
|
+
worker_memory_limit: args.fetch(:worker_memory_limit) { itsifile_config.fetch(:worker_memory_limit, nil) },
|
111
|
+
silence: args.fetch(:silence) { itsifile_config.fetch(:silence, false) },
|
112
|
+
shutdown_timeout: args.fetch(:shutdown_timeout) { itsifile_config.fetch(:shutdown_timeout, 5) },
|
113
|
+
hooks: if args[:hooks] && itsifile_config[:hooks]
|
114
|
+
args[:hooks].merge(itsifile_config[:hooks])
|
115
|
+
else
|
116
|
+
itsifile_config.fetch(
|
117
|
+
:hooks, args[:hooks]
|
118
|
+
)
|
119
|
+
end,
|
120
|
+
preload: !!preload,
|
121
|
+
request_timeout: itsifile_config.fetch(:request_timeout, nil),
|
122
|
+
header_read_timeout: args.fetch(:header_read_timeout) { itsifile_config.fetch(:header_read_timeout, nil) },
|
123
|
+
notify_watchers: itsifile_config.fetch(:notify_watchers, nil),
|
124
|
+
threads: args.fetch(:threads) { itsifile_config.fetch(:threads, 1) },
|
125
|
+
scheduler_threads: args.fetch(:scheduler_threads) { itsifile_config.fetch(:scheduler_threads, nil) },
|
126
|
+
streamable_body: args.fetch(:streamable_body) { itsifile_config.fetch(:streamable_body, false) },
|
127
|
+
multithreaded_reactor: args.fetch(:multithreaded_reactor) do
|
128
|
+
itsifile_config.fetch(:multithreaded_reactor, nil)
|
129
|
+
end,
|
130
|
+
pin_worker_cores: args.fetch(:pin_worker_cores) { itsifile_config.fetch(:pin_worker_cores, true) },
|
131
|
+
scheduler_class: args.fetch(:scheduler_class) { itsifile_config.fetch(:scheduler_class, nil) },
|
132
|
+
oob_gc_responses_threshold: args.fetch(:oob_gc_responses_threshold) do
|
133
|
+
itsifile_config.fetch(:oob_gc_responses_threshold, nil)
|
134
|
+
end,
|
135
|
+
log_level: args.fetch(:log_level) { itsifile_config.fetch(:log_level, nil) },
|
136
|
+
log_format: args.fetch(:log_format) { itsifile_config.fetch(:log_format, nil) },
|
137
|
+
log_target: args.fetch(:log_target) { itsifile_config.fetch(:log_target, nil) },
|
138
|
+
log_target_filters: args.fetch(:log_target_filters) { itsifile_config.fetch(:log_target_filters, nil) },
|
139
|
+
binds: args.fetch(:binds) { itsifile_config.fetch(:binds, ["http://0.0.0.0:3000"]) },
|
140
|
+
middleware_loader: middleware_loader,
|
141
|
+
listeners: args.fetch(:listeners) { nil },
|
142
|
+
reuse_address: itsifile_config.fetch(:reuse_address, true),
|
143
|
+
reuse_port: itsifile_config.fetch(:reuse_port, true),
|
144
|
+
listen_backlog: itsifile_config.fetch(:listen_backlog, 1024),
|
145
|
+
nodelay: itsifile_config.fetch(:nodelay, true),
|
146
|
+
recv_buffer_size: itsifile_config.fetch(:recv_buffer_size, 262_144)
|
147
|
+
}.transform_keys(&:to_s)
|
148
|
+
|
149
|
+
[srv_config, errors_to_error_lines(errors)]
|
150
|
+
rescue StandardError
|
151
|
+
Itsi.log_error e.message
|
152
|
+
puts e.backtrace
|
153
153
|
end
|
154
154
|
|
155
155
|
def self.test!(cli_params)
|
156
|
-
|
156
|
+
config, errors = build_config(cli_params, Itsi::Server::Config.config_file_path(cli_params[:config_file]))
|
157
|
+
unless errors.any?
|
158
|
+
begin
|
159
|
+
config["middleware_loader"][]
|
160
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
161
|
+
errors = [e]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
157
165
|
if errors.any?
|
158
166
|
Itsi.log_error("Config file is invalid")
|
159
167
|
puts errors
|
@@ -162,6 +170,42 @@ module Itsi
|
|
162
170
|
end
|
163
171
|
end
|
164
172
|
|
173
|
+
def self.errors_to_error_lines(errors)
|
174
|
+
return unless errors
|
175
|
+
|
176
|
+
errors.flat_map do |(error, message)|
|
177
|
+
location = message[/(.*?):in/, 1]
|
178
|
+
file, lineno = location.split(":")
|
179
|
+
lineno = lineno.to_i
|
180
|
+
err_message = error.is_a?(NoMethodError) ? error.detailed_message : error.message
|
181
|
+
file_lines = IO.readlines(file)
|
182
|
+
info_lines = \
|
183
|
+
if error.is_a?(SyntaxError)
|
184
|
+
[]
|
185
|
+
else
|
186
|
+
|
187
|
+
([lineno - 2, 0].max...[file_lines.length, lineno.succ.succ].min).map do |currline|
|
188
|
+
if currline == lineno - 1
|
189
|
+
line = file_lines[currline][0...-1]
|
190
|
+
padding = line[/^\s+/]&.length || 0
|
191
|
+
|
192
|
+
[
|
193
|
+
" \e[31m#{currline.succ.to_s.rjust(3)} | #{line}\e[0m",
|
194
|
+
" | #{" " * padding}\e[33m^^^\e[0m "
|
195
|
+
]
|
196
|
+
else
|
197
|
+
" #{currline.succ.to_s.rjust(3)} | #{file_lines[currline][0...-1]}"
|
198
|
+
end
|
199
|
+
end.flatten
|
200
|
+
end
|
201
|
+
[
|
202
|
+
err_message,
|
203
|
+
" --> #{File.expand_path(file)}:#{lineno}",
|
204
|
+
*info_lines
|
205
|
+
]
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
165
209
|
# Reloads the entire process
|
166
210
|
# using exec, passing in any active file descriptors
|
167
211
|
# and previous invocation arguments
|
@@ -181,7 +225,7 @@ module Itsi
|
|
181
225
|
elsif File.exist?("config/#{ITSI_DEFAULT_CONFIG_FILE}")
|
182
226
|
"config/#{ITSI_DEFAULT_CONFIG_FILE}"
|
183
227
|
end
|
184
|
-
# Options
|
228
|
+
# Options pass through unless we've specified a config file
|
185
229
|
return unless File.exist?(config_file_path.to_s)
|
186
230
|
|
187
231
|
config_file_path
|
@@ -204,56 +248,56 @@ module Itsi
|
|
204
248
|
|
205
249
|
default_config = IO.read("#{__dir__}/default_config/Itsi.rb")
|
206
250
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
251
|
+
default_config << \
|
252
|
+
if File.exist?("./config.ru")
|
253
|
+
<<~RUBY
|
254
|
+
# You can mount several Ruby apps as either
|
255
|
+
# 1. rackup files
|
256
|
+
# 2. inline rack apps
|
257
|
+
# 3. inline Ruby endpoints
|
258
|
+
#
|
259
|
+
# 1. rackup_file
|
260
|
+
rackup_file "./config.ru"
|
261
|
+
#
|
262
|
+
# 2. inline rack app
|
263
|
+
# require 'rack'
|
264
|
+
# run(Rack::Builder.app do
|
265
|
+
# use Rack::CommonLogger
|
266
|
+
# run ->(env) { [200, { 'content-type' => 'text/plain' }, ['OK']] }
|
267
|
+
# end)
|
268
|
+
#
|
269
|
+
# 3. Endpoints
|
270
|
+
# endpoint "/" do |req|
|
271
|
+
# req.ok "Hello from Itsi"
|
272
|
+
# end
|
273
|
+
RUBY
|
274
|
+
else
|
275
|
+
<<~RUBY
|
276
|
+
# You can mount several Ruby apps as either
|
277
|
+
# 1. rackup files
|
278
|
+
# 2. inline rack apps
|
279
|
+
# 3. inline Ruby endpoints
|
280
|
+
#
|
281
|
+
# 1. rackup_file
|
282
|
+
# Use `rackup_file` to specify the Rack app file name.
|
283
|
+
#
|
284
|
+
# 2. inline rack app
|
285
|
+
# require 'rack'
|
286
|
+
# run(Rack::Builder.app do
|
287
|
+
# use Rack::CommonLogger
|
288
|
+
# run ->(env) { [200, { 'content-type' => 'text/plain' }, ['OK']] }
|
289
|
+
# end)
|
290
|
+
#
|
291
|
+
# 3. Endpoint
|
292
|
+
endpoint "/" do |req|
|
293
|
+
req.ok "Hello from Itsi"
|
294
|
+
end
|
295
|
+
RUBY
|
296
|
+
end
|
252
297
|
|
253
298
|
File.open(ITSI_DEFAULT_CONFIG_FILE, "w") do |file|
|
254
299
|
file.write(default_config)
|
255
300
|
end
|
256
|
-
|
257
301
|
end
|
258
302
|
end
|
259
303
|
end
|
@@ -73,7 +73,7 @@ worker_memory_limit 1024 * 1024 * 1024
|
|
73
73
|
|
74
74
|
# You can provide an optional block of code to run, when a worker hits its memory threshold (Use this to send yourself an alert,
|
75
75
|
# write metrics to disk etc. etc.)
|
76
|
-
|
76
|
+
after_memory_limit_reached do |pid|
|
77
77
|
puts "Worker #{pid} has reached its memory threshold and will restart"
|
78
78
|
end
|
79
79
|
|
@@ -102,6 +102,6 @@ oob_gc_responses_threshold 512
|
|
102
102
|
log_level :info
|
103
103
|
|
104
104
|
# Log Format
|
105
|
-
# Set this to be either :
|
105
|
+
# Set this to be either :plain or :json. If you leave it blank Itsi will try
|
106
106
|
# and auto-detect the format based on the TTY environment.
|
107
|
-
log_format :
|
107
|
+
log_format :plain
|
@@ -7,11 +7,11 @@ module Itsi
|
|
7
7
|
attr_accessor :rpc_desc
|
8
8
|
|
9
9
|
def input_stream?
|
10
|
-
@input_stream ||= @rpc_desc&.input
|
10
|
+
@input_stream ||= @rpc_desc&.input.is_a?(GRPC::RpcDesc::Stream) || false
|
11
11
|
end
|
12
12
|
|
13
13
|
def output_stream?
|
14
|
-
@output_stream ||= @rpc_desc&.output
|
14
|
+
@output_stream ||= @rpc_desc&.output.is_a?(GRPC::RpcDesc::Stream) || false
|
15
15
|
end
|
16
16
|
|
17
17
|
def input_type
|
@@ -64,7 +64,7 @@ module Itsi
|
|
64
64
|
return nil if first_char.nil?
|
65
65
|
|
66
66
|
# Step 2: Process objects until we hit the end of the JSON stream or array.
|
67
|
-
loop do
|
67
|
+
loop do # rubocop:disable Lint/UnreachableLoop,Metrics/BlockLength
|
68
68
|
# Skip any whitespace or commas preceding an object.
|
69
69
|
char = nil
|
70
70
|
loop do
|
@@ -74,7 +74,6 @@ module Itsi
|
|
74
74
|
|
75
75
|
break
|
76
76
|
end
|
77
|
-
|
78
77
|
# The next non-whitespace, non-comma character should be the start of an object.
|
79
78
|
return nil unless char == "{"
|
80
79
|
|
@@ -120,7 +119,7 @@ module Itsi
|
|
120
119
|
def remote_read
|
121
120
|
if content_type == "application/json"
|
122
121
|
if input_stream?
|
123
|
-
if next_item = parse_from_json_stream(reader)
|
122
|
+
if (next_item = parse_from_json_stream(reader))
|
124
123
|
input_type.decode_json(next_item)
|
125
124
|
end
|
126
125
|
else
|
@@ -23,13 +23,13 @@ module Itsi
|
|
23
23
|
def initialize(service)
|
24
24
|
@service = service
|
25
25
|
@service_class = service.class
|
26
|
-
@service_class.rpc_descs.transform_keys
|
26
|
+
@rpc_descs = @service_class.rpc_descs.transform_keys do |k|
|
27
27
|
k.to_s.gsub(/([a-z])([A-Z])/, "\\1_\\2").downcase.to_sym
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
def handle_request(active_call)
|
32
|
-
unless (active_call.rpc_desc =
|
32
|
+
unless (active_call.rpc_desc = @rpc_descs[active_call.method_name])
|
33
33
|
active_call.stream.write("\n")
|
34
34
|
active_call.send_status(13, "Method not found")
|
35
35
|
active_call.close
|
@@ -85,15 +85,21 @@ module Itsi
|
|
85
85
|
|
86
86
|
def handle_server_streaming(active_call)
|
87
87
|
message = active_call.remote_read
|
88
|
-
service.send(active_call.method_name, message, active_call) do |response|
|
88
|
+
result = service.send(active_call.method_name, message, active_call) do |response|
|
89
89
|
active_call.remote_send(response)
|
90
90
|
end
|
91
|
+
return unless result.is_a?(Enumerator)
|
92
|
+
|
93
|
+
result.each { |response| active_call.remote_send(response) }
|
91
94
|
end
|
92
95
|
|
93
96
|
def handle_bidi_streaming(active_call)
|
94
|
-
service.send(active_call.method_name, active_call.each_remote_read, active_call) do |response|
|
97
|
+
result = service.send(active_call.method_name, active_call.each_remote_read, active_call) do |response|
|
95
98
|
active_call.remote_send(response)
|
96
99
|
end
|
100
|
+
return unless result.is_a?(Enumerator)
|
101
|
+
|
102
|
+
result.each { |response| active_call.remote_send(response) }
|
97
103
|
end
|
98
104
|
end
|
99
105
|
end
|
@@ -6,12 +6,11 @@ module Rack
|
|
6
6
|
def self.run(app, options = {})
|
7
7
|
host = options.fetch(:host, "127.0.0.1")
|
8
8
|
port = options.fetch(:Port, 3001)
|
9
|
-
Itsi::Server.start(
|
9
|
+
::Itsi::Server.start(
|
10
10
|
{
|
11
11
|
app: app,
|
12
12
|
binds: ["http://#{host}:#{port}"]
|
13
|
-
}
|
14
|
-
Itsi::Server::Config.config_file_path
|
13
|
+
}
|
15
14
|
)
|
16
15
|
end
|
17
16
|
end
|