itsi 0.2.3 → 0.2.4
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/Cargo.lock +2 -2
- data/README.md +1 -1
- data/Rakefile +2 -2
- data/crates/itsi_scheduler/Cargo.toml +1 -1
- data/crates/itsi_server/Cargo.toml +1 -1
- data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +28 -11
- data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +1 -1
- data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +1 -2
- data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +14 -2
- data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +86 -41
- data/crates/itsi_server/src/services/itsi_http_service.rs +46 -35
- data/crates/itsi_server/src/services/static_file_server.rs +31 -3
- data/examples/api_with_schema_and_controllers/Itsi.rb +35 -0
- data/examples/api_with_schema_and_controllers/README.md +10 -0
- data/examples/api_with_schema_and_controllers/controllers.rb +66 -0
- data/examples/api_with_schema_and_controllers/schemas.rb +25 -0
- data/examples/file_server/Itsi.rb +30 -0
- data/examples/file_server/README.md +3 -0
- data/examples/file_server/about.html +80 -0
- data/examples/file_server/admin/secrets.txt +1 -0
- data/examples/file_server/fairytale.txt +33 -0
- data/examples/file_server/itsi-server-100.png +0 -0
- data/examples/file_server/subdirectory/movies.csv +21 -0
- data/examples/helpers/datastore.rb +84 -0
- data/examples/media_server/Itsi.rb +5 -0
- data/examples/media_server/README.md +3 -0
- data/examples/media_server/images/itsi-server-100.png +0 -0
- data/examples/media_server/index.html +82 -0
- data/examples/multi_rack_rails_sinatra/Gemfile +66 -0
- data/examples/multi_rack_rails_sinatra/Gemfile.lock +416 -0
- data/examples/multi_rack_rails_sinatra/Itsi.rb +44 -0
- data/examples/multi_rack_rails_sinatra/README.md +7 -0
- data/examples/multi_rack_rails_sinatra/index.html +119 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.dockerignore +51 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.gitattributes +9 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.github/dependabot.yml +12 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.github/workflows/ci.yml +90 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.gitignore +34 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/hooks/docker-setup.sample +3 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/hooks/post-app-boot.sample +3 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/hooks/post-deploy.sample +14 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/hooks/post-proxy-reboot.sample +3 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/hooks/pre-app-boot.sample +3 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/hooks/pre-build.sample +51 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/hooks/pre-connect.sample +47 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/hooks/pre-deploy.sample +109 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/hooks/pre-proxy-reboot.sample +3 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.kamal/secrets +17 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.rubocop.yml +8 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/.ruby-version +1 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/Dockerfile +72 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/Gemfile +66 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/Gemfile.lock +416 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/README.md +24 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/Rakefile +6 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/assets/images/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/assets/stylesheets/application.css +161 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/controllers/application_controller.rb +4 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/controllers/articles_controller.rb +70 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/controllers/concerns/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/controllers/home_controller.rb +4 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/helpers/application_helper.rb +2 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/helpers/articles_helper.rb +2 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/helpers/home_helper.rb +2 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/javascript/application.js +3 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/javascript/controllers/application.js +9 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/javascript/controllers/hello_controller.js +7 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/javascript/controllers/index.js +4 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/jobs/application_job.rb +7 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/mailers/application_mailer.rb +4 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/models/application_record.rb +3 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/models/article.rb +2 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/models/concerns/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/articles/_article.html.erb +14 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/articles/_article.json.jbuilder +2 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/articles/_form.html.erb +30 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/articles/edit.html.erb +12 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/articles/index.html.erb +29 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/articles/index.json.jbuilder +1 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/articles/new.html.erb +11 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/articles/show.html.erb +10 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/articles/show.json.jbuilder +1 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/home/index.html.erb +8 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/layouts/application.html.erb +34 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/layouts/mailer.html.erb +13 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/layouts/mailer.text.erb +1 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/pwa/manifest.json.erb +22 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/app/views/pwa/service-worker.js +26 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/brakeman +7 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/bundle +109 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/dev +2 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/docker-entrypoint +14 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/importmap +4 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/jobs +6 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/kamal +27 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/rails +4 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/rake +4 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/rubocop +8 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/setup +34 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/bin/thrust +5 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/application.rb +27 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/boot.rb +4 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/cable.yml +17 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/cache.yml +16 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/credentials.yml.enc +1 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/database.yml +41 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/deploy.yml +116 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/environment.rb +5 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/environments/development.rb +72 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/environments/production.rb +90 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/environments/test.rb +53 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/importmap.rb +7 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/initializers/assets.rb +7 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/initializers/content_security_policy.rb +25 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/initializers/filter_parameter_logging.rb +8 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/initializers/inflections.rb +16 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/locales/en.yml +31 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/puma.rb +41 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/queue.yml +18 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/recurring.yml +10 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/routes.rb +17 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config/storage.yml +34 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/config.ru +6 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/db/cable_schema.rb +11 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/db/cache_schema.rb +14 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/db/migrate/20250422211855_create_articles.rb +10 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/db/queue_schema.rb +129 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/db/schema.rb +20 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/db/seeds.rb +9 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/lib/tasks/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/log/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/public/400.html +114 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/public/404.html +114 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/public/406-unsupported-browser.html +114 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/public/422.html +114 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/public/500.html +114 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/public/icon.png +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/public/icon.svg +3 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/public/robots.txt +1 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/script/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/storage/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/application_system_test_case.rb +5 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/controllers/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/controllers/articles_controller_test.rb +48 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/controllers/home_controller_test.rb +8 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/fixtures/articles.yml +9 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/fixtures/files/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/helpers/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/integration/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/mailers/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/models/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/models/article_test.rb +7 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/system/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/system/articles_test.rb +43 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/test/test_helper.rb +15 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/tmp/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/tmp/pids/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/tmp/storage/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/vendor/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/rails_subapp/vendor/javascript/.keep +0 -0
- data/examples/multi_rack_rails_sinatra/sinatra_subapp/config.ru +2 -0
- data/examples/multi_rack_rails_sinatra/sinatra_subapp/my_app.rb +96 -0
- data/examples/rails_with_static_assets/.dockerignore +51 -0
- data/examples/rails_with_static_assets/.gitattributes +9 -0
- data/examples/rails_with_static_assets/.github/dependabot.yml +12 -0
- data/examples/rails_with_static_assets/.github/workflows/ci.yml +90 -0
- data/examples/rails_with_static_assets/.gitignore +34 -0
- data/examples/rails_with_static_assets/.kamal/hooks/docker-setup.sample +3 -0
- data/examples/rails_with_static_assets/.kamal/hooks/post-app-boot.sample +3 -0
- data/examples/rails_with_static_assets/.kamal/hooks/post-deploy.sample +14 -0
- data/examples/rails_with_static_assets/.kamal/hooks/post-proxy-reboot.sample +3 -0
- data/examples/rails_with_static_assets/.kamal/hooks/pre-app-boot.sample +3 -0
- data/examples/rails_with_static_assets/.kamal/hooks/pre-build.sample +51 -0
- data/examples/rails_with_static_assets/.kamal/hooks/pre-connect.sample +47 -0
- data/examples/rails_with_static_assets/.kamal/hooks/pre-deploy.sample +109 -0
- data/examples/rails_with_static_assets/.kamal/hooks/pre-proxy-reboot.sample +3 -0
- data/examples/rails_with_static_assets/.kamal/secrets +17 -0
- data/examples/rails_with_static_assets/.rubocop.yml +8 -0
- data/examples/rails_with_static_assets/.ruby-version +1 -0
- data/examples/rails_with_static_assets/Dockerfile +72 -0
- data/examples/rails_with_static_assets/Gemfile +66 -0
- data/examples/rails_with_static_assets/Gemfile.lock +416 -0
- data/examples/rails_with_static_assets/Itsi.rb +10 -0
- data/examples/rails_with_static_assets/README.md +14 -0
- data/examples/rails_with_static_assets/Rakefile +6 -0
- data/examples/rails_with_static_assets/app/assets/images/.keep +0 -0
- data/examples/rails_with_static_assets/app/assets/stylesheets/application.css +161 -0
- data/examples/rails_with_static_assets/app/controllers/application_controller.rb +4 -0
- data/examples/rails_with_static_assets/app/controllers/articles_controller.rb +70 -0
- data/examples/rails_with_static_assets/app/controllers/concerns/.keep +0 -0
- data/examples/rails_with_static_assets/app/controllers/home_controller.rb +4 -0
- data/examples/rails_with_static_assets/app/helpers/application_helper.rb +2 -0
- data/examples/rails_with_static_assets/app/helpers/articles_helper.rb +2 -0
- data/examples/rails_with_static_assets/app/helpers/home_helper.rb +2 -0
- data/examples/rails_with_static_assets/app/javascript/application.js +3 -0
- data/examples/rails_with_static_assets/app/javascript/controllers/application.js +9 -0
- data/examples/rails_with_static_assets/app/javascript/controllers/hello_controller.js +7 -0
- data/examples/rails_with_static_assets/app/javascript/controllers/index.js +4 -0
- data/examples/rails_with_static_assets/app/jobs/application_job.rb +7 -0
- data/examples/rails_with_static_assets/app/mailers/application_mailer.rb +4 -0
- data/examples/rails_with_static_assets/app/models/application_record.rb +3 -0
- data/examples/rails_with_static_assets/app/models/article.rb +2 -0
- data/examples/rails_with_static_assets/app/models/concerns/.keep +0 -0
- data/examples/rails_with_static_assets/app/views/articles/_article.html.erb +14 -0
- data/examples/rails_with_static_assets/app/views/articles/_article.json.jbuilder +2 -0
- data/examples/rails_with_static_assets/app/views/articles/_form.html.erb +30 -0
- data/examples/rails_with_static_assets/app/views/articles/edit.html.erb +12 -0
- data/examples/rails_with_static_assets/app/views/articles/index.html.erb +29 -0
- data/examples/rails_with_static_assets/app/views/articles/index.json.jbuilder +1 -0
- data/examples/rails_with_static_assets/app/views/articles/new.html.erb +11 -0
- data/examples/rails_with_static_assets/app/views/articles/show.html.erb +10 -0
- data/examples/rails_with_static_assets/app/views/articles/show.json.jbuilder +1 -0
- data/examples/rails_with_static_assets/app/views/home/index.html.erb +8 -0
- data/examples/rails_with_static_assets/app/views/layouts/application.html.erb +34 -0
- data/examples/rails_with_static_assets/app/views/layouts/mailer.html.erb +13 -0
- data/examples/rails_with_static_assets/app/views/layouts/mailer.text.erb +1 -0
- data/examples/rails_with_static_assets/app/views/pwa/manifest.json.erb +22 -0
- data/examples/rails_with_static_assets/app/views/pwa/service-worker.js +26 -0
- data/examples/rails_with_static_assets/bin/brakeman +7 -0
- data/examples/rails_with_static_assets/bin/bundle +109 -0
- data/examples/rails_with_static_assets/bin/dev +2 -0
- data/examples/rails_with_static_assets/bin/docker-entrypoint +14 -0
- data/examples/rails_with_static_assets/bin/importmap +4 -0
- data/examples/rails_with_static_assets/bin/jobs +6 -0
- data/examples/rails_with_static_assets/bin/kamal +27 -0
- data/examples/rails_with_static_assets/bin/rails +4 -0
- data/examples/rails_with_static_assets/bin/rake +4 -0
- data/examples/rails_with_static_assets/bin/rubocop +8 -0
- data/examples/rails_with_static_assets/bin/setup +34 -0
- data/examples/rails_with_static_assets/bin/thrust +5 -0
- data/examples/rails_with_static_assets/config/application.rb +26 -0
- data/examples/rails_with_static_assets/config/boot.rb +4 -0
- data/examples/rails_with_static_assets/config/cable.yml +17 -0
- data/examples/rails_with_static_assets/config/cache.yml +16 -0
- data/examples/rails_with_static_assets/config/credentials.yml.enc +1 -0
- data/examples/rails_with_static_assets/config/database.yml +41 -0
- data/examples/rails_with_static_assets/config/deploy.yml +116 -0
- data/examples/rails_with_static_assets/config/environment.rb +5 -0
- data/examples/rails_with_static_assets/config/environments/development.rb +74 -0
- data/examples/rails_with_static_assets/config/environments/production.rb +90 -0
- data/examples/rails_with_static_assets/config/environments/test.rb +53 -0
- data/examples/rails_with_static_assets/config/importmap.rb +7 -0
- data/examples/rails_with_static_assets/config/initializers/assets.rb +7 -0
- data/examples/rails_with_static_assets/config/initializers/content_security_policy.rb +25 -0
- data/examples/rails_with_static_assets/config/initializers/filter_parameter_logging.rb +8 -0
- data/examples/rails_with_static_assets/config/initializers/inflections.rb +16 -0
- data/examples/rails_with_static_assets/config/locales/en.yml +31 -0
- data/examples/rails_with_static_assets/config/puma.rb +41 -0
- data/examples/rails_with_static_assets/config/queue.yml +18 -0
- data/examples/rails_with_static_assets/config/recurring.yml +10 -0
- data/examples/rails_with_static_assets/config/routes.rb +17 -0
- data/examples/rails_with_static_assets/config/storage.yml +34 -0
- data/examples/rails_with_static_assets/config.ru +6 -0
- data/examples/rails_with_static_assets/db/cable_schema.rb +11 -0
- data/examples/rails_with_static_assets/db/cache_schema.rb +14 -0
- data/examples/rails_with_static_assets/db/migrate/20250422211855_create_articles.rb +10 -0
- data/examples/rails_with_static_assets/db/queue_schema.rb +129 -0
- data/examples/rails_with_static_assets/db/schema.rb +20 -0
- data/examples/rails_with_static_assets/db/seeds.rb +9 -0
- data/examples/rails_with_static_assets/lib/tasks/.keep +0 -0
- data/examples/rails_with_static_assets/log/.keep +0 -0
- data/examples/rails_with_static_assets/public/400.html +114 -0
- data/examples/rails_with_static_assets/public/404.html +114 -0
- data/examples/rails_with_static_assets/public/406-unsupported-browser.html +114 -0
- data/examples/rails_with_static_assets/public/422.html +114 -0
- data/examples/rails_with_static_assets/public/500.html +114 -0
- data/examples/rails_with_static_assets/public/icon.png +0 -0
- data/examples/rails_with_static_assets/public/icon.svg +3 -0
- data/examples/rails_with_static_assets/public/robots.txt +1 -0
- data/examples/rails_with_static_assets/script/.keep +0 -0
- data/examples/rails_with_static_assets/storage/.keep +0 -0
- data/examples/rails_with_static_assets/test/application_system_test_case.rb +5 -0
- data/examples/rails_with_static_assets/test/controllers/.keep +0 -0
- data/examples/rails_with_static_assets/test/controllers/articles_controller_test.rb +48 -0
- data/examples/rails_with_static_assets/test/controllers/home_controller_test.rb +8 -0
- data/examples/rails_with_static_assets/test/fixtures/articles.yml +9 -0
- data/examples/rails_with_static_assets/test/fixtures/files/.keep +0 -0
- data/examples/rails_with_static_assets/test/helpers/.keep +0 -0
- data/examples/rails_with_static_assets/test/integration/.keep +0 -0
- data/examples/rails_with_static_assets/test/mailers/.keep +0 -0
- data/examples/rails_with_static_assets/test/models/.keep +0 -0
- data/examples/rails_with_static_assets/test/models/article_test.rb +7 -0
- data/examples/rails_with_static_assets/test/system/.keep +0 -0
- data/examples/rails_with_static_assets/test/system/articles_test.rb +43 -0
- data/examples/rails_with_static_assets/test/test_helper.rb +15 -0
- data/examples/rails_with_static_assets/tmp/.keep +0 -0
- data/examples/rails_with_static_assets/tmp/pids/.keep +0 -0
- data/examples/rails_with_static_assets/tmp/storage/.keep +0 -0
- data/examples/rails_with_static_assets/vendor/.keep +0 -0
- data/examples/rails_with_static_assets/vendor/javascript/.keep +0 -0
- data/examples/reverse_proxy/Itsi.rb +28 -0
- data/examples/reverse_proxy/README.md +14 -0
- data/examples/reverse_proxy/index.html +119 -0
- data/examples/reverse_proxy/rails_subapp/.dockerignore +51 -0
- data/examples/reverse_proxy/rails_subapp/.gitattributes +9 -0
- data/examples/reverse_proxy/rails_subapp/.github/dependabot.yml +12 -0
- data/examples/reverse_proxy/rails_subapp/.github/workflows/ci.yml +90 -0
- data/examples/reverse_proxy/rails_subapp/.gitignore +34 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/hooks/docker-setup.sample +3 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/hooks/post-app-boot.sample +3 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/hooks/post-deploy.sample +14 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/hooks/post-proxy-reboot.sample +3 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/hooks/pre-app-boot.sample +3 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/hooks/pre-build.sample +51 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/hooks/pre-connect.sample +47 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/hooks/pre-deploy.sample +109 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/hooks/pre-proxy-reboot.sample +3 -0
- data/examples/reverse_proxy/rails_subapp/.kamal/secrets +17 -0
- data/examples/reverse_proxy/rails_subapp/.rubocop.yml +8 -0
- data/examples/reverse_proxy/rails_subapp/.ruby-version +1 -0
- data/examples/reverse_proxy/rails_subapp/Dockerfile +72 -0
- data/examples/reverse_proxy/rails_subapp/Gemfile +66 -0
- data/examples/reverse_proxy/rails_subapp/Gemfile.lock +416 -0
- data/examples/reverse_proxy/rails_subapp/README.md +24 -0
- data/examples/reverse_proxy/rails_subapp/Rakefile +6 -0
- data/examples/reverse_proxy/rails_subapp/app/assets/images/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/app/assets/stylesheets/application.css +161 -0
- data/examples/reverse_proxy/rails_subapp/app/controllers/application_controller.rb +4 -0
- data/examples/reverse_proxy/rails_subapp/app/controllers/articles_controller.rb +70 -0
- data/examples/reverse_proxy/rails_subapp/app/controllers/concerns/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/app/controllers/home_controller.rb +4 -0
- data/examples/reverse_proxy/rails_subapp/app/helpers/application_helper.rb +2 -0
- data/examples/reverse_proxy/rails_subapp/app/helpers/articles_helper.rb +2 -0
- data/examples/reverse_proxy/rails_subapp/app/helpers/home_helper.rb +2 -0
- data/examples/reverse_proxy/rails_subapp/app/javascript/application.js +3 -0
- data/examples/reverse_proxy/rails_subapp/app/javascript/controllers/application.js +9 -0
- data/examples/reverse_proxy/rails_subapp/app/javascript/controllers/hello_controller.js +7 -0
- data/examples/reverse_proxy/rails_subapp/app/javascript/controllers/index.js +4 -0
- data/examples/reverse_proxy/rails_subapp/app/jobs/application_job.rb +7 -0
- data/examples/reverse_proxy/rails_subapp/app/mailers/application_mailer.rb +4 -0
- data/examples/reverse_proxy/rails_subapp/app/models/application_record.rb +3 -0
- data/examples/reverse_proxy/rails_subapp/app/models/article.rb +2 -0
- data/examples/reverse_proxy/rails_subapp/app/models/concerns/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/app/views/articles/_article.html.erb +14 -0
- data/examples/reverse_proxy/rails_subapp/app/views/articles/_article.json.jbuilder +2 -0
- data/examples/reverse_proxy/rails_subapp/app/views/articles/_form.html.erb +30 -0
- data/examples/reverse_proxy/rails_subapp/app/views/articles/edit.html.erb +12 -0
- data/examples/reverse_proxy/rails_subapp/app/views/articles/index.html.erb +29 -0
- data/examples/reverse_proxy/rails_subapp/app/views/articles/index.json.jbuilder +1 -0
- data/examples/reverse_proxy/rails_subapp/app/views/articles/new.html.erb +11 -0
- data/examples/reverse_proxy/rails_subapp/app/views/articles/show.html.erb +10 -0
- data/examples/reverse_proxy/rails_subapp/app/views/articles/show.json.jbuilder +1 -0
- data/examples/reverse_proxy/rails_subapp/app/views/home/index.html.erb +8 -0
- data/examples/reverse_proxy/rails_subapp/app/views/layouts/application.html.erb +34 -0
- data/examples/reverse_proxy/rails_subapp/app/views/layouts/mailer.html.erb +13 -0
- data/examples/reverse_proxy/rails_subapp/app/views/layouts/mailer.text.erb +1 -0
- data/examples/reverse_proxy/rails_subapp/app/views/pwa/manifest.json.erb +22 -0
- data/examples/reverse_proxy/rails_subapp/app/views/pwa/service-worker.js +26 -0
- data/examples/reverse_proxy/rails_subapp/bin/brakeman +7 -0
- data/examples/reverse_proxy/rails_subapp/bin/bundle +109 -0
- data/examples/reverse_proxy/rails_subapp/bin/dev +2 -0
- data/examples/reverse_proxy/rails_subapp/bin/docker-entrypoint +14 -0
- data/examples/reverse_proxy/rails_subapp/bin/importmap +4 -0
- data/examples/reverse_proxy/rails_subapp/bin/jobs +6 -0
- data/examples/reverse_proxy/rails_subapp/bin/kamal +27 -0
- data/examples/reverse_proxy/rails_subapp/bin/rails +4 -0
- data/examples/reverse_proxy/rails_subapp/bin/rake +4 -0
- data/examples/reverse_proxy/rails_subapp/bin/rubocop +8 -0
- data/examples/reverse_proxy/rails_subapp/bin/setup +34 -0
- data/examples/reverse_proxy/rails_subapp/bin/thrust +5 -0
- data/examples/reverse_proxy/rails_subapp/config/application.rb +26 -0
- data/examples/reverse_proxy/rails_subapp/config/boot.rb +4 -0
- data/examples/reverse_proxy/rails_subapp/config/cable.yml +17 -0
- data/examples/reverse_proxy/rails_subapp/config/cache.yml +16 -0
- data/examples/reverse_proxy/rails_subapp/config/credentials.yml.enc +1 -0
- data/examples/reverse_proxy/rails_subapp/config/database.yml +41 -0
- data/examples/reverse_proxy/rails_subapp/config/deploy.yml +116 -0
- data/examples/reverse_proxy/rails_subapp/config/environment.rb +5 -0
- data/examples/reverse_proxy/rails_subapp/config/environments/development.rb +72 -0
- data/examples/reverse_proxy/rails_subapp/config/environments/production.rb +90 -0
- data/examples/reverse_proxy/rails_subapp/config/environments/test.rb +53 -0
- data/examples/reverse_proxy/rails_subapp/config/importmap.rb +7 -0
- data/examples/reverse_proxy/rails_subapp/config/initializers/assets.rb +7 -0
- data/examples/reverse_proxy/rails_subapp/config/initializers/content_security_policy.rb +25 -0
- data/examples/reverse_proxy/rails_subapp/config/initializers/filter_parameter_logging.rb +8 -0
- data/examples/reverse_proxy/rails_subapp/config/initializers/inflections.rb +16 -0
- data/examples/reverse_proxy/rails_subapp/config/locales/en.yml +31 -0
- data/examples/reverse_proxy/rails_subapp/config/puma.rb +41 -0
- data/examples/reverse_proxy/rails_subapp/config/queue.yml +18 -0
- data/examples/reverse_proxy/rails_subapp/config/recurring.yml +10 -0
- data/examples/reverse_proxy/rails_subapp/config/routes.rb +17 -0
- data/examples/reverse_proxy/rails_subapp/config/storage.yml +34 -0
- data/examples/reverse_proxy/rails_subapp/config.ru +6 -0
- data/examples/reverse_proxy/rails_subapp/db/cable_schema.rb +11 -0
- data/examples/reverse_proxy/rails_subapp/db/cache_schema.rb +14 -0
- data/examples/reverse_proxy/rails_subapp/db/migrate/20250422211855_create_articles.rb +10 -0
- data/examples/reverse_proxy/rails_subapp/db/queue_schema.rb +129 -0
- data/examples/reverse_proxy/rails_subapp/db/schema.rb +20 -0
- data/examples/reverse_proxy/rails_subapp/db/seeds.rb +9 -0
- data/examples/reverse_proxy/rails_subapp/lib/tasks/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/log/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/public/400.html +114 -0
- data/examples/reverse_proxy/rails_subapp/public/404.html +114 -0
- data/examples/reverse_proxy/rails_subapp/public/406-unsupported-browser.html +114 -0
- data/examples/reverse_proxy/rails_subapp/public/422.html +114 -0
- data/examples/reverse_proxy/rails_subapp/public/500.html +114 -0
- data/examples/reverse_proxy/rails_subapp/public/icon.png +0 -0
- data/examples/reverse_proxy/rails_subapp/public/icon.svg +3 -0
- data/examples/reverse_proxy/rails_subapp/public/robots.txt +1 -0
- data/examples/reverse_proxy/rails_subapp/script/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/storage/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/test/application_system_test_case.rb +5 -0
- data/examples/reverse_proxy/rails_subapp/test/controllers/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/test/controllers/articles_controller_test.rb +48 -0
- data/examples/reverse_proxy/rails_subapp/test/controllers/home_controller_test.rb +8 -0
- data/examples/reverse_proxy/rails_subapp/test/fixtures/articles.yml +9 -0
- data/examples/reverse_proxy/rails_subapp/test/fixtures/files/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/test/helpers/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/test/integration/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/test/mailers/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/test/models/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/test/models/article_test.rb +7 -0
- data/examples/reverse_proxy/rails_subapp/test/system/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/test/system/articles_test.rb +43 -0
- data/examples/reverse_proxy/rails_subapp/test/test_helper.rb +15 -0
- data/examples/reverse_proxy/rails_subapp/tmp/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/tmp/pids/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/tmp/storage/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/vendor/.keep +0 -0
- data/examples/reverse_proxy/rails_subapp/vendor/javascript/.keep +0 -0
- data/examples/reverse_proxy/sinatra_subapp/Gemfile +2 -0
- data/examples/reverse_proxy/sinatra_subapp/Gemfile.lock +46 -0
- data/examples/reverse_proxy/sinatra_subapp/config.ru +2 -0
- data/examples/reverse_proxy/sinatra_subapp/my_app.rb +96 -0
- data/examples/simple_api/Itsi.rb +127 -0
- data/examples/simple_api_no_schema/Itsi.rb +86 -0
- data/examples/spa/Itsi.rb +5 -0
- data/examples/spa/README.md +3 -0
- data/examples/spa/dist/assets/index-2cf7be43.js +40 -0
- data/examples/spa/dist/index.html +13 -0
- data/examples/spa/index.html +12 -0
- data/examples/spa/package-lock.json +1265 -0
- data/examples/spa/package.json +18 -0
- data/examples/spa/src/App.jsx +49 -0
- data/examples/spa/src/main.jsx +6 -0
- data/examples/spa/src/pages/About.jsx +9 -0
- data/examples/spa/src/pages/Home.jsx +9 -0
- data/examples/spa/vite.config.js +9 -0
- data/gems/scheduler/Cargo.lock +1 -1
- data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
- data/gems/server/Cargo.lock +1 -1
- data/gems/server/lib/itsi/server/config/dsl.rb +2 -2
- data/gems/server/lib/itsi/server/config/middleware/endpoint/endpoint.rb +0 -4
- data/gems/server/lib/itsi/server/config/middleware/location.rb +25 -21
- data/gems/server/lib/itsi/server/config/middleware/proxy.rb +15 -14
- data/gems/server/lib/itsi/server/config/middleware/rackup_file.rb +7 -10
- data/gems/server/lib/itsi/server/config/middleware/static_assets.rb +8 -4
- data/gems/server/lib/itsi/server/config/middleware/string_rewrite.md +14 -0
- data/gems/server/lib/itsi/server/config/options/include.rb +1 -1
- data/gems/server/lib/itsi/server/rack_interface.rb +1 -1
- data/gems/server/lib/itsi/server/route_tester.rb +1 -1
- data/gems/server/lib/itsi/server/typed_handlers/param_parser.rb +25 -0
- data/gems/server/lib/itsi/server/version.rb +1 -1
- data/gems/server/lib/itsi/server.rb +1 -1
- data/gems/server/test/middleware/static_assets.rb +6 -4
- data/gems/server/test/middleware/string_rewrite.rb +54 -0
- data/gems/server/test/middleware/test_log_requests.rb +13 -1
- data/lib/itsi/version.rb +1 -1
- metadata +431 -5
@@ -0,0 +1,18 @@
|
|
1
|
+
{
|
2
|
+
"name": "my-app",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"private": true,
|
5
|
+
"scripts": {
|
6
|
+
"dev": "vite",
|
7
|
+
"build": "vite build",
|
8
|
+
"preview": "vite preview"
|
9
|
+
},
|
10
|
+
"dependencies": {
|
11
|
+
"react": "^18.2.0",
|
12
|
+
"react-dom": "^18.2.0"
|
13
|
+
},
|
14
|
+
"devDependencies": {
|
15
|
+
"@vitejs/plugin-react": "^4.0.0",
|
16
|
+
"vite": "^4.4.0"
|
17
|
+
}
|
18
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
2
|
+
import Home from "./pages/Home";
|
3
|
+
import About from "./pages/About";
|
4
|
+
|
5
|
+
export default function App() {
|
6
|
+
const [path, setPath] = useState(window.location.pathname);
|
7
|
+
|
8
|
+
useEffect(() => {
|
9
|
+
const onPop = () => setPath(window.location.pathname);
|
10
|
+
window.addEventListener("popstate", onPop);
|
11
|
+
return () => window.removeEventListener("popstate", onPop);
|
12
|
+
}, []);
|
13
|
+
|
14
|
+
const navigate = (to) => {
|
15
|
+
window.history.pushState(null, "", to);
|
16
|
+
setPath(to);
|
17
|
+
};
|
18
|
+
|
19
|
+
let Page;
|
20
|
+
if (path === "/about") Page = About;
|
21
|
+
else Page = Home;
|
22
|
+
|
23
|
+
return (
|
24
|
+
<div style={{ padding: 20, fontFamily: "sans-serif" }}>
|
25
|
+
<nav style={{ marginBottom: 20 }}>
|
26
|
+
<a
|
27
|
+
href="/"
|
28
|
+
onClick={(e) => {
|
29
|
+
e.preventDefault();
|
30
|
+
navigate("/");
|
31
|
+
}}
|
32
|
+
style={{ marginRight: 10 }}
|
33
|
+
>
|
34
|
+
Home
|
35
|
+
</a>
|
36
|
+
<a
|
37
|
+
href="/about"
|
38
|
+
onClick={(e) => {
|
39
|
+
e.preventDefault();
|
40
|
+
navigate("/about");
|
41
|
+
}}
|
42
|
+
>
|
43
|
+
About
|
44
|
+
</a>
|
45
|
+
</nav>
|
46
|
+
<Page />
|
47
|
+
</div>
|
48
|
+
);
|
49
|
+
}
|
data/gems/scheduler/Cargo.lock
CHANGED
data/gems/server/Cargo.lock
CHANGED
@@ -52,9 +52,9 @@ module Itsi
|
|
52
52
|
@accepts = accepts.map { |s| s.is_a?(Regexp) ? s : s.to_s }
|
53
53
|
|
54
54
|
@options = {
|
55
|
-
|
55
|
+
nested_locations: [],
|
56
56
|
middleware_loader: lambda do
|
57
|
-
@options[:
|
57
|
+
@options[:nested_locations].each(&:call)
|
58
58
|
@middleware[:app] ||= {}
|
59
59
|
@middleware[:app][:app_proc] = @middleware[:app]&.[](:preloader)&.call || DEFAULT_APP[]
|
60
60
|
[flatten_routes, Config.errors_to_error_lines(errors)]
|
@@ -84,10 +84,6 @@ module Itsi
|
|
84
84
|
end
|
85
85
|
else
|
86
86
|
@params[:paths] << "" if @params[:paths].empty?
|
87
|
-
@params[:paths] = @params[:paths].flat_map do |p|
|
88
|
-
stripped_trailing = p[/(.*)\/?$/, 1]
|
89
|
-
[stripped_trailing, stripped_trailing + "/"]
|
90
|
-
end.uniq
|
91
87
|
location.location(*@params[:paths], methods: @params[:http_methods]) do
|
92
88
|
@middleware[:app] = app
|
93
89
|
end
|
@@ -27,7 +27,7 @@ module Itsi
|
|
27
27
|
end
|
28
28
|
|
29
29
|
attr_accessor :location, :routes, :block, :protocols, :hosts, :ports,
|
30
|
-
:extensions, :content_types, :accepts
|
30
|
+
:extensions, :content_types, :accepts
|
31
31
|
|
32
32
|
def initialize(location,
|
33
33
|
*routes,
|
@@ -56,13 +56,13 @@ module Itsi
|
|
56
56
|
block: block
|
57
57
|
}).to_h
|
58
58
|
@routes = params[:routes].empty? ? ["*"] : params[:routes]
|
59
|
-
@methods = params[:methods]
|
60
|
-
@protocols = params[:protocols] | params[:schemes]
|
61
|
-
@hosts = params[:hosts]
|
62
|
-
@ports = params[:ports]
|
63
|
-
@extensions = params[:extensions]
|
64
|
-
@content_types = params[:content_types]
|
65
|
-
@accepts = params[:accepts]
|
59
|
+
@methods = params[:methods].map { |s| s.is_a?(Regexp) ? s : s.to_s }
|
60
|
+
@protocols = (params[:protocols] | params[:schemes]).map { |s| s.is_a?(Regexp) ? s : s.to_s }
|
61
|
+
@hosts = params[:hosts].map { |s| s.is_a?(Regexp) ? s : s.to_s }
|
62
|
+
@ports = params[:ports].map { |s| s.is_a?(Regexp) ? s : s.to_s }
|
63
|
+
@extensions = params[:extensions].map { |s| s.is_a?(Regexp) ? s : s.to_s }
|
64
|
+
@content_types = params[:content_types].map { |s| s.is_a?(Regexp) ? s : s.to_s }
|
65
|
+
@accepts = params[:accepts].map { |s| s.is_a?(Regexp) ? s : s.to_s }
|
66
66
|
@block = block
|
67
67
|
end
|
68
68
|
|
@@ -70,27 +70,31 @@ module Itsi
|
|
70
70
|
@methods
|
71
71
|
end
|
72
72
|
|
73
|
+
def intersect(a, b)
|
74
|
+
return b if a.empty?
|
75
|
+
return a if b.empty?
|
76
|
+
a & b
|
77
|
+
end
|
78
|
+
|
73
79
|
def build!
|
74
80
|
build_child = lambda {
|
75
|
-
|
81
|
+
child = DSL.new(
|
76
82
|
location,
|
77
83
|
routes: routes,
|
78
|
-
methods:
|
79
|
-
protocols:
|
80
|
-
hosts:
|
81
|
-
ports:
|
82
|
-
extensions:
|
83
|
-
content_types:
|
84
|
-
accepts:
|
84
|
+
methods: intersect(http_methods, location.http_methods),
|
85
|
+
protocols: intersect(protocols, location.protocols),
|
86
|
+
hosts: intersect(hosts, location.hosts),
|
87
|
+
ports: intersect(ports, location.ports),
|
88
|
+
extensions: intersect(extensions, location.extensions),
|
89
|
+
content_types: intersect(content_types, location.content_types),
|
90
|
+
accepts: intersect(accepts, location.accepts),
|
85
91
|
controller: location.controller,
|
86
92
|
&block
|
87
93
|
)
|
94
|
+
child.options[:nested_locations].each(&:call)
|
95
|
+
location.children << child
|
88
96
|
}
|
89
|
-
|
90
|
-
location.options[:middleware_loaders] << build_child
|
91
|
-
else
|
92
|
-
build_child[]
|
93
|
-
end
|
97
|
+
location.options[:nested_locations] << build_child
|
94
98
|
end
|
95
99
|
|
96
100
|
end
|
@@ -2,17 +2,16 @@ module Itsi
|
|
2
2
|
class Server
|
3
3
|
module Config
|
4
4
|
class Proxy < Middleware
|
5
|
-
|
6
5
|
insert_text <<~SNIPPET
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
6
|
+
proxy \\
|
7
|
+
to: "${1:http://backend.example.com{path_and_query}",
|
8
|
+
backends: [${2:"127.0.0.1:3001", "127.0.0.1:3002"}],
|
9
|
+
backend_priority: ${3|"round_robin","ordered","random"|},
|
10
|
+
headers: { ${4| "X-Forwarded-For" => { rewrite: "{addr}" },|} },
|
11
|
+
verify_ssl: ${5|true,false|},
|
12
|
+
timeout: ${6|30,60|},
|
13
|
+
tls_sni: ${7|true,false|},
|
14
|
+
error_response: ${8|"bad_gateway", "service_unavailable", { code: 503\\, default_format: "html"\\, html: { inline: "<h1>Service Unavailable</h1>" } }|}
|
16
15
|
SNIPPET
|
17
16
|
|
18
17
|
detail "Forwards incoming requests to a backend server using dynamic URL rewriting. Supports various backend selection strategies and header overriding."
|
@@ -21,18 +20,20 @@ module Itsi
|
|
21
20
|
{
|
22
21
|
to: Type(String) & Required(),
|
23
22
|
backends: Array(Type(String)),
|
24
|
-
backend_priority: Enum([
|
23
|
+
backend_priority: Enum(%w[round_robin ordered random]).default("round_robin"),
|
25
24
|
headers: Hash(Type(String), Type(String)).default({}),
|
26
25
|
verify_ssl: Bool().default(true),
|
27
26
|
tls_sni: Bool().default(true),
|
28
27
|
timeout: Type(Integer).default(30),
|
29
|
-
error_response: Type(ErrorResponseDef).default("bad_gateway")
|
28
|
+
error_response: Type(ErrorResponseDef).default("bad_gateway")
|
30
29
|
}
|
31
30
|
end
|
32
31
|
|
33
32
|
def build!
|
34
|
-
require
|
35
|
-
@params[:backends]||=
|
33
|
+
require "uri"
|
34
|
+
@params[:backends] ||= URI.extract(@params[:to]).map(&URI.method(:parse)).map do |u|
|
35
|
+
"#{u.scheme}://#{u.host}:#{u.port}"
|
36
|
+
end
|
36
37
|
super
|
37
38
|
end
|
38
39
|
end
|
@@ -2,12 +2,11 @@ module Itsi
|
|
2
2
|
class Server
|
3
3
|
module Config
|
4
4
|
class RackupFile < Middleware
|
5
|
-
|
6
5
|
insert_text <<~SNIPPET
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
rackup_file \\
|
7
|
+
"config.ru",
|
8
|
+
nonblocking: ${2|true,false|},
|
9
|
+
sendfile: ${3|true,false|}
|
11
10
|
|
12
11
|
SNIPPET
|
13
12
|
|
@@ -23,20 +22,18 @@ module Itsi
|
|
23
22
|
def initialize(location, app, **params)
|
24
23
|
super(location, params)
|
25
24
|
raise "Rackup file must be a string" unless app.is_a?(String)
|
25
|
+
|
26
26
|
@app = Itsi::Server::RackInterface.for(app)
|
27
27
|
end
|
28
28
|
|
29
29
|
def build!
|
30
30
|
app_args = {
|
31
|
-
preloader: -> { @app},
|
31
|
+
preloader: -> { @app },
|
32
32
|
sendfile: @params[:sendfile],
|
33
33
|
nonblocking: @params[:nonblocking],
|
34
|
-
base_path: "^(?<base_path>#{location.paths_from_parent.gsub(/\.\*\)$/,
|
34
|
+
base_path: "^(?<base_path>#{location.paths_from_parent.gsub(/\.\*\)$/, ")")}).*$"
|
35
35
|
}
|
36
36
|
location.middleware[:app] = app_args
|
37
|
-
location.location("*") do
|
38
|
-
@middleware[:app] = app_args
|
39
|
-
end
|
40
37
|
end
|
41
38
|
end
|
42
39
|
end
|
@@ -75,11 +75,15 @@ module Itsi
|
|
75
75
|
@params[:allowed_extensions] << ""
|
76
76
|
end
|
77
77
|
|
78
|
-
@params[:
|
79
|
-
|
80
|
-
|
81
|
-
@middleware[:static_assets] = params
|
78
|
+
if @params[:allowed_extensions].any? && @params[:auto_index]
|
79
|
+
@params[:allowed_extensions] |= ["html"]
|
80
|
+
@params[:allowed_extensions] |= [""]
|
82
81
|
end
|
82
|
+
|
83
|
+
@params[:base_path] = "^(?<base_path>#{location.paths_from_parent.gsub(/\.\*\)$/,")")}).*$"
|
84
|
+
params = @params
|
85
|
+
|
86
|
+
location.middleware[:static_assets] = params
|
83
87
|
end
|
84
88
|
end
|
85
89
|
end
|
@@ -13,6 +13,20 @@ The String Rewrite mechanism is used when configuring Itsi for
|
|
13
13
|
|
14
14
|
It allows you to create dynamic strings from a template by combining literal text with placeholders. Placeholders (denoted using curly braces: `{}`) are replaced at runtime with data derived from the HTTP request, response, or context.
|
15
15
|
|
16
|
+
Modifiers can be appended after a pipe | to transform the substituted value.
|
17
|
+
|
18
|
+
## Modifiers
|
19
|
+
|
20
|
+
After a placeholder name, add |<modifier>:<arg> (or for replace, |replace:<from>,<to>). Available modifiers:
|
21
|
+
|
22
|
+
`strip_prefix:<text>` If the substituted value starts with <text>, remove that prefix.
|
23
|
+
|
24
|
+
`strip_suffix:<text>` If the substituted value ends with <text>, remove that suffix.
|
25
|
+
|
26
|
+
`replace:<from>,<to>` Replace all occurrences of <from> in the substituted value with <to>.
|
27
|
+
|
28
|
+
Modifiers are applied in the order they appear. You can chain multiple modifiers by repeating the |<modifier>:<arg> syntax (e.g. `{path|strip_prefix:/rails|replace:old,new}`).
|
29
|
+
|
16
30
|
### Rewriting a Request
|
17
31
|
|
18
32
|
The following placeholders are supported:
|
@@ -3,7 +3,7 @@ module Itsi
|
|
3
3
|
module Config
|
4
4
|
class Include < Option
|
5
5
|
|
6
|
-
insert_text "include \"${1|other_file
|
6
|
+
insert_text "include \"${1|other_file|}\" # Include another file to be loaded within the current configuration"
|
7
7
|
|
8
8
|
detail "Include another file to be loaded within the current configuration"
|
9
9
|
|
@@ -7,7 +7,7 @@ module Itsi
|
|
7
7
|
if app.is_a?(String)
|
8
8
|
dir = File.expand_path(File.dirname(app))
|
9
9
|
Dir.chdir(dir) do
|
10
|
-
loaded_app = ::Rack::Builder.parse_file(app)
|
10
|
+
loaded_app = ::Rack::Builder.parse_file(File.basename(app))
|
11
11
|
app = loaded_app.is_a?(Array) ? loaded_app.first : loaded_app
|
12
12
|
end
|
13
13
|
end
|
@@ -143,6 +143,31 @@ module Itsi
|
|
143
143
|
# Fixed keys are converted to symbols, and regex-matched keys remain as strings.
|
144
144
|
# The current location in the params is tracked as an array of path segments.
|
145
145
|
def apply_schema!(params, schema, path = [])
|
146
|
+
# Support top-level array schema: homogeneous arrays.
|
147
|
+
if schema.is_a?(Array)
|
148
|
+
# Only allow homogeneous array types
|
149
|
+
unless schema.size == 1
|
150
|
+
raise ValidationError.new(["Schema Array must contain exactly one type. Got #{schema.size}"])
|
151
|
+
end
|
152
|
+
expected_type = schema.first
|
153
|
+
# Expect params to be an Array
|
154
|
+
unless params.is_a?(Array)
|
155
|
+
raise ValidationError.new(["Expected Array at #{format_path(path)}, got #{params.class}"])
|
156
|
+
end
|
157
|
+
errors = []
|
158
|
+
params.each_with_index do |_, idx|
|
159
|
+
err = cast_value!(params, idx, expected_type, path + [idx])
|
160
|
+
errors << err if err
|
161
|
+
end
|
162
|
+
raise ValidationError.new(errors) unless errors.empty?
|
163
|
+
return params
|
164
|
+
end
|
165
|
+
|
166
|
+
# Ensure schema is a Hash
|
167
|
+
unless schema.is_a?(Hash)
|
168
|
+
raise ValidationError.new(["Unsupported schema type: #{schema.class} at #{format_path(path)}"])
|
169
|
+
end
|
170
|
+
|
146
171
|
errors = []
|
147
172
|
processed = processed_schema(schema)
|
148
173
|
fixed_schema = processed[0]
|
@@ -262,7 +262,7 @@ module Itsi
|
|
262
262
|
end
|
263
263
|
|
264
264
|
def routes(cli_params = {})
|
265
|
-
load_route_middleware_stack(cli_params).each do |stack|
|
265
|
+
load_route_middleware_stack(cli_params).first.each do |stack|
|
266
266
|
routes = explode_route_pattern(stack["route"].source)
|
267
267
|
routes.each do |route|
|
268
268
|
print_route(route, stack)
|
@@ -133,6 +133,7 @@ class TestStaticAssets < Minitest::Test
|
|
133
133
|
end
|
134
134
|
end
|
135
135
|
end
|
136
|
+
|
136
137
|
def test_relative_path_true
|
137
138
|
Dir.mktmpdir do |dir|
|
138
139
|
# Create file "test.txt" in root_dir.
|
@@ -141,18 +142,19 @@ class TestStaticAssets < Minitest::Test
|
|
141
142
|
File.write(file_path, "relative true")
|
142
143
|
server(
|
143
144
|
itsi_rb: lambda do
|
144
|
-
location "foo/bar/baz" do
|
145
|
+
location "foo/bar/baz/*" do
|
145
146
|
static_assets \
|
146
147
|
root_dir: "#{dir}",
|
147
148
|
not_found_behavior: "fallthrough",
|
148
149
|
allowed_extensions: ["txt"],
|
149
150
|
relative_path: true
|
150
151
|
|
151
|
-
get("/
|
152
|
+
get("/test.txt") { |r| r.not_found }
|
152
153
|
end
|
153
154
|
end
|
154
155
|
) do
|
155
156
|
res = get_resp("/foo/bar/baz/test.txt")
|
157
|
+
|
156
158
|
assert_equal "200", res.code, "Expected 200 OK with relative_path: true"
|
157
159
|
assert_equal "relative true", res.body
|
158
160
|
end
|
@@ -169,14 +171,14 @@ class TestStaticAssets < Minitest::Test
|
|
169
171
|
server(
|
170
172
|
itsi_rb: lambda do
|
171
173
|
|
172
|
-
location "/foo/bar/baz
|
174
|
+
location "/foo/bar/baz/*" do
|
173
175
|
static_assets \
|
174
176
|
root_dir: "#{dir}",
|
175
177
|
not_found_behavior: "fallthrough",
|
176
178
|
allowed_extensions: ["txt"],
|
177
179
|
relative_path: false
|
178
180
|
|
179
|
-
get("/
|
181
|
+
get("/test.txt") { |r| r.ok "fallback" }
|
180
182
|
end
|
181
183
|
end
|
182
184
|
) do
|
@@ -109,4 +109,58 @@ class TestStringRewrite < Minitest::Test
|
|
109
109
|
assert_equal "https://example.com/{unknown}", res["Location"]
|
110
110
|
end
|
111
111
|
end
|
112
|
+
|
113
|
+
def test_strip_prefix
|
114
|
+
server(
|
115
|
+
itsi_rb: lambda do
|
116
|
+
redirect to: "https://example.com{path|strip_prefix:/rails}", type: "temporary"
|
117
|
+
get("/rails/foo") { |r| r.ok }
|
118
|
+
end
|
119
|
+
) do
|
120
|
+
res = get_resp("/rails/foo")
|
121
|
+
assert_equal "307", res.code
|
122
|
+
assert_equal "https://example.com/foo", res["Location"]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_strip_suffix
|
127
|
+
server(
|
128
|
+
itsi_rb: lambda do
|
129
|
+
redirect to: "{path_and_query|strip_suffix:.json}", type: "found"
|
130
|
+
get("/data.json") { |r| r.ok }
|
131
|
+
end
|
132
|
+
) do
|
133
|
+
res = get_resp("/data.json")
|
134
|
+
assert_equal "302", res.code
|
135
|
+
# .json is removed from end of "/data.json"
|
136
|
+
assert_equal "/data", res["Location"]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_replace
|
141
|
+
server(
|
142
|
+
itsi_rb: lambda do
|
143
|
+
redirect to: "https://{host|replace:localhost,api.example.com}", type: "permanent"
|
144
|
+
get("/foo") { |r| r.ok }
|
145
|
+
end
|
146
|
+
) do
|
147
|
+
res = get_resp("/foo")
|
148
|
+
assert_equal "308", res.code
|
149
|
+
assert_equal "https://api.example.com", res["Location"]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_chain_modifiers
|
154
|
+
server(
|
155
|
+
itsi_rb: lambda do
|
156
|
+
redirect to: "https://example.com{path|strip_prefix:/v1|replace:api,service}", type: "temporary"
|
157
|
+
get("/v1/api/users") { |r| r.ok }
|
158
|
+
end
|
159
|
+
) do
|
160
|
+
res = get_resp("/v1/api/users")
|
161
|
+
assert_equal "307", res.code
|
162
|
+
# after strip_prefix: "/api/users", then replace "api"→"service"
|
163
|
+
assert_equal "https://example.com/service/users", res["Location"]
|
164
|
+
end
|
165
|
+
end
|
112
166
|
end
|
@@ -18,6 +18,11 @@ class TestLogRequests < Minitest::Test
|
|
18
18
|
get_resp("/foo?bar=baz")
|
19
19
|
end
|
20
20
|
end
|
21
|
+
server(
|
22
|
+
itsi_rb: lambda do
|
23
|
+
log_level :error
|
24
|
+
end
|
25
|
+
){}
|
21
26
|
|
22
27
|
# should emit something like "[a1b2c3] BEFORE GET /foo?bar=baz"
|
23
28
|
assert_match(%r{\[[0-9a-f]+\] BEFORE GET /foo\?bar=baz}, stdout)
|
@@ -39,10 +44,17 @@ class TestLogRequests < Minitest::Test
|
|
39
44
|
) do
|
40
45
|
get_resp("/foo")
|
41
46
|
end
|
47
|
+
|
48
|
+
server(
|
49
|
+
itsi_rb: lambda do
|
50
|
+
log_level :error
|
51
|
+
end
|
52
|
+
){}
|
53
|
+
|
42
54
|
end
|
43
55
|
|
44
56
|
# should emit something like "[d4e5f6] AFTER 200 in 1.234ms"
|
45
|
-
assert_match(/\[[0-9a-f]+\] AFTER 200 in \d
|
57
|
+
assert_match(/\[[0-9a-f]+\] AFTER 200 in \d+(?:\.\d+)?.?s/, stdout)
|
46
58
|
end
|
47
59
|
|
48
60
|
# 3. custom log‑level is honored
|
data/lib/itsi/version.rb
CHANGED