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
@@ -0,0 +1,50 @@
|
|
1
|
+
require_relative "../helpers/test_helper"
|
2
|
+
|
3
|
+
class TestRequestHeaders < Minitest::Test
|
4
|
+
def test_add_and_remove_static
|
5
|
+
server(
|
6
|
+
itsi_rb: lambda do
|
7
|
+
request_headers \
|
8
|
+
additions: { "X-Test" => ["hello"] },
|
9
|
+
removals: ["X-Remove-Me"]
|
10
|
+
get("/foo") do |r|
|
11
|
+
r.ok r.header("X-Test").first + "|" + (r.header("X-Remove-Me").empty? ? "gone" : "here")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
) do
|
15
|
+
res = get_resp("/foo", { "X-Remove-Me" => "bye" })
|
16
|
+
assert_equal "200", res.code
|
17
|
+
assert_equal "hello|gone", res.body
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_dynamic_string_rewrite
|
22
|
+
server(
|
23
|
+
itsi_rb: lambda do
|
24
|
+
request_headers \
|
25
|
+
additions: { "X-Path" => ["{path_and_query}"] },
|
26
|
+
removals: []
|
27
|
+
get("/bar") { |r| r.ok r.header("X-Path").first }
|
28
|
+
end
|
29
|
+
) do
|
30
|
+
res = get_resp("/bar?x=1")
|
31
|
+
assert_equal "200", res.code
|
32
|
+
assert_equal "/bar?x=1", res.body
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_override_existing_header
|
37
|
+
server(
|
38
|
+
itsi_rb: lambda do
|
39
|
+
request_headers \
|
40
|
+
additions: { "User-Agent" => ["ItsiTester"] },
|
41
|
+
removals: ["User-Agent"]
|
42
|
+
get("/u") { |r| r.ok r.header("User-Agent").first }
|
43
|
+
end
|
44
|
+
) do
|
45
|
+
res = get_resp("/u", { "User-Agent" => "orig" })
|
46
|
+
assert_equal "200", res.code
|
47
|
+
assert_equal "ItsiTester", res.body
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require_relative "../helpers/test_helper"
|
2
|
+
|
3
|
+
class TestResponseHeaders < Minitest::Test
|
4
|
+
def test_add_and_remove_static
|
5
|
+
server(
|
6
|
+
itsi_rb: lambda do
|
7
|
+
response_headers \
|
8
|
+
additions: { "X-Test" => ["world"] }
|
9
|
+
# removals: ["X-Custom"]
|
10
|
+
get("/foo") { |r| r.ok "hi", {"X-Custom" => "value"} }
|
11
|
+
end
|
12
|
+
) do
|
13
|
+
res = get_resp("/foo")
|
14
|
+
assert_equal "200", res.code
|
15
|
+
assert_equal "world", res["X-Test"]
|
16
|
+
refute res.key?("X-Custom")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_dynamic_response_rewrite
|
21
|
+
server(
|
22
|
+
itsi_rb: lambda do
|
23
|
+
response_headers \
|
24
|
+
additions: { "X-Addr" => ["{addr}"] },
|
25
|
+
removals: []
|
26
|
+
get("/addr") { |r| r.ok "12345" }
|
27
|
+
end
|
28
|
+
) do
|
29
|
+
res = get_resp("/addr")
|
30
|
+
assert_equal "200", res.code
|
31
|
+
assert_equal "127.0.0.1", res["X-Addr"]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_override_multiple_values
|
36
|
+
server(
|
37
|
+
itsi_rb: lambda do
|
38
|
+
response_headers \
|
39
|
+
additions: { "Set-Cookie" => ["a=1", "b=2"] },
|
40
|
+
removals: ["Set-Cookie"]
|
41
|
+
get("/cookie") { |r| r.ok "ok" }
|
42
|
+
end
|
43
|
+
) do
|
44
|
+
res = get_resp("/cookie")
|
45
|
+
cookies = res.get_fields("Set-Cookie")
|
46
|
+
assert_includes cookies, "a=1"
|
47
|
+
assert_includes cookies, "b=2"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,374 @@
|
|
1
|
+
require_relative "../helpers/test_helper"
|
2
|
+
require "tmpdir"
|
3
|
+
|
4
|
+
class TestStaticAssets < Minitest::Test
|
5
|
+
# Test serving an existing file via GET.
|
6
|
+
def test_serving_existing_file
|
7
|
+
Dir.mktmpdir do |dir|
|
8
|
+
file_path = File.join(dir, "test.txt")
|
9
|
+
File.write(file_path, "Hello world")
|
10
|
+
server(
|
11
|
+
itsi_rb: lambda do
|
12
|
+
static_assets \
|
13
|
+
root_dir: "#{dir}",
|
14
|
+
not_found_behavior: "fallthrough",
|
15
|
+
headers: { "Cache-Control" => "max-age=3600" },
|
16
|
+
allowed_extensions: ["txt"]
|
17
|
+
|
18
|
+
get("/test.txt") { |r| r.ok "fallback" }
|
19
|
+
end
|
20
|
+
) do
|
21
|
+
res = get_resp("/test.txt")
|
22
|
+
assert_equal "200", res.code, "Expected 200 OK for an existing file"
|
23
|
+
assert_equal "Hello world", res.body
|
24
|
+
assert_match /max-age=3600/, res["Cache-Control"]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Test HEAD request returns headers with no body.
|
30
|
+
def test_head_request
|
31
|
+
Dir.mktmpdir do |dir|
|
32
|
+
file_path = File.join(dir, "test.txt")
|
33
|
+
File.write(file_path, "Hello world")
|
34
|
+
server(
|
35
|
+
itsi_rb: lambda do
|
36
|
+
static_assets \
|
37
|
+
root_dir: "#{dir}",
|
38
|
+
not_found_behavior: "fallthrough",
|
39
|
+
allowed_extensions: ["txt"]
|
40
|
+
|
41
|
+
get("/test.txt") { |r| r.ok "fallback" }
|
42
|
+
end
|
43
|
+
) do
|
44
|
+
res = head("/test.txt")
|
45
|
+
assert_equal "200", res.code, "Expected 200 OK for HEAD request"
|
46
|
+
assert(res.body.nil? || res.body.empty?, "Expected empty body for HEAD request")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Test that non-GET/HEAD requests are not handled by static asset middleware.
|
52
|
+
def test_non_get_head_request_passes_through
|
53
|
+
Dir.mktmpdir do |dir|
|
54
|
+
File.write(File.join(dir, "test.txt"), "Hello world")
|
55
|
+
server(
|
56
|
+
itsi_rb: lambda do
|
57
|
+
static_assets \
|
58
|
+
root_dir: "#{dir}",
|
59
|
+
not_found_behavior: "fallthrough",
|
60
|
+
allowed_extensions: ["txt"]
|
61
|
+
|
62
|
+
endpoint { |r| r.ok "fallback" }
|
63
|
+
end
|
64
|
+
) do
|
65
|
+
res = post("/test.txt","")
|
66
|
+
# Since POST is not handled by static assets, expect the fallback.
|
67
|
+
assert_equal "200", res.code, "Expected fallback response for non-GET/HEAD request"
|
68
|
+
assert_equal "fallback", res.body
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Test try_html_extension: If "test.html" exists, a request to "/test" returns its content.
|
74
|
+
def test_try_html_extension
|
75
|
+
Dir.mktmpdir do |dir|
|
76
|
+
File.write(File.join(dir, "test.html"), "HTML content")
|
77
|
+
server(
|
78
|
+
itsi_rb: lambda do
|
79
|
+
static_assets \
|
80
|
+
root_dir: "#{dir}",
|
81
|
+
not_found_behavior: "fallthrough",
|
82
|
+
try_html_extension: true,
|
83
|
+
allowed_extensions: ["html"]
|
84
|
+
|
85
|
+
get("/test") { |r| r.ok "fallback" }
|
86
|
+
end
|
87
|
+
) do
|
88
|
+
res = get_resp("/test")
|
89
|
+
assert_equal "200", res.code, "Expected 200 OK with try_html_extension"
|
90
|
+
assert_equal "HTML content", res.body
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Test a Range request for partial content.
|
96
|
+
def test_range_request
|
97
|
+
Dir.mktmpdir do |dir|
|
98
|
+
File.write(File.join(dir, "test.txt"), "Hello world")
|
99
|
+
server(
|
100
|
+
itsi_rb: lambda do
|
101
|
+
static_assets \
|
102
|
+
root_dir: "#{dir}",
|
103
|
+
not_found_behavior: "fallthrough",
|
104
|
+
allowed_extensions: ["txt"]
|
105
|
+
|
106
|
+
get("/test.txt") { |r| r.ok "fallback" }
|
107
|
+
end
|
108
|
+
) do
|
109
|
+
res = get_resp("/test.txt", { "Range" => "bytes=0-4" })
|
110
|
+
# Expecting 206 Partial Content with "Hello" as the body.
|
111
|
+
assert_equal "206", res.code, "Expected 206 Partial Content for valid Range request"
|
112
|
+
assert_equal "Hello", res.body
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Test that a non-existent file passes through to the fallback handler.
|
118
|
+
def test_file_not_found_passes_through
|
119
|
+
Dir.mktmpdir do |dir|
|
120
|
+
server(
|
121
|
+
itsi_rb: lambda do
|
122
|
+
static_assets \
|
123
|
+
root_dir: "#{dir}",
|
124
|
+
not_found_behavior: "fallthrough",
|
125
|
+
allowed_extensions: ["txt"]
|
126
|
+
|
127
|
+
get("/nonexistent") { |r| r.ok "fallback" }
|
128
|
+
end
|
129
|
+
) do
|
130
|
+
res = get_resp("/nonexistent")
|
131
|
+
assert_equal "200", res.code, "Expected fallback response for non-existent file"
|
132
|
+
assert_equal "fallback", res.body
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
def test_relative_path_true
|
137
|
+
Dir.mktmpdir do |dir|
|
138
|
+
# Create file "test.txt" in root_dir.
|
139
|
+
dir = FileUtils.mkdir_p(File.join(dir, "foo", "bar", "baz")).first
|
140
|
+
file_path = File.join(dir, "test.txt")
|
141
|
+
File.write(file_path, "relative true")
|
142
|
+
server(
|
143
|
+
itsi_rb: lambda do
|
144
|
+
location "foo/bar/baz" do
|
145
|
+
static_assets \
|
146
|
+
root_dir: "#{dir}",
|
147
|
+
not_found_behavior: "fallthrough",
|
148
|
+
allowed_extensions: ["txt"],
|
149
|
+
relative_path: true
|
150
|
+
|
151
|
+
get("/foo/bar/baz/test.txt") { |r| r.ok "fallback" }
|
152
|
+
end
|
153
|
+
end
|
154
|
+
) do
|
155
|
+
res = get_resp("/foo/bar/baz/test.txt")
|
156
|
+
assert_equal "200", res.code, "Expected 200 OK with relative_path: true"
|
157
|
+
assert_equal "relative true", res.body
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_relative_path_false
|
163
|
+
Dir.mktmpdir do |dir|
|
164
|
+
# Create file "test.txt" in root_dir.
|
165
|
+
child_dir = FileUtils.mkdir_p(File.join(dir, "foo", "bar", "baz")).first
|
166
|
+
file_path = File.join(child_dir, "test.txt")
|
167
|
+
|
168
|
+
File.write(file_path, "relative false")
|
169
|
+
server(
|
170
|
+
itsi_rb: lambda do
|
171
|
+
|
172
|
+
location "/foo/bar/baz/" do
|
173
|
+
static_assets \
|
174
|
+
root_dir: "#{dir}",
|
175
|
+
not_found_behavior: "fallthrough",
|
176
|
+
allowed_extensions: ["txt"],
|
177
|
+
relative_path: false
|
178
|
+
|
179
|
+
get("/foo/bar/baz/test.txt") { |r| r.ok "fallback" }
|
180
|
+
end
|
181
|
+
end
|
182
|
+
) do
|
183
|
+
res = get_resp("/foo/bar/baz/test.txt")
|
184
|
+
|
185
|
+
assert_equal "200", res.code, "Expected 200 OK with relative_path: false"
|
186
|
+
assert_equal "relative false", res.body
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# 2. Allowed Extensions Test
|
192
|
+
def test_file_not_in_allowed_extensions
|
193
|
+
Dir.mktmpdir do |dir|
|
194
|
+
file_path = File.join(dir, "file.xyz")
|
195
|
+
File.write(file_path, "not allowed")
|
196
|
+
server(
|
197
|
+
itsi_rb: lambda do
|
198
|
+
static_assets \
|
199
|
+
root_dir: "#{dir}",
|
200
|
+
not_found_behavior: "fallthrough",
|
201
|
+
allowed_extensions: ["txt"]
|
202
|
+
get("/file.xyz") { |r| r.ok "fallback" }
|
203
|
+
end
|
204
|
+
) do
|
205
|
+
res = get_resp("/file.xyz")
|
206
|
+
assert_equal "200", res.code, "Expected fallback when file extension is not allowed"
|
207
|
+
assert_equal "fallback", res.body
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_hidden_files_not_served_when_disabled
|
213
|
+
Dir.mktmpdir do |dir|
|
214
|
+
file_path = File.join(dir, ".secret.txt")
|
215
|
+
File.write(file_path, "hidden content")
|
216
|
+
server(
|
217
|
+
itsi_rb: lambda do
|
218
|
+
static_assets \
|
219
|
+
root_dir: "#{dir}",
|
220
|
+
not_found_behavior: "fallthrough"
|
221
|
+
endpoint { |r| r.ok "fallback" }
|
222
|
+
end
|
223
|
+
) do
|
224
|
+
res = get_resp("/.secret.txt")
|
225
|
+
|
226
|
+
assert_equal "200", res.code, "Expected fallback when hidden files are disabled"
|
227
|
+
assert_equal "fallback", res.body
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_hidden_files_served_when_enabled
|
233
|
+
Dir.mktmpdir do |dir|
|
234
|
+
file_path = File.join(dir, ".secret.txt")
|
235
|
+
File.write(file_path, "hidden content")
|
236
|
+
server(
|
237
|
+
itsi_rb: lambda do
|
238
|
+
static_assets \
|
239
|
+
root_dir: "#{dir}",
|
240
|
+
not_found_behavior: "fallthrough",
|
241
|
+
allowed_extensions: ["txt"],
|
242
|
+
serve_hidden_files: true
|
243
|
+
get("/.secret.txt") { |r| r.ok "fallback" }
|
244
|
+
end
|
245
|
+
) do
|
246
|
+
res = get_resp("/.secret.txt")
|
247
|
+
assert_equal "200", res.code, "Expected 200 OK when hidden files are enabled"
|
248
|
+
assert_equal "hidden content", res.body
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
# 4. Auto Index Tests
|
254
|
+
def test_auto_index_json
|
255
|
+
Dir.mktmpdir do |dir|
|
256
|
+
File.write(File.join(dir, "file1.txt"), "content1")
|
257
|
+
File.write(File.join(dir, "file2.txt"), "content2")
|
258
|
+
server(
|
259
|
+
itsi_rb: lambda do
|
260
|
+
static_assets \
|
261
|
+
root_dir: "#{dir}",
|
262
|
+
not_found_behavior: "fallthrough",
|
263
|
+
auto_index: true,
|
264
|
+
allowed_extensions: []
|
265
|
+
get("/") { |r| r.ok "fallback" }
|
266
|
+
end
|
267
|
+
) do
|
268
|
+
res = get_resp("/", { "Accept" => "application/json" })
|
269
|
+
|
270
|
+
assert_equal "200", res.code, "Expected 200 OK for JSON auto index"
|
271
|
+
assert_includes res.body, "[", "Expected JSON listing in auto index"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_auto_index_html
|
277
|
+
Dir.mktmpdir do |dir|
|
278
|
+
File.write(File.join(dir, "file1.txt"), "content1")
|
279
|
+
File.write(File.join(dir, "file2.txt"), "content2")
|
280
|
+
server(
|
281
|
+
itsi_rb: lambda do
|
282
|
+
static_assets \
|
283
|
+
root_dir: "#{dir}",
|
284
|
+
not_found_behavior: "fallthrough",
|
285
|
+
auto_index: true,
|
286
|
+
allowed_extensions: []
|
287
|
+
get("/") { |r| r.ok "fallback" }
|
288
|
+
end
|
289
|
+
) do
|
290
|
+
res = get_resp("/", { "Accept" => "text/html" })
|
291
|
+
assert_equal "200", res.code, "Expected 200 OK for HTML auto index"
|
292
|
+
assert_includes res.body.downcase, "<html", "Expected HTML structure in auto index"
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
# 5. Not Found Behavior Tests
|
298
|
+
def test_not_found_behavior_index
|
299
|
+
Dir.mktmpdir do |dir|
|
300
|
+
# Create an index file to be used as fallback.
|
301
|
+
File.write(File.join(dir, "index.html"), "SPA Index")
|
302
|
+
server(
|
303
|
+
itsi_rb: lambda do
|
304
|
+
static_assets \
|
305
|
+
root_dir: "#{dir}",
|
306
|
+
not_found_behavior: { index: "index.html" },
|
307
|
+
allowed_extensions: ["html"]
|
308
|
+
get("/nonexistent") { |r| r.ok "fallback" }
|
309
|
+
end
|
310
|
+
) do
|
311
|
+
res = get_resp("/nonexistent")
|
312
|
+
assert_equal "200", res.code, "Expected index to be served for index not found behaviour"
|
313
|
+
assert_equal "SPA Index", res.body
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_not_found_behavior_redirect
|
319
|
+
Dir.mktmpdir do |dir|
|
320
|
+
server(
|
321
|
+
itsi_rb: lambda do
|
322
|
+
static_assets \
|
323
|
+
root_dir: "#{dir}",
|
324
|
+
not_found_behavior: { redirect: { to: "https://example.com", type: "permanent" } }
|
325
|
+
get("/nonexistent") { |r| r.ok "fallback" }
|
326
|
+
end
|
327
|
+
) do
|
328
|
+
res = get_resp("/nonexistent")
|
329
|
+
assert_equal "308", res.code, "Expected 308 for redirect not found behaviour"
|
330
|
+
assert_equal "https://example.com", res["Location"]
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_not_found_behavior_error_builtin
|
336
|
+
Dir.mktmpdir do |dir|
|
337
|
+
server(
|
338
|
+
itsi_rb: lambda do
|
339
|
+
static_assets \
|
340
|
+
root_dir: "#{dir}",
|
341
|
+
not_found_behavior: {error: "not_found"}
|
342
|
+
get("/nonexistent") { |r| r.ok "fallback" }
|
343
|
+
end
|
344
|
+
) do
|
345
|
+
res = get_resp("/nonexistent")
|
346
|
+
assert_equal "404", res.code, "Expected 404 for built-in not_found behaviour"
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
def test_not_found_behavior_custom_error
|
352
|
+
Dir.mktmpdir do |dir|
|
353
|
+
server(
|
354
|
+
itsi_rb: lambda do
|
355
|
+
static_assets \
|
356
|
+
root_dir: "#{dir}",
|
357
|
+
not_found_behavior: {
|
358
|
+
error: {
|
359
|
+
code: 404,
|
360
|
+
plaintext: { inline: "Not Found" },
|
361
|
+
html: { inline: "<h1>Not Found</h1>" },
|
362
|
+
default: "plaintext"
|
363
|
+
},
|
364
|
+
}
|
365
|
+
get("/nonexistent") { |r| r.ok "fallback" }
|
366
|
+
end
|
367
|
+
) do
|
368
|
+
res = get_resp("/nonexistent")
|
369
|
+
assert_equal "404", res.code, "Expected 404 for custom not_found behaviour"
|
370
|
+
assert_equal "Not Found", res.body
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# test_static_response.rb
|
2
|
+
require_relative "../helpers/test_helper"
|
3
|
+
|
4
|
+
class TestStaticResponse < Minitest::Test
|
5
|
+
def test_basic_response_code_and_body
|
6
|
+
server(
|
7
|
+
itsi_rb: lambda do
|
8
|
+
static_response \
|
9
|
+
code: 204,
|
10
|
+
headers: [],
|
11
|
+
body: ""
|
12
|
+
end
|
13
|
+
) do
|
14
|
+
res = get_resp("/any")
|
15
|
+
assert_equal "204", res.code
|
16
|
+
assert_nil res.body # 204 should have no body
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_custom_headers_and_body
|
21
|
+
server(
|
22
|
+
itsi_rb: lambda do
|
23
|
+
static_response \
|
24
|
+
code: 418,
|
25
|
+
headers: [
|
26
|
+
["Content-Type","text/teapot"],
|
27
|
+
["X-Test","value"]
|
28
|
+
],
|
29
|
+
body: "I'm a teapot"
|
30
|
+
end
|
31
|
+
) do
|
32
|
+
res = get_resp("/brew")
|
33
|
+
assert_equal "418", res.code
|
34
|
+
assert_equal "text/teapot", res["Content-Type"]
|
35
|
+
assert_equal "value", res["X-Test"]
|
36
|
+
assert_equal "I'm a teapot", res.body
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_binary_body
|
41
|
+
data = [0x00,0xFF,0x7F]
|
42
|
+
server(
|
43
|
+
itsi_rb: lambda do
|
44
|
+
static_response \
|
45
|
+
code: 200,
|
46
|
+
headers: [["Content-Type","application/octet-stream"]],
|
47
|
+
body: data.pack("C*")
|
48
|
+
end
|
49
|
+
) do
|
50
|
+
res = get_resp("/bin")
|
51
|
+
# Ensure raw bytes round‑trip
|
52
|
+
assert_equal data.pack("C*"), res.body
|
53
|
+
assert_equal "application/octet-stream", res["Content-Type"]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require_relative "../helpers/test_helper"
|
2
|
+
|
3
|
+
class TestStringRewrite < Minitest::Test
|
4
|
+
|
5
|
+
def test_interpolates_method
|
6
|
+
server(
|
7
|
+
itsi_rb: lambda do
|
8
|
+
redirect to: "https://example.com/{method}/redirect", type: "temporary"
|
9
|
+
get("/foo") { |r| r.ok "should not get here" }
|
10
|
+
end
|
11
|
+
) do
|
12
|
+
res = get_resp("/foo")
|
13
|
+
assert_equal "307", res.code, "Expected status 307 for temporary redirect"
|
14
|
+
assert_equal "https://example.com/GET/redirect", res["Location"]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_interpolates_path
|
19
|
+
server(
|
20
|
+
itsi_rb: lambda do
|
21
|
+
redirect to: "https://example.com{path}", type: "found"
|
22
|
+
get("/bar") { |r| r.ok "should not get here" }
|
23
|
+
end
|
24
|
+
) do
|
25
|
+
res = get_resp("/bar")
|
26
|
+
assert_equal "302", res.code, "Expected status 302 for found redirect"
|
27
|
+
assert_equal "https://example.com/bar", res["Location"]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_interpolates_addr
|
32
|
+
server(
|
33
|
+
itsi_rb: lambda do
|
34
|
+
redirect to: "https://{addr}/redirect", type: "moved_permanently"
|
35
|
+
get("/foo") { |r| r.ok "should not get here" }
|
36
|
+
end
|
37
|
+
) do
|
38
|
+
res = get_resp("/foo")
|
39
|
+
assert_equal "301", res.code, "Expected status 301 for moved permanently redirect"
|
40
|
+
# In tests, the context's address is typically set to "127.0.0.1"
|
41
|
+
assert_equal "https://127.0.0.1/redirect", res["Location"]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_interpolates_host
|
46
|
+
server(
|
47
|
+
itsi_rb: lambda do
|
48
|
+
redirect to: "https://{host}/", type: "permanent"
|
49
|
+
get("/foo") { |r| r.ok "should not get here" }
|
50
|
+
end
|
51
|
+
) do
|
52
|
+
res = get_resp("/foo")
|
53
|
+
assert_equal "308", res.code, "Expected status 308 for permanent redirect"
|
54
|
+
# When no host is explicitly specified in the URL, it defaults to "localhost"
|
55
|
+
assert_equal "https://localhost/", res["Location"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_interpolates_path_and_query
|
60
|
+
server(
|
61
|
+
itsi_rb: lambda do
|
62
|
+
redirect to: "https://example.com{path_and_query}", type: "temporary"
|
63
|
+
get("/foo") { |r| r.ok "should not get here" }
|
64
|
+
end
|
65
|
+
) do
|
66
|
+
res = get_resp("/foo?bar=baz")
|
67
|
+
assert_equal "307", res.code, "Expected status 307 for temporary redirect"
|
68
|
+
assert_equal "https://example.com/foo?bar=baz", res["Location"]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_interpolates_query
|
73
|
+
server(
|
74
|
+
itsi_rb: lambda do
|
75
|
+
redirect to: "https://example.com{query}", type: "found"
|
76
|
+
get("/foo?x=y") { |r| r.ok "should not get here" }
|
77
|
+
end
|
78
|
+
) do
|
79
|
+
res = get_resp("/foo?x=y")
|
80
|
+
assert_equal "302", res.code, "Expected status 302 for found redirect"
|
81
|
+
assert_equal "https://example.com?x=y", res["Location"]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_interpolates_port
|
86
|
+
server(
|
87
|
+
itsi_rb: lambda do
|
88
|
+
redirect to: "https://example.com:{port}/", type: "moved_permanently"
|
89
|
+
# We assume that if no port is provided in the request URI, it defaults to "80"
|
90
|
+
get("/foo") { |r| r.ok "should not get here" }
|
91
|
+
end
|
92
|
+
) do
|
93
|
+
res = get_resp("/foo")
|
94
|
+
assert_equal "301", res.code, "Expected status 301 for moved permanently redirect"
|
95
|
+
assert_equal "https://example.com:80/", res["Location"]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_unknown_placeholder_remains_unmodified
|
100
|
+
server(
|
101
|
+
itsi_rb: lambda do
|
102
|
+
redirect to: "https://example.com/{unknown}", type: "permanent"
|
103
|
+
get("/foo") { |r| r.ok "should not get here" }
|
104
|
+
end
|
105
|
+
) do
|
106
|
+
res = get_resp("/foo")
|
107
|
+
# The unknown placeholder is not substituted and remains as '{unknown}'.
|
108
|
+
assert_equal "308", res.code, "Expected status 308 for permanent redirect"
|
109
|
+
assert_equal "https://example.com/{unknown}", res["Location"]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative "../helpers/test_helper"
|
2
|
+
|
3
|
+
class TestBind < Minitest::Test
|
4
|
+
def test_http
|
5
|
+
server(
|
6
|
+
app: lambda do |env|
|
7
|
+
[200, { "Content-Type" => "text/plain" }, ["Hello, World!"]]
|
8
|
+
end) do
|
9
|
+
assert_equal "Hello, World!", get("/")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def test_https
|
15
|
+
server(app: lambda do |env|
|
16
|
+
[200, { "Content-Type" => "text/plain" }, ["Hello, HTTPS!"]]
|
17
|
+
end, protocol: "https") do |uri|
|
18
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true,
|
19
|
+
verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
|
20
|
+
http.request(Net::HTTP::Get.new("/"))
|
21
|
+
end
|
22
|
+
assert_equal "200", response.code
|
23
|
+
assert_equal "Hello, HTTPS!", response.body
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_unix_socket_http
|
28
|
+
server(
|
29
|
+
bind: free_bind("http", unix_socket: true),
|
30
|
+
app: lambda do |env|
|
31
|
+
[200, { "Content-Type" => "text/plain" }, ["Hello, World!"]]
|
32
|
+
end) do
|
33
|
+
assert_equal "Hello, World!", get("/")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_unix_socket_https
|
38
|
+
server(
|
39
|
+
bind: free_bind("http", unix_socket: true),
|
40
|
+
app: lambda do |env|
|
41
|
+
[200, { "Content-Type" => "text/plain" }, ["Hello, World!"]]
|
42
|
+
end) do
|
43
|
+
assert_equal "Hello, World!", get("/")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|