itsi 0.2.2 → 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/CHANGELOG.md +1 -1
- data/Cargo.lock +29 -30
- data/README.md +1 -0
- 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/ruby_types/itsi_server/itsi_server_config.rs +26 -3
- 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/docs/content/_index.md +1 -1
- data/docs/content/contact/_index.md +1 -1
- data/docs/content/directory_listing.jpg +0 -0
- data/docs/content/error_page.jpg +0 -0
- data/docs/content/getting_started/local_development.md +9 -2
- data/docs/content/getting_started/logging.md +1 -2
- data/docs/content/getting_started/signals.md +0 -1
- data/docs/hugo.yaml +3 -0
- 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 +74 -17
- data/gems/scheduler/itsi-scheduler.gemspec +2 -2
- data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
- data/gems/server/Cargo.lock +28 -29
- data/gems/server/itsi-server.gemspec +2 -2
- data/gems/server/lib/itsi/http_request.rb +31 -34
- data/gems/server/lib/itsi/http_response.rb +10 -8
- data/gems/server/lib/itsi/passfile.rb +6 -6
- data/gems/server/lib/itsi/server/config/config_helpers.rb +33 -33
- data/gems/server/lib/itsi/server/config/dsl.rb +16 -21
- data/gems/server/lib/itsi/server/config/known_paths.rb +11 -7
- data/gems/server/lib/itsi/server/config/middleware/endpoint/endpoint.rb +0 -4
- data/gems/server/lib/itsi/server/config/middleware/error_response.md +13 -0
- 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.md +40 -0
- 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/option.rb +0 -1
- data/gems/server/lib/itsi/server/config/options/include.rb +1 -1
- data/gems/server/lib/itsi/server/config/options/nodelay.md +2 -2
- data/gems/server/lib/itsi/server/config/options/reuse_address.md +1 -1
- data/gems/server/lib/itsi/server/config/typed_struct.rb +32 -35
- data/gems/server/lib/itsi/server/config.rb +107 -92
- data/gems/server/lib/itsi/server/default_app/default_app.rb +1 -1
- data/gems/server/lib/itsi/server/grpc/grpc_call.rb +4 -5
- data/gems/server/lib/itsi/server/grpc/grpc_interface.rb +6 -7
- data/gems/server/lib/itsi/server/rack/handler/itsi.rb +0 -1
- data/gems/server/lib/itsi/server/rack_interface.rb +1 -2
- data/gems/server/lib/itsi/server/route_tester.rb +26 -24
- data/gems/server/lib/itsi/server/typed_handlers/param_parser.rb +25 -0
- data/gems/server/lib/itsi/server/typed_handlers/source_parser.rb +9 -7
- data/gems/server/lib/itsi/server/version.rb +1 -1
- data/gems/server/lib/itsi/server.rb +22 -22
- data/gems/server/lib/itsi/standard_headers.rb +80 -80
- data/gems/server/test/helpers/test_helper.rb +17 -16
- 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 +66 -2
- data/gems/server/test/options/test_workers.rb +12 -5
- data/lib/itsi/version.rb +1 -1
- metadata +435 -13
- data/examples/static_assets_example.rb +0 -83
- data/grpc_test/Itsi.rb +0 -11
- data/grpc_test/echo.proto +0 -14
- data/grpc_test/echo_pb.rb +0 -16
- data/grpc_test/echo_service_impl.rb +0 -8
- data/grpc_test/echo_services_pb.rb +0 -22
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
require "forwardable"
|
3
4
|
require "stringio"
|
4
5
|
require "socket"
|
5
6
|
|
6
7
|
module Itsi
|
7
|
-
|
8
8
|
class HttpResponse
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def respond(
|
10
|
+
_body = nil, _status = 200, _header = nil, # rubocop:disable Lint/UnderscorePrefixedVariableName
|
11
|
+
status: _status, headers: _header, body: _body,
|
12
|
+
hijack: false
|
13
|
+
)
|
14
|
+
self.status = status.is_a?(Symbol) ? HTTP_STATUS_NAME_TO_CODE_MAP.fetch(status) : status.to_i
|
13
15
|
|
14
16
|
body = body.to_s unless body.is_a?(String)
|
15
17
|
|
@@ -33,9 +35,9 @@ module Itsi
|
|
33
35
|
|
34
36
|
# If you hijack the connection, you are responsible for closing it.
|
35
37
|
# Otherwise, the response will be closed automatically.
|
36
|
-
|
38
|
+
close unless hijack
|
37
39
|
else
|
38
|
-
|
40
|
+
close
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
module Itsi
|
2
2
|
class Server
|
3
|
-
|
4
3
|
module Passfile
|
5
|
-
require
|
4
|
+
require "io/console"
|
6
5
|
|
7
6
|
module_function
|
8
7
|
|
@@ -18,7 +17,7 @@ module Itsi
|
|
18
17
|
line.chomp!
|
19
18
|
next if line.empty?
|
20
19
|
|
21
|
-
user, pass = line.split(
|
20
|
+
user, pass = line.split(":", 2)
|
22
21
|
creds[user] = pass
|
23
22
|
end
|
24
23
|
end
|
@@ -26,14 +25,14 @@ module Itsi
|
|
26
25
|
end
|
27
26
|
|
28
27
|
def save(creds, filename)
|
29
|
-
File.open(filename,
|
28
|
+
File.open(filename, "w", 0o600) do |f|
|
30
29
|
creds.each do |u, p|
|
31
30
|
f.puts "#{u}:#{p}"
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|
35
34
|
|
36
|
-
def echo(
|
35
|
+
def echo(_, algorithm)
|
37
36
|
print "Enter username: "
|
38
37
|
username = $stdin.gets.chomp
|
39
38
|
|
@@ -56,6 +55,7 @@ module Itsi
|
|
56
55
|
|
57
56
|
def add(filename, algorithm)
|
58
57
|
return unless (creds = load(filename))
|
58
|
+
|
59
59
|
print "Enter username: "
|
60
60
|
username = $stdin.gets.chomp
|
61
61
|
|
@@ -98,11 +98,11 @@ module Itsi
|
|
98
98
|
def list(filename)
|
99
99
|
puts "Current credentials in '#{filename}':"
|
100
100
|
return unless (creds = load(filename))
|
101
|
+
|
101
102
|
creds.each do |u, p|
|
102
103
|
puts "#{u}:#{p}"
|
103
104
|
end
|
104
105
|
end
|
105
|
-
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
@@ -2,7 +2,6 @@ module Itsi
|
|
2
2
|
class Server
|
3
3
|
module Config
|
4
4
|
module ConfigHelpers
|
5
|
-
|
6
5
|
def self.load_and_register(klass)
|
7
6
|
config_type = klass.name.split("::").last.downcase.gsub(/([a-z]()[A-Z])/, '\1_\2')
|
8
7
|
|
@@ -17,35 +16,35 @@ module Itsi
|
|
17
16
|
following = klass.subclasses
|
18
17
|
new_class = (following - current).first
|
19
18
|
|
20
|
-
documentation_file = "#{file[/(.*)\.rb/,1]}.md"
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
.gsub(/^\{\{[^\}]+\}\}/, "") # Strip Hugo blocks
|
29
|
-
end
|
19
|
+
documentation_file = "#{file[/(.*)\.rb/, 1]}.md"
|
20
|
+
documentation_file = "#{file[%r{(.*)/[^/]+\.rb}, 1]}/_index.md" unless File.exist?(documentation_file)
|
21
|
+
next unless File.exist?(documentation_file) && new_class
|
22
|
+
|
23
|
+
new_class.documentation IO.read(documentation_file)
|
24
|
+
.gsub(/^---.*?\n.*?-+/m, "") # Strip frontmatter
|
25
|
+
.gsub(/^(```.*?)\{.*?\}.*$/, "\\1") # Strip filename from code blocks
|
26
|
+
.gsub(/^\{\{[^}]+\}\}/, "") # Strip Hugo blocks
|
30
27
|
end
|
31
28
|
end
|
32
29
|
|
33
|
-
def normalize_keys!(hash, expected=[])
|
30
|
+
def normalize_keys!(hash, expected = [])
|
34
31
|
hash.keys.each do |key|
|
35
32
|
value = hash.delete(key)
|
36
33
|
key = key.to_s.downcase.to_sym
|
37
34
|
hash[key] = value
|
38
35
|
raise "Unexpected key: #{key}" unless expected.include?(key)
|
36
|
+
|
39
37
|
expected -= [key]
|
40
38
|
end
|
41
|
-
raise "Missing required keys: #{expected.join(
|
39
|
+
raise "Missing required keys: #{expected.join(", ")}" unless expected.empty?
|
40
|
+
|
42
41
|
hash
|
43
42
|
end
|
44
43
|
|
45
|
-
def self.included(cls)
|
46
|
-
def cls.inherited(base)
|
44
|
+
def self.included(cls) # rubocop:disable Metrics/PerceivedComplexity,Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength
|
45
|
+
def cls.inherited(base) # rubocop:disable Metrics/MethodLength,Lint/MissingSuper,Metrics/PerceivedComplexity
|
47
46
|
%i[detail documentation insert_text schema].each do |attr|
|
48
|
-
base.define_singleton_method(attr) do |value=nil|
|
47
|
+
base.define_singleton_method(attr) do |value = nil|
|
49
48
|
@middleware_class_attrs ||= {}
|
50
49
|
if value
|
51
50
|
@middleware_class_attrs[attr] = value
|
@@ -54,12 +53,12 @@ module Itsi
|
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
|
-
base.define_method(attr) do |
|
56
|
+
base.define_method(attr) do |_value = nil|
|
58
57
|
self.class.send(attr)
|
59
58
|
end
|
60
59
|
end
|
61
60
|
|
62
|
-
def base.schema(value=nil, &blk)
|
61
|
+
def base.schema(value = nil, &blk)
|
63
62
|
@middleware_class_attrs ||= {}
|
64
63
|
if blk
|
65
64
|
@middleware_class_attrs[:schema] = TypedStruct.new(&blk)
|
@@ -75,29 +74,30 @@ module Itsi
|
|
75
74
|
|
76
75
|
config_type = cls.name.split("::").last.downcase
|
77
76
|
|
78
|
-
cls.define_singleton_method("#{config_type}_name") do |name=self.name|
|
77
|
+
cls.define_singleton_method("#{config_type}_name") do |name = self.name|
|
79
78
|
@config_name ||= name.split("::").last.gsub(/([a-z])([A-Z])/, '\1_\2').downcase.to_sym
|
80
79
|
end
|
81
|
-
cls.define_method(:opt_name){ self.class.send("#{config_type}_name") }
|
82
|
-
cls.define_method(:location){ @location }
|
80
|
+
cls.define_method(:opt_name) { self.class.send("#{config_type}_name") }
|
81
|
+
cls.define_method(:location) { @location }
|
83
82
|
end
|
84
83
|
|
85
|
-
def initialize(location, params={})
|
84
|
+
def initialize(location, params = {})
|
86
85
|
if !self.class.ancestors.include?(Middleware) && !location.parent.nil?
|
87
86
|
raise "#{opt_name} must be set at the top level"
|
88
87
|
end
|
88
|
+
|
89
89
|
@location = location
|
90
|
-
@params = case
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
90
|
+
@params = case schema
|
91
|
+
when TypedStruct::Validation
|
92
|
+
schema.validate!(params)
|
93
|
+
when Array
|
94
|
+
default, validation = schema
|
95
|
+
params ? validation.validate!(params) : default
|
96
|
+
when nil
|
97
|
+
nil
|
98
|
+
else
|
99
|
+
schema.new(params).to_h
|
100
|
+
end
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
@@ -9,7 +9,7 @@ module Itsi
|
|
9
9
|
attr_reader :parent, :children, :middleware, :controller, :routes, :http_methods, :protocols,
|
10
10
|
:hosts, :ports, :extensions, :content_types, :accepts, :options
|
11
11
|
|
12
|
-
def self.evaluate(config = Itsi::Server::Config.config_file_path, &blk)
|
12
|
+
def self.evaluate(config = Itsi::Server::Config.config_file_path, &blk) # rubocop:disable Metrics/MethodLength
|
13
13
|
config = new(routes: ["/"]) do
|
14
14
|
if blk
|
15
15
|
instance_exec(&blk)
|
@@ -17,14 +17,14 @@ module Itsi
|
|
17
17
|
code = IO.read(config)
|
18
18
|
instance_eval(code, config.to_s, 1)
|
19
19
|
end
|
20
|
-
location("*"){}
|
20
|
+
location("*") {}
|
21
21
|
end
|
22
22
|
[config.options, config.errors]
|
23
|
-
rescue Exception => e
|
23
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
24
24
|
[{}, [[e, e.backtrace[0]]]]
|
25
25
|
end
|
26
26
|
|
27
|
-
def initialize(
|
27
|
+
def initialize( # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity
|
28
28
|
parent = nil,
|
29
29
|
routes: [],
|
30
30
|
methods: [],
|
@@ -52,17 +52,12 @@ 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
|
-
|
61
|
-
error = errors.first.first
|
62
|
-
error.set_backtrace(error.backtrace.drop_while{|r| r =~ /itsi\/server\/config/ })
|
63
|
-
raise error
|
64
|
-
end
|
65
|
-
flatten_routes
|
60
|
+
[flatten_routes, Config.errors_to_error_lines(errors)]
|
66
61
|
end
|
67
62
|
}
|
68
63
|
|
@@ -78,7 +73,7 @@ module Itsi
|
|
78
73
|
option_name = option.option_name
|
79
74
|
define_method(option_name) do |*args, **kwargs, &blk|
|
80
75
|
option.new(self, *args, **kwargs, &blk).build!
|
81
|
-
rescue => e
|
76
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
82
77
|
@errors << [e, caller[1]]
|
83
78
|
end
|
84
79
|
end
|
@@ -89,7 +84,7 @@ module Itsi
|
|
89
84
|
middleware.new(self, *args, **kwargs, &blk).build!
|
90
85
|
rescue Config::Endpoint::InvalidHandlerException => e
|
91
86
|
@errors << [e, "#{e.backtrace[0]}:in #{e.message}"]
|
92
|
-
rescue => e
|
87
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
93
88
|
@errors << [e, caller[1]]
|
94
89
|
end
|
95
90
|
end
|
@@ -99,7 +94,7 @@ module Itsi
|
|
99
94
|
@grpc_reflected_services.concat(handlers)
|
100
95
|
|
101
96
|
location("grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo",
|
102
|
-
|
97
|
+
"grpc.reflection.v1.ServerReflection/ServerReflectionInfo") do
|
103
98
|
@middleware[:app] = { preloader: lambda {
|
104
99
|
Itsi::Server::GrpcInterface.reflection_for(handlers)
|
105
100
|
}, request_type: "grpc" }
|
@@ -141,7 +136,7 @@ module Itsi
|
|
141
136
|
when Regexp
|
142
137
|
seg.source
|
143
138
|
else
|
144
|
-
parts = seg.split(
|
139
|
+
parts = seg.split("/")
|
145
140
|
parts.map do |part|
|
146
141
|
case part
|
147
142
|
when /^:([A-Za-z_]\w*)(?:\(([^)]*)\))?$/
|
@@ -184,11 +179,11 @@ module Itsi
|
|
184
179
|
|
185
180
|
chain.each do |n|
|
186
181
|
n.middleware.each do |k, v|
|
187
|
-
if v[:combine]
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
182
|
+
merged[k] = if v[:combine]
|
183
|
+
([merged[k] || []] + [v]).flatten
|
184
|
+
else
|
185
|
+
v
|
186
|
+
end
|
192
187
|
end
|
193
188
|
end
|
194
189
|
deep_stringify_keys(merged)
|
@@ -2,16 +2,20 @@ module Itsi
|
|
2
2
|
class Server
|
3
3
|
module KnownPaths
|
4
4
|
ALL = []
|
5
|
-
Dir.glob(File.join(__dir__,
|
6
|
-
method_name = file[/
|
7
|
-
|
8
|
-
|
5
|
+
Dir.glob(File.join(__dir__, "known_paths", "**", "*.txt")).each do |file|
|
6
|
+
method_name = file[%r{known_paths/(.*?)\.txt}, 1].gsub(/([a-z])([A-Z])/, "\\1_\\2")
|
7
|
+
.gsub(%r{-|\.|/}, "_")
|
8
|
+
.gsub(%r{(^|/)[0-9]}) do |match|
|
9
|
+
match.gsub(/\d/) do |digit|
|
10
|
+
%w[zero one two three four five six seven eight nine][digit.to_i]
|
11
|
+
end
|
12
|
+
end.downcase.to_sym
|
9
13
|
|
10
14
|
ALL << method_name
|
11
|
-
|
15
|
+
define_singleton_method(method_name) do
|
12
16
|
File.readlines(file).map do |s|
|
13
|
-
s.force_encoding(
|
14
|
-
s.valid_encoding? ? s.strip : s.encode(
|
17
|
+
s.force_encoding("UTF-8")
|
18
|
+
s.valid_encoding? ? s.strip : s.encode("UTF-8", invalid: :replace, undef: :replace, replace: "").strip
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
@@ -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
|
@@ -34,6 +34,19 @@ E.g.
|
|
34
34
|
auth_api_key .. other options.., error_response: 'forbidden'
|
35
35
|
```
|
36
36
|
|
37
|
+
## Example of built-in response
|
38
|
+
### HTML
|
39
|
+
{{< card title="Built-in error page" image="/error_page.jpg" subtitle="Default Itsi Error Page." method="Resize" options="10x q80 webp" >}}
|
40
|
+
### JSON
|
41
|
+
```json
|
42
|
+
{
|
43
|
+
"error": "Too Many Requests",
|
44
|
+
"message": "Too many requests within a limited time frame.",
|
45
|
+
"code": 429,
|
46
|
+
"status": "error"
|
47
|
+
}
|
48
|
+
```
|
49
|
+
|
37
50
|
## Override the error response
|
38
51
|
You may instead wish to completely override the error response. You can provide a status code, and a message in up to three
|
39
52
|
formats: plain-text, JSON, or HTML (at least one must be provided). Itsi will serve the appropriate type based on the `Accept` header of the incoming request, or fall back to the default if the requested type is not available.
|
@@ -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
|
@@ -20,6 +20,46 @@ It can auto-index directories for simple directory listings.
|
|
20
20
|
static_assets root_dir: "./"
|
21
21
|
```
|
22
22
|
|
23
|
+
### Directory Index
|
24
|
+
#### HTML
|
25
|
+
|
26
|
+
{{< card link="/" title="Static File Server" image="/directory_listing.jpg" subtitle="Static File Listing, Powered by Itsi." method="Resize" options="500x q80 webp" >}}
|
27
|
+
|
28
|
+
#### JSON
|
29
|
+
Directory indexes also support responding in JSON format. E.g.
|
30
|
+
|
31
|
+
`curl -H "Accept: application/json" http://0.0.0.0`
|
32
|
+
|
33
|
+
```json
|
34
|
+
{
|
35
|
+
"directory": ".",
|
36
|
+
"items": [
|
37
|
+
{
|
38
|
+
"is_dir": false,
|
39
|
+
"modified": "2025-04-22 04:21:43",
|
40
|
+
"name": "Gemfile",
|
41
|
+
"path": "Gemfile",
|
42
|
+
"size": "42 B"
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"is_dir": false,
|
46
|
+
"modified": "2025-04-22 04:21:48",
|
47
|
+
"name": "Gemfile.lock",
|
48
|
+
"path": "Gemfile%2Elock",
|
49
|
+
"size": "463 B"
|
50
|
+
},
|
51
|
+
{
|
52
|
+
"is_dir": false,
|
53
|
+
"modified": "2025-04-22 02:46:45",
|
54
|
+
"name": "Itsi.rb",
|
55
|
+
"path": "Itsi%2Erb",
|
56
|
+
"size": "80 B"
|
57
|
+
}
|
58
|
+
],
|
59
|
+
"title": "Directory listing for ."
|
60
|
+
}
|
61
|
+
```
|
62
|
+
|
23
63
|
## Configuration Options
|
24
64
|
|
25
65
|
|
@@ -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
|
|