itsi 0.1.20 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -8
- data/Cargo.lock +2 -2
- data/LICENSE.txt +698 -0
- data/README.md +15 -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 +122 -63
- 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 +1 -2
- 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/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 +68 -8
- data/docs/content/getting_started/logging.md +16 -9
- data/docs/content/getting_started/running_itsi_in_production.md +5 -3
- data/docs/content/getting_started/signals.md +38 -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 +1 -1
- data/fairytale.txt +3 -4
- data/gems/scheduler/Cargo.lock +1 -1
- data/gems/scheduler/README.md +4 -5
- data/gems/scheduler/Rakefile +0 -4
- 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 +1 -1
- data/gems/server/Rakefile +0 -4
- data/gems/server/exe/itsi +13 -2
- data/gems/server/lib/itsi/http_request/response_status_shortcodes.rb +2 -0
- data/gems/server/lib/itsi/http_request.rb +40 -9
- data/gems/server/lib/itsi/http_response.rb +2 -1
- data/gems/server/lib/itsi/passfile.rb +0 -1
- data/gems/server/lib/itsi/server/config/config_helpers.rb +20 -8
- data/gems/server/lib/itsi/server/config/dsl.rb +20 -435
- data/gems/server/lib/itsi/server/config/known_paths.rb +4 -1
- 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 +61 -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 +73 -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 +5 -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 +59 -20
- data/gems/server/lib/itsi/server/config.rb +77 -48
- data/gems/server/lib/itsi/server/default_config/Itsi.rb +3 -3
- data/gems/server/lib/itsi/server/grpc/grpc_call.rb +1 -1
- data/gems/server/lib/itsi/server/grpc/grpc_interface.rb +11 -4
- data/gems/server/lib/itsi/server/rack/handler/itsi.rb +3 -3
- data/gems/server/lib/itsi/server/route_tester.rb +58 -8
- 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 +5 -4
- 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 +98 -14
- data/gems/server/lib/ruby_lsp/itsi/addon.rb +20 -18
- data/gems/server/test/helpers/test_helper.rb +89 -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/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 +2 -4
- data/gems/server/test/{test_itsi_server.rb → rack/test_rack_server.rb} +2 -2
- data/grpc_test/Itsi.rb +11 -0
- data/grpc_test/echo.proto +14 -0
- data/grpc_test/echo_pb.rb +16 -0
- data/grpc_test/echo_service_impl.rb +8 -0
- data/grpc_test/echo_services_pb.rb +22 -0
- data/lib/itsi/version.rb +1 -1
- data/tasks.txt +15 -72
- metadata +210 -7
- data/gems/server/lib/itsi/server/default_config/Itsi-rackup.rb +0 -119
@@ -41,10 +41,9 @@ module Itsi
|
|
41
41
|
elsif args[:static]
|
42
42
|
DSL.evaluate do
|
43
43
|
location "/" do
|
44
|
-
allow_list allowed_patterns: ['127.0.0.1']
|
45
44
|
rate_limit key: 'address', store_config: 'in_memory', requests: 2, seconds: 5
|
46
45
|
etag type: 'strong', algorithm: 'md5', min_body_size: 1024 * 1024
|
47
|
-
compress min_size: 1024 * 1024, level: 'fastest', algorithms: %w[zstd gzip
|
46
|
+
compress min_size: 1024 * 1024, level: 'fastest', algorithms: %w[zstd gzip br deflate], mime_types: %w[all], compress_streams: true
|
48
47
|
log_requests before: { level: "INFO", format: "[{request_id}] {method} {path_and_query} - {addr} " }, after: { level: "INFO", format: "[{request_id}] └─ {status} in {response_time}" }
|
49
48
|
static_assets \
|
50
49
|
relative_path: true,
|
@@ -82,50 +81,63 @@ module Itsi
|
|
82
81
|
case preload
|
83
82
|
# If we preload everything, then we'll load middleware and default rack app ahead of time
|
84
83
|
when true
|
85
|
-
|
86
|
-
|
84
|
+
begin
|
85
|
+
Itsi.log_debug("Preloading middleware and default rack app")
|
86
|
+
preloaded_middleware = middleware_loader.call
|
87
|
+
middleware_loader = -> { preloaded_middleware }
|
88
|
+
rescue StandardError => e
|
89
|
+
errors << [e, e.backtrace[0]]
|
90
|
+
end
|
87
91
|
# If we're just preloading a specific gem group, we'll do that here too
|
88
92
|
when Symbol
|
93
|
+
Itsi.log_debug("Preloading gem group #{preload}")
|
89
94
|
Bundler.require(preload)
|
90
95
|
end
|
91
96
|
|
92
|
-
[
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
97
|
+
if itsifile_config[:daemonize] && !@daemonized
|
98
|
+
@daemonized = true
|
99
|
+
Itsi.log_info("Itsi is running in the background. Writing pid to #{Itsi::Server::Config.pid_file_path}")
|
100
|
+
Itsi.log_info("To stop Itsi, run 'itsi stop' from this directory.")
|
101
|
+
Process.daemon(true, false)
|
102
|
+
Server.write_pid
|
103
|
+
end
|
104
|
+
|
105
|
+
srv_config = {
|
106
|
+
workers: args.fetch(:workers) { itsifile_config.fetch(:workers, 1) },
|
107
|
+
worker_memory_limit: args.fetch(:worker_memory_limit) { itsifile_config.fetch(:worker_memory_limit, nil) },
|
108
|
+
silence: args.fetch(:silence) { itsifile_config.fetch(:silence, false) },
|
109
|
+
shutdown_timeout: args.fetch(:shutdown_timeout) { itsifile_config.fetch(:shutdown_timeout, 5) },
|
110
|
+
hooks: args[:hooks] && itsifile_config[:hooks] ? args[:hooks].merge(itsifile_config[:hooks]) : itsifile_config.fetch(:hooks, args[:hooks]),
|
111
|
+
preload: !!preload,
|
112
|
+
request_timeout: itsifile_config.fetch(:request_timeout, nil),
|
113
|
+
header_read_timeout: args.fetch(:header_read_timeout) { itsifile_config.fetch(:header_read_timeout, nil) },
|
114
|
+
notify_watchers: itsifile_config.fetch(:notify_watchers, nil),
|
115
|
+
threads: args.fetch(:threads) { itsifile_config.fetch(:threads, 1) },
|
116
|
+
scheduler_threads: args.fetch(:scheduler_threads) { itsifile_config.fetch(:scheduler_threads, nil) },
|
117
|
+
streamable_body: args.fetch(:streamable_body) { itsifile_config.fetch(:streamable_body, false) },
|
118
|
+
multithreaded_reactor: args.fetch(:multithreaded_reactor) do
|
119
|
+
itsifile_config.fetch(:multithreaded_reactor, nil)
|
120
|
+
end,
|
121
|
+
pin_worker_cores: args.fetch(:pin_worker_cores) { itsifile_config.fetch(:pin_worker_cores, true) },
|
122
|
+
scheduler_class: args.fetch(:scheduler_class) { itsifile_config.fetch(:scheduler_class, nil) },
|
123
|
+
oob_gc_responses_threshold: args.fetch(:oob_gc_responses_threshold) do
|
124
|
+
itsifile_config.fetch(:oob_gc_responses_threshold, nil)
|
125
|
+
end,
|
126
|
+
log_level: args.fetch(:log_level) { itsifile_config.fetch(:log_level, nil) },
|
127
|
+
log_format: args.fetch(:log_format) { itsifile_config.fetch(:log_format, nil) },
|
128
|
+
log_target: args.fetch(:log_target) { itsifile_config.fetch(:log_target, nil) },
|
129
|
+
log_target_filters: args.fetch(:log_target_filters) { itsifile_config.fetch(:log_target_filters, nil) },
|
130
|
+
binds: args.fetch(:binds) { itsifile_config.fetch(:binds, ["http://0.0.0.0:3000"]) },
|
131
|
+
middleware_loader: middleware_loader,
|
132
|
+
listeners: args.fetch(:listeners) { nil },
|
133
|
+
reuse_address: itsifile_config.fetch(:reuse_address, true),
|
134
|
+
reuse_port: itsifile_config.fetch(:reuse_port, true),
|
135
|
+
listen_backlog: itsifile_config.fetch(:listen_backlog, 1024 ),
|
136
|
+
nodelay: itsifile_config.fetch(:nodelay, true),
|
137
|
+
recv_buffer_size: itsifile_config.fetch(:recv_buffer_size, 262_144)
|
138
|
+
}.transform_keys(&:to_s)
|
127
139
|
|
128
|
-
|
140
|
+
error_lines = errors.flat_map do |(error, message)|
|
129
141
|
location = message[/(.*?)\:in/,1]
|
130
142
|
file, lineno = location.split(":")
|
131
143
|
lineno = lineno.to_i
|
@@ -135,12 +147,17 @@ module Itsi
|
|
135
147
|
[]
|
136
148
|
else
|
137
149
|
([lineno-2, 0].max...[file_lines.length, lineno.succ.succ].min).map do |currline|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
150
|
+
if currline == lineno-1
|
151
|
+
line = file_lines[currline][0...-1]
|
152
|
+
padding = line[/^\s+/]&.length || 0
|
153
|
+
|
154
|
+
[
|
155
|
+
" \e[31m#{currline.succ.to_s.rjust(3)} | #{line}\e[0m",
|
156
|
+
" | #{' ' * padding}\e[33m^^^\e[0m "
|
157
|
+
]
|
158
|
+
else
|
159
|
+
" #{currline.succ.to_s.rjust(3)} | #{file_lines[currline][0...-1]}"
|
160
|
+
end
|
144
161
|
end.flatten
|
145
162
|
end
|
146
163
|
[
|
@@ -149,11 +166,23 @@ module Itsi
|
|
149
166
|
*info_lines
|
150
167
|
]
|
151
168
|
end
|
152
|
-
|
169
|
+
|
170
|
+
return srv_config, error_lines
|
171
|
+
rescue
|
172
|
+
Itsi.log_error e.message
|
173
|
+
puts e.backtrace
|
153
174
|
end
|
154
175
|
|
155
176
|
def self.test!(cli_params)
|
156
177
|
_, errors = build_config(cli_params, Itsi::Server::Config.config_file_path(cli_params[:config_file]))
|
178
|
+
unless errors.any?
|
179
|
+
begin
|
180
|
+
_["middleware_loader"][]
|
181
|
+
rescue Exception => e
|
182
|
+
errors = [e]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
157
186
|
if errors.any?
|
158
187
|
Itsi.log_error("Config file is invalid")
|
159
188
|
puts errors
|
@@ -181,7 +210,7 @@ module Itsi
|
|
181
210
|
elsif File.exist?("config/#{ITSI_DEFAULT_CONFIG_FILE}")
|
182
211
|
"config/#{ITSI_DEFAULT_CONFIG_FILE}"
|
183
212
|
end
|
184
|
-
# Options
|
213
|
+
# Options pass through unless we've specified a config file
|
185
214
|
return unless File.exist?(config_file_path.to_s)
|
186
215
|
|
187
216
|
config_file_path
|
@@ -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
|
@@ -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
|
|
@@ -90,6 +89,7 @@ module Itsi
|
|
90
89
|
|
91
90
|
buffer << ch
|
92
91
|
|
92
|
+
|
93
93
|
if in_string
|
94
94
|
if escape
|
95
95
|
escape = false
|
@@ -23,13 +23,14 @@ 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
|
-
|
32
|
+
puts "Handling active call"
|
33
|
+
unless (active_call.rpc_desc = @rpc_descs[active_call.method_name])
|
33
34
|
active_call.stream.write("\n")
|
34
35
|
active_call.send_status(13, "Method not found")
|
35
36
|
active_call.close
|
@@ -85,15 +86,21 @@ module Itsi
|
|
85
86
|
|
86
87
|
def handle_server_streaming(active_call)
|
87
88
|
message = active_call.remote_read
|
88
|
-
service.send(active_call.method_name, message, active_call) do |response|
|
89
|
+
result = service.send(active_call.method_name, message, active_call) do |response|
|
89
90
|
active_call.remote_send(response)
|
90
91
|
end
|
92
|
+
if result.kind_of?(Enumerator)
|
93
|
+
result.each { |response| active_call.remote_send(response) }
|
94
|
+
end
|
91
95
|
end
|
92
96
|
|
93
97
|
def handle_bidi_streaming(active_call)
|
94
|
-
service.send(active_call.method_name, active_call.each_remote_read, active_call) do |response|
|
98
|
+
result = service.send(active_call.method_name, active_call.each_remote_read, active_call) do |response|
|
95
99
|
active_call.remote_send(response)
|
96
100
|
end
|
101
|
+
if result.kind_of?(Enumerator)
|
102
|
+
result.each { |response| active_call.remote_send(response) }
|
103
|
+
end
|
97
104
|
end
|
98
105
|
end
|
99
106
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
return unless defined?(::Rackup::Handler) || defined?(Rack::Handler)
|
2
2
|
|
3
|
+
|
3
4
|
module Rack
|
4
5
|
module Handler
|
5
6
|
module Itsi
|
6
7
|
def self.run(app, options = {})
|
7
8
|
host = options.fetch(:host, "127.0.0.1")
|
8
9
|
port = options.fetch(:Port, 3001)
|
9
|
-
Itsi::Server.start(
|
10
|
+
::Itsi::Server.start(
|
10
11
|
{
|
11
12
|
app: app,
|
12
13
|
binds: ["http://#{host}:#{port}"]
|
13
|
-
}
|
14
|
-
Itsi::Server::Config.config_file_path
|
14
|
+
}
|
15
15
|
)
|
16
16
|
end
|
17
17
|
end
|
@@ -4,13 +4,63 @@ module Itsi
|
|
4
4
|
|
5
5
|
require "set"
|
6
6
|
require "strscan"
|
7
|
-
|
7
|
+
require "debug"
|
8
8
|
def format_mw(mw)
|
9
|
-
|
9
|
+
mw_name, mw_args = mw
|
10
|
+
case mw_name
|
10
11
|
when "app"
|
11
|
-
"
|
12
|
+
"\e[33mapp\e[0m(#{mw_args['app_proc'].inspect.split(' ')[1][0...-1]})"
|
13
|
+
when "log_requests"
|
14
|
+
if mw_args['before'] && mw_args['after']
|
15
|
+
"\e[33mlog_requests\e[0m(before: #{mw_args['before']['format'][0..6]}..., after: #{mw_args['after']['format'][0..6]}...)"
|
16
|
+
elsif mw_args['before']
|
17
|
+
"\e[33mlog_requests\e[0m(before: #{mw_args['before']['format'][0..6]}...)"
|
18
|
+
elsif mw_args['after']
|
19
|
+
"\e[33mlog_requests\e[0m(before: nil, after: #{mw_args['after']['format'][0..6]}...)"
|
20
|
+
end
|
21
|
+
when "compress"
|
22
|
+
"\e[33mcompress\e[0m(#{mw_args['algorithms'].join(' ')}, #{mw_args['mime_types']})"
|
23
|
+
when "cors"
|
24
|
+
"\e[33mcors\e[0m(#{mw_args['allow_origins'].join(' ')}, #{mw_args['allow_methods'].join(' ')})"
|
25
|
+
when "etag"
|
26
|
+
"\e[33metag\e[0m(#{mw_args['type']}/#{mw_args['algorithm']}, #{mw_args['handle_if_none_match'] ? 'if_none_match' : ''})"
|
27
|
+
when "cache_control"
|
28
|
+
"\e[33mcache_control\e[0m(max_age: #{mw_args['max_age']}, #{mw_args.select{|_,v| v == true }.keys.join(", ")})"
|
29
|
+
when "redirect"
|
30
|
+
"\e[33mredirect\e[0m(to: #{mw_args['to']}, type: #{mw_args['type']})"
|
31
|
+
when "static_assets"
|
32
|
+
"\e[33mstatic_assets\e[0m(path: #{mw_args['root_dir']})"
|
33
|
+
when "auth_api_key"
|
34
|
+
"\e[33mauth_api_key\e[0m(keys: #{mw_args['valid_keys'].keys}#{mw_args['credentials_file'] ? ", credentials_file: #{mw_args['credentials_file']}" : ""})"
|
35
|
+
when "auth_basic"
|
36
|
+
"\e[33mbasic_auth\e[0m(keys: #{mw_args['realm']}#{mw_args['credentials_file'] ? ", credentials_file: #{mw_args['credentials_file']}" : ""})"
|
37
|
+
when "auth_jwt"
|
38
|
+
"\e[33mjwt_auth\e[0m(#{mw_args['verifiers'].keys.join(",")})"
|
39
|
+
when "rate_limit"
|
40
|
+
key = mw_args['key'].kind_of?(Hash) ? mw_args['key']["parameter"] : mw_args['key']
|
41
|
+
"\e[33mrate_limit\e[0m(rps: #{mw_args['requests']}/#{mw_args['seconds']}, key: #{key})"
|
42
|
+
when "allow_list"
|
43
|
+
"\e[33mallow_list\e[0m(patterns: #{mw_args['allowed_patterns'].join(", ")})"
|
44
|
+
when "deny_list"
|
45
|
+
"\e[33mdeny_list\e[0m(patterns: #{mw_args['denied_patterns'].join(", ")})"
|
46
|
+
when "csp"
|
47
|
+
"\e[33mcsp\e[0m(#{mw_args['policy'].map{|k,v| "#{k}: #{v.join(",")}"}.join(", ")})"
|
48
|
+
when "intrusion_protection"
|
49
|
+
[mw_args].flatten.map do |mw_args|
|
50
|
+
"\e[33mintrusion_protection\e[0m(banned_url_patterns: #{mw_args['banned_url_patterns']&.length}, banned_header_patterns: #{mw_args['banned_header_patterns']&.keys&.join(", ")}, #{mw_args['banned_time_seconds']}s)"
|
51
|
+
end.join("\n")
|
52
|
+
when "request_headers"
|
53
|
+
[mw_args].flatten.map do |mw_args|
|
54
|
+
"\e[33mrequest_headers\e[0m(added: #{mw_args["additions"].keys}, removed: #{mw_args["removals"]})"
|
55
|
+
end.join("\n")
|
56
|
+
when "response_headers"
|
57
|
+
[mw_args].flatten.map do |mw_args|
|
58
|
+
"\e[33mresponse_headers\e[0m(added: #{mw_args["additions"].keys}, removed: #{mw_args["removals"]})"
|
59
|
+
end.join("\n")
|
60
|
+
when "static_response"
|
61
|
+
"\e[response_headers\e[0m(#{mw_args["code"]} body: #{mw_args["body"][0..10]})"
|
12
62
|
else
|
13
|
-
mw["
|
63
|
+
"\e[33m#{mw.first}\e[0m"
|
14
64
|
end
|
15
65
|
end
|
16
66
|
|
@@ -21,12 +71,12 @@ module Itsi
|
|
21
71
|
end.compact
|
22
72
|
filter_str = filters.any? ? filters.join(", ") : "(none)"
|
23
73
|
|
24
|
-
middlewares = stack["middleware"]
|
74
|
+
middlewares = stack["middleware"].to_a
|
25
75
|
|
26
76
|
puts "─" * 76
|
27
|
-
puts "
|
28
|
-
puts "
|
29
|
-
puts "
|
77
|
+
puts "\e[32mRoute:\e[0m \e[33m#{route_str}\e[0m"
|
78
|
+
puts "\e[32mConditions:\e[0m \e[34m#{filter_str}\e[0m"
|
79
|
+
puts "\e[32mMiddleware:\e[0m • #{format_mw(middlewares.first)}"
|
30
80
|
middlewares[1..].each do |mw|
|
31
81
|
puts " • #{format_mw(mw)}"
|
32
82
|
end
|
@@ -23,21 +23,21 @@ module Itsi
|
|
23
23
|
case v
|
24
24
|
when true, 'true', '1', 1 then true
|
25
25
|
when false, 'false', '0', 0 then false
|
26
|
-
else raise "Cannot cast #{v.inspect} to Boolean"
|
26
|
+
else raise ValidationError.new("Cannot cast #{v.inspect} to Boolean")
|
27
27
|
end
|
28
28
|
},
|
29
29
|
FalseClass => ->(v){
|
30
30
|
case v
|
31
31
|
when true, 'true', '1', 1 then true
|
32
32
|
when false, 'false', '0', 0 then false
|
33
|
-
else raise "Cannot cast #{v.inspect} to Boolean"
|
33
|
+
else raise ValidationError.new("Cannot cast #{v.inspect} to Boolean")
|
34
34
|
end
|
35
35
|
},
|
36
36
|
:Boolean => ->(v){
|
37
37
|
case v
|
38
38
|
when true, 'true', '1', 1 then true
|
39
39
|
when false, 'false', '0', 0 then false
|
40
|
-
else raise "Cannot cast #{v.inspect} to Boolean"
|
40
|
+
else raise ValidationError.new("Cannot cast #{v.inspect} to Boolean")
|
41
41
|
end
|
42
42
|
},
|
43
43
|
Date => ->(v){ Date.parse(v.to_s) },
|
@@ -45,17 +45,6 @@ module Itsi
|
|
45
45
|
DateTime => ->(v){ DateTime.parse(v.to_s) }
|
46
46
|
}.compare_by_identity
|
47
47
|
|
48
|
-
# Extracts the expected type and required flag from a schema definition.
|
49
|
-
def extract_schema(schema_def)
|
50
|
-
if schema_def.is_a?(Hash) && schema_def.key?(:_type)
|
51
|
-
expected_type = schema_def[:_type]
|
52
|
-
required = schema_def.fetch(:required, true)
|
53
|
-
[expected_type, required]
|
54
|
-
else
|
55
|
-
[schema_def, true]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
48
|
# Preprocess the schema into fixed keys (as symbols) and regex keys.
|
60
49
|
# Memoizes the result based on the schema.
|
61
50
|
def processed_schema(schema)
|
@@ -63,8 +52,9 @@ module Itsi
|
|
63
52
|
@@schema_cache[schema] ||= begin
|
64
53
|
fixed = {}
|
65
54
|
regex = []
|
55
|
+
required_params = schema[:_required] || []
|
66
56
|
schema.each do |k, schema_def|
|
67
|
-
expected_type, required =
|
57
|
+
expected_type, required = schema_def, required_params.include?(k)
|
68
58
|
if k.is_a?(Regexp)
|
69
59
|
regex << [k, [expected_type, required]]
|
70
60
|
else
|
@@ -179,16 +169,22 @@ module Itsi
|
|
179
169
|
end
|
180
170
|
|
181
171
|
# Process regex keys (only string keys not already handled as fixed keys).
|
182
|
-
params.keys.
|
172
|
+
params.keys.each do |key|
|
173
|
+
if key == :_required
|
174
|
+
params.delete(key)
|
175
|
+
next
|
176
|
+
end
|
183
177
|
next if fixed_schema.has_key?(key.to_sym) || fixed_schema.has_key?(key)
|
184
|
-
regex_schema.
|
178
|
+
unless regex_schema.find do |regex, (expected_type, _required)|
|
185
179
|
if regex.match(key)
|
186
180
|
new_path = path + [key]
|
187
181
|
err = cast_value!(params, key, expected_type, new_path)
|
188
182
|
errors << err if err
|
189
|
-
|
183
|
+
true # only use the first matching regex
|
190
184
|
end
|
191
185
|
end
|
186
|
+
params.delete(key)
|
187
|
+
end
|
192
188
|
end
|
193
189
|
|
194
190
|
raise ValidationError.new(errors) unless errors.empty?
|
@@ -6,17 +6,18 @@ module Itsi
|
|
6
6
|
|
7
7
|
|
8
8
|
def self.extract_expr_from_source_location(proc)
|
9
|
-
|
9
|
+
source_location = proc.source_location
|
10
|
+
source_lines = IO.readlines(source_location.first)
|
10
11
|
|
11
12
|
proc_line = source_location.last - 1
|
12
13
|
first_line = source_lines[proc_line]
|
13
14
|
|
14
|
-
until first_line =~ /(?:lambda|proc|->|def|.*?do\s
|
15
|
+
until first_line =~ /(?:lambda|proc|->|def|.*?do\s*|.*?\{.*?\|)/ || proc_line.zero?
|
15
16
|
proc_line -= 1
|
16
17
|
first_line = source_lines[proc_line]
|
17
18
|
end
|
18
19
|
lines = source_lines[proc_line..]
|
19
|
-
lines[0] = lines[0][/(?:lambda|proc|->|def|.*?do\s
|
20
|
+
lines[0] = lines[0][/(?:lambda|proc|->|def|.*?do\s+|.*?\{.*?\|).*/]
|
20
21
|
src_str = lines.first << "\n"
|
21
22
|
intermediate = Prism.parse(src_str)
|
22
23
|
|
@@ -47,7 +48,7 @@ module Itsi
|
|
47
48
|
|
48
49
|
[requireds.length, keywords]
|
49
50
|
rescue
|
50
|
-
[ proc.parameters.
|
51
|
+
[ proc.parameters.select{|p| p == :req }&.length || 0, {}]
|
51
52
|
end
|
52
53
|
end
|
53
54
|
end
|
@@ -5,10 +5,18 @@ module Itsi
|
|
5
5
|
class Server
|
6
6
|
module TypedHandlers
|
7
7
|
def self.handler_for(proc, input_schema)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
if input_schema
|
9
|
+
input_schema = proc.binding.eval(input_schema)
|
10
|
+
lambda do |req|
|
11
|
+
req.params(input_schema) do |params|
|
12
|
+
proc.call(req, params: params)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
else
|
16
|
+
lambda do |req|
|
17
|
+
req.params do |params|
|
18
|
+
proc.call(req, params)
|
19
|
+
end
|
12
20
|
end
|
13
21
|
end
|
14
22
|
end
|