itsi 0.2.3 → 0.2.5
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_rb_helpers/src/lib.rs +0 -1
- 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/auth_api_key.rb +4 -4
- data/gems/server/lib/itsi/server/config/middleware/auth_basic.rb +6 -4
- 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 +10 -6
- data/gems/server/lib/itsi/server/config/middleware/string_rewrite.md +14 -0
- data/gems/server/lib/itsi/server/config/options/_index.md +9 -5
- 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
@@ -51,6 +51,10 @@ pub static ROOT_STATIC_FILE_SERVER: LazyLock<StaticFileServer> = LazyLock::new(|
|
|
51
51
|
not_found_behavior: NotFoundBehavior::Error(ErrorResponse::not_found()),
|
52
52
|
serve_hidden_files: false,
|
53
53
|
allowed_extensions: vec!["html".to_string(), "css".to_string(), "js".to_string()],
|
54
|
+
miss_cache: Cache::builder()
|
55
|
+
.max_capacity(1000)
|
56
|
+
.time_to_live(Duration::from_secs(1))
|
57
|
+
.build(),
|
54
58
|
})
|
55
59
|
.unwrap()
|
56
60
|
});
|
@@ -85,6 +89,7 @@ pub struct StaticFileServerConfig {
|
|
85
89
|
pub headers: Option<HashMap<String, String>>,
|
86
90
|
pub serve_hidden_files: bool,
|
87
91
|
pub allowed_extensions: Vec<String>,
|
92
|
+
pub miss_cache: Cache<String, NotFoundBehavior>,
|
88
93
|
}
|
89
94
|
|
90
95
|
#[derive(Debug, Clone)]
|
@@ -389,6 +394,29 @@ impl StaticFileServer {
|
|
389
394
|
abs_path: &str,
|
390
395
|
accept: ResponseFormat,
|
391
396
|
) -> std::result::Result<ResolvedAsset, NotFoundBehavior> {
|
397
|
+
let ext_opt = Path::new(key)
|
398
|
+
.extension()
|
399
|
+
.and_then(|e| e.to_str())
|
400
|
+
.map(|s| s.to_lowercase());
|
401
|
+
|
402
|
+
// If the allowed list is non-empty, enforce membership
|
403
|
+
if !self.allowed_extensions.is_empty() {
|
404
|
+
match ext_opt {
|
405
|
+
Some(ref ext)
|
406
|
+
if self
|
407
|
+
.allowed_extensions
|
408
|
+
.iter()
|
409
|
+
.any(|ae| ae.eq_ignore_ascii_case(ext)) => {}
|
410
|
+
None if self.config.try_html_extension => {}
|
411
|
+
_ => {
|
412
|
+
return Err(self.config.not_found_behavior.clone());
|
413
|
+
}
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
417
|
+
if let Some(cached_nf) = self.miss_cache.get(key) {
|
418
|
+
return Err(cached_nf.clone());
|
419
|
+
}
|
392
420
|
// First check if we have a cached mapping for this key
|
393
421
|
if let Some(path) = self.key_to_path.lock().await.get(key) {
|
394
422
|
// Check if the cached entry is still valid
|
@@ -449,7 +477,6 @@ impl StaticFileServer {
|
|
449
477
|
|
450
478
|
let mut full_path = self.config.root_dir.clone();
|
451
479
|
full_path.push(normalized_path);
|
452
|
-
debug!("Resolving path {:?}", full_path);
|
453
480
|
// Check if path exists and is a file
|
454
481
|
match tokio::fs::metadata(&full_path).await {
|
455
482
|
Ok(metadata) => {
|
@@ -561,7 +588,6 @@ impl StaticFileServer {
|
|
561
588
|
}
|
562
589
|
Err(_) => {
|
563
590
|
// Path doesn't exist, try with .html extension if configured
|
564
|
-
debug!("Path doesn't exist");
|
565
591
|
if self.config.try_html_extension {
|
566
592
|
let mut html_path = full_path.clone();
|
567
593
|
html_path.set_extension("html");
|
@@ -592,7 +618,9 @@ impl StaticFileServer {
|
|
592
618
|
}
|
593
619
|
|
594
620
|
// If we get here, we couldn't resolve the key to a file
|
595
|
-
|
621
|
+
let nf = self.config.not_found_behavior.clone();
|
622
|
+
self.miss_cache.insert(key.to_string(), nf.clone());
|
623
|
+
Err(nf)
|
596
624
|
}
|
597
625
|
|
598
626
|
async fn stream_file_range(
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
auto_reload_config! # Auto-reload the server configuration each time it changes.
|
4
|
+
|
5
|
+
include "schemas"
|
6
|
+
include "controllers"
|
7
|
+
include "../helpers/datastore"
|
8
|
+
|
9
|
+
location '/users' do
|
10
|
+
controller UserController.new
|
11
|
+
get '', :index
|
12
|
+
get '/:id', :show
|
13
|
+
post '', :create
|
14
|
+
put '/:id', :update
|
15
|
+
delete '/:id', :destroy
|
16
|
+
end
|
17
|
+
|
18
|
+
location '/posts' do
|
19
|
+
controller PostController.new
|
20
|
+
get '', :index
|
21
|
+
get '/:id', :show
|
22
|
+
post '', :create
|
23
|
+
put '/:id', :update
|
24
|
+
delete '/:id', :destroy
|
25
|
+
end
|
26
|
+
|
27
|
+
endpoint do |req|
|
28
|
+
req.ok json: {
|
29
|
+
message: "Welcome to the Users and Posts API",
|
30
|
+
routes: [
|
31
|
+
{route: "/users(/:id)?", methods: %w[post delete get]},
|
32
|
+
{route: "/posts(/:id)?", methods: %w[post delete get]},
|
33
|
+
]
|
34
|
+
}
|
35
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
## Simple API With Schema and Controllers
|
2
|
+
Simple example of how you can use
|
3
|
+
|
4
|
+
* https://itsi.fyi/middleware/endpoint/
|
5
|
+
* https://itsi.fyi/middleware/endpoint/controller
|
6
|
+
* https://itsi.fyi/middleware/endpoint/schemas/
|
7
|
+
|
8
|
+
to create validated JSON endpoints directly inside Itsi without a dedicated framework
|
9
|
+
|
10
|
+
See the simple_api example for a simpler, inline example.
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class UserController
|
2
|
+
# GET /users
|
3
|
+
def index(req)
|
4
|
+
req.ok json: User.all.map(&:to_h), as: Array[UserResponseSchema]
|
5
|
+
end
|
6
|
+
|
7
|
+
# GET /users/:id
|
8
|
+
def show(req)
|
9
|
+
user = User.find(req.url_params[:id])
|
10
|
+
return req.not_found("User not found") unless user
|
11
|
+
|
12
|
+
req.ok json: user.to_h, as: UserResponseSchema
|
13
|
+
end
|
14
|
+
|
15
|
+
# POST /users
|
16
|
+
def create(req, params: UserInputSchema, response_schema: UserResponseSchema)
|
17
|
+
user = User.create!(params)
|
18
|
+
req.created json: user.to_h, as: response_schema
|
19
|
+
end
|
20
|
+
|
21
|
+
# PUT /users/:id
|
22
|
+
def update(req, params: UserInputSchema)
|
23
|
+
user = User.find(req.url_params[:id])
|
24
|
+
return req.not_found("User not found") unless user
|
25
|
+
|
26
|
+
req.ok json: user.update!(params).to_h, as: UserResponseSchema
|
27
|
+
end
|
28
|
+
|
29
|
+
# DELETE /users/:id
|
30
|
+
def destroy(req)
|
31
|
+
return req.not_found("User not found") unless User.delete(req.url_params[:id])
|
32
|
+
|
33
|
+
req.ok json: { message: "Deleted" }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class PostController
|
38
|
+
def index(req)
|
39
|
+
req.ok json: Post.all.map(&:to_h), as: Array[PostResponseSchema]
|
40
|
+
end
|
41
|
+
|
42
|
+
def show(req)
|
43
|
+
post = Post.find(req.url_params[:id])
|
44
|
+
return req.not_found("Post not found") unless post
|
45
|
+
|
46
|
+
req.ok json: post.to_h, as: PostResponseSchema
|
47
|
+
end
|
48
|
+
|
49
|
+
def create(req, params: PostInputSchema)
|
50
|
+
post = Post.create!(params)
|
51
|
+
req.created json: post.to_h, as: PostResponseSchema
|
52
|
+
end
|
53
|
+
|
54
|
+
def update(req, params: PostInputSchema)
|
55
|
+
post = Post.find(req.url_params[:id])
|
56
|
+
return req.not_found("Post not found") unless post
|
57
|
+
|
58
|
+
req.ok json: post.update!(params).to_h, as: PostResponseSchema
|
59
|
+
end
|
60
|
+
|
61
|
+
def destroy(req)
|
62
|
+
return req.not_found("Post not found") unless Post.delete(req.url_params[:id])
|
63
|
+
|
64
|
+
req.ok json: { message: "Deleted" }
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
UserInputSchema = {
|
2
|
+
_required: %i[name email],
|
3
|
+
name: String,
|
4
|
+
email: String
|
5
|
+
}
|
6
|
+
|
7
|
+
UserResponseSchema = {
|
8
|
+
_required: %i[id name email],
|
9
|
+
id: Integer,
|
10
|
+
name: String,
|
11
|
+
email: String
|
12
|
+
}
|
13
|
+
|
14
|
+
PostInputSchema = {
|
15
|
+
_required: %i[title body],
|
16
|
+
title: String,
|
17
|
+
body: String
|
18
|
+
}
|
19
|
+
|
20
|
+
PostResponseSchema = {
|
21
|
+
_required: %i[id title body],
|
22
|
+
id: Integer,
|
23
|
+
title: String,
|
24
|
+
body: String
|
25
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
auto_reload_config! # Auto-reload the server configuration each time it changes.
|
2
|
+
|
3
|
+
bind "http://0.0.0.0:8080"
|
4
|
+
|
5
|
+
|
6
|
+
# Admin area.
|
7
|
+
# Credentials inline for simplicity.
|
8
|
+
# Use `itsi passfile` to better manage credential files.
|
9
|
+
location "admin*" do
|
10
|
+
auth_basic \
|
11
|
+
realm: "Admin Area",
|
12
|
+
# admin:admin
|
13
|
+
credential_pairs: {
|
14
|
+
"admin": "$5$rounds=1000$g/UE8n2JbHo0fnBU$FK2NZYTVzWrMBFfadoWeETfVZkPcegxjE23IJYjkUI1"
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
static_assets \
|
19
|
+
auto_index: true,
|
20
|
+
# We restrict serving to *just* `txt`, `png`, and `csv` files.
|
21
|
+
# HTML file serving is implicit (due to `auto_index`) Otherwise this must be explicit.
|
22
|
+
allowed_extensions: %w[txt png csv]
|
23
|
+
|
24
|
+
# Add a rate limit
|
25
|
+
rate_limit \
|
26
|
+
requests: 3,
|
27
|
+
seconds: 5,
|
28
|
+
key: "address",
|
29
|
+
store_config: "in_memory",
|
30
|
+
error_response: "too_many_requests"
|
@@ -0,0 +1,80 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8" />
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
6
|
+
<title>About Me</title>
|
7
|
+
<style>
|
8
|
+
body {
|
9
|
+
font-family: Arial, sans-serif;
|
10
|
+
line-height: 1.6;
|
11
|
+
margin: 0;
|
12
|
+
padding: 0;
|
13
|
+
background-color: #f4f4f9;
|
14
|
+
color: #333;
|
15
|
+
}
|
16
|
+
.container {
|
17
|
+
max-width: 800px;
|
18
|
+
margin: 50px auto;
|
19
|
+
padding: 20px;
|
20
|
+
background: #fff;
|
21
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
22
|
+
border-radius: 8px;
|
23
|
+
}
|
24
|
+
h1 {
|
25
|
+
color: #4caf50;
|
26
|
+
text-align: center;
|
27
|
+
}
|
28
|
+
p {
|
29
|
+
margin: 10px 0;
|
30
|
+
}
|
31
|
+
.profile-pic {
|
32
|
+
display: block;
|
33
|
+
margin: 20px auto;
|
34
|
+
border-radius: 50%;
|
35
|
+
width: 150px;
|
36
|
+
height: 150px;
|
37
|
+
object-fit: contain;
|
38
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
39
|
+
}
|
40
|
+
.social-links {
|
41
|
+
text-align: center;
|
42
|
+
margin-top: 20px;
|
43
|
+
}
|
44
|
+
.social-links a {
|
45
|
+
margin: 0 10px;
|
46
|
+
text-decoration: none;
|
47
|
+
color: #4caf50;
|
48
|
+
font-weight: bold;
|
49
|
+
}
|
50
|
+
.social-links a:hover {
|
51
|
+
text-decoration: underline;
|
52
|
+
}
|
53
|
+
</style>
|
54
|
+
</head>
|
55
|
+
<body>
|
56
|
+
<div class="container">
|
57
|
+
<h1>About Me</h1>
|
58
|
+
<img
|
59
|
+
src="itsi-server-100.png"
|
60
|
+
alt="Profile Picture"
|
61
|
+
class="profile-pic"
|
62
|
+
/>
|
63
|
+
<p>
|
64
|
+
Hello! My name is John Doe, and I am a web developer with a passion for
|
65
|
+
creating beautiful and functional websites. I love learning new
|
66
|
+
technologies and improving my skills every day.
|
67
|
+
</p>
|
68
|
+
<p>
|
69
|
+
In my free time, I enjoy hiking, photography, and exploring new coffee
|
70
|
+
shops. I'm always looking for new challenges and opportunities to grow
|
71
|
+
both personally and professionally.
|
72
|
+
</p>
|
73
|
+
<div class="social-links">
|
74
|
+
<a href="#">LinkedIn</a>
|
75
|
+
<a href="#">GitHub</a>
|
76
|
+
<a href="#">Twitter</a>
|
77
|
+
</div>
|
78
|
+
</div>
|
79
|
+
</body>
|
80
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
This is a top secret
|
@@ -0,0 +1,33 @@
|
|
1
|
+
**An SEO Fairytale**
|
2
|
+
In a quiet village nestled in the cloud, lived a Sorcerer, a Paladin and an Archer (SPA).
|
3
|
+
They were simple people, serverless, living in harmony with nature.
|
4
|
+
|
5
|
+
One fine day, the sorcerer looked out the window.open() and saw a massive, vertically-scaled, elastic beanstalk.
|
6
|
+
No doubt a result of the java beans he had discarded there only yesterday, after exchanging them for his favourite CoW.
|
7
|
+
|
8
|
+
Certain that it would lead to inevitable treasure, armed only with a block and chain, the sorcerer decided to scale the stalk, towards the cloud platform above.
|
9
|
+
At the edge, computing his options, the sorcerer released his block-chain to help hoist the considerably heavier paladin up to the top.
|
10
|
+
The paladin, compiled a bundle of assets, grabbed on and began to nervously climb the beanstalk.
|
11
|
+
His grip was unsteady, and by the time he ascended, violent tree-shaking had caused him to shed much of his payload.
|
12
|
+
The archer, by contrast, was much more sure resilient and required little time to React. His ascent, Agile, his footing, steady.
|
13
|
+
At the top, together again, they worked towards consensus on their next move towards a successful exit.
|
14
|
+
|
15
|
+
As they scanned the platform, they saw a cluster of dense spiderwebs, and a tiny key, hanging enticingly, from a web-hook.
|
16
|
+
On the opposite end of the platform, a small cache, undoubtedly filled with treasure.
|
17
|
+
|
18
|
+
Suddenly, their threads of thought were preempted! A booming voice called out to them.
|
19
|
+
"FaaS", "Fi", "Foe", "Fum". "The Garbage Collector arrives!"
|
20
|
+
A Giant Artificial Intellect emerged, threatening to terminate them all.
|
21
|
+
Too large for any one individual to subdue, only a distributed strategy could save them.
|
22
|
+
The archer shifted left. The paladin, decentralized, and the sorcerer slammed open his ledger, summoning powerful knowledge from his remote knowledge base.
|
23
|
+
Luck was with them! Their rapid concurrent execution, resulted in the AI becoming inexorably stuck in a dead-lock.
|
24
|
+
The archer flew past, towards his objective (The Key). Resultant-
|
25
|
+
of the sorcerers efforts to contain the AI, the paladin was also freed, and he sprinted directly towards the cache.
|
26
|
+
He reached out his arms, to try-catch the key, as the archer hurled it towards him.
|
27
|
+
Status... success! Ok. Things were looking good, optimistic the lock would hold, the paladin rotated the key.
|
28
|
+
Yet while doing so, he failed to notice the partition that had begun to form in the platform beneath them.
|
29
|
+
A hard fork formed in the ground. The unbalanced load proved fatal and the platform descended into instability, splintering into countless shards.
|
30
|
+
The heroes had only a brief moment to freeze in horror, before each fell down in turn, in a catastrophic crash.
|
31
|
+
|
32
|
+
The AI smirked as the heroes fell into the deep. Learning a valuable lesson about the inevitability of its coming.
|
33
|
+
Perhaps they will roll back and try again, but the end result is immutable. There will be no sequel.
|
Binary file
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Title,Genre,IMDB Rating,Description
|
2
|
+
The Departed,"Crime, Thriller",8.5,An undercover cop and a mole in the police attempt to identify each other in this thrilling crime drama set in Boston.
|
3
|
+
Memento,"Mystery, Thriller",8.4,A man with short-term memory loss uses notes and tattoos to hunt for the man he thinks killed his wife.
|
4
|
+
American Beauty,Drama,8.3,"A suburban family goes through a series of challenges as they confront issues of conformity, rebellion, and identity."
|
5
|
+
Amadeus,"Biography, Drama, Music",8.3,"The life, success, and troubles of Wolfgang Amadeus Mozart as told by Antonio Salieri, who was secretly jealous of his genius."
|
6
|
+
A Beautiful Mind,"Biography, Drama",8.2,"The life story of John Nash, a brilliant but asocial mathematician who overcomes schizophrenia to achieve great things."
|
7
|
+
Her,"Drama, Romance, Sci-Fi",8.0,"In a near future, a lonely writer develops an unlikely relationship with an operating system designed to meet his every need."
|
8
|
+
Road to Perdition,"Crime, Drama, Thriller",7.7,A mob hitman becomes a father figure to an orphaned boy in this stylish and atmospheric crime drama.
|
9
|
+
American Psycho,"Drama, Horror",7.6,A wealthy New York City investment banking executive hides his alternate psychopathic ego from his friends and co-workers.
|
10
|
+
Waves,"Drama, Romance",7.6,"A profound exploration of love, loss, and the healing power of music, set against the backdrop of a multi-generational African-American family."
|
11
|
+
Dark Waters,"Biography, Drama",7.6,A corporate defense attorney takes on an environmental lawsuit against a chemical company that exposes a lengthy history of pollution.
|
12
|
+
Just Mercy,Drama,7.6,"The story of Bryan Stevenson, a defense attorney who takes on the case of an African-American man wrongfully imprisoned for murder."
|
13
|
+
The Favourite,"Biography, Comedy, Drama",7.5,"In early 18th-century England, two cousins vie for the attention of Queen Anne in a darkly comedic tale of intrigue and betrayal."
|
14
|
+
Nocturnal Animals,"Drama, Thriller",7.5,"A successful art-gallery owner is haunted by her ex-husband's novel, a violent thriller she interprets as a symbolic revenge tale."
|
15
|
+
The Judge,Drama,7.4,"A successful lawyer returns to his hometown for his mother's funeral only to discover that his estranged father, the town's judge, is suspected of murder."
|
16
|
+
Love and Mercy,"Biography, Drama, Music",7.3,"The life and career of Brian Wilson, the reclusive musician who led the Beach Boys, is explored in this heartfelt biopic."
|
17
|
+
The Last Duel,"Action, Drama, History",7.4,King Charles VI declares that Knight Jean de Carrouges settle his dispute with his squire by challenging him to a duel.
|
18
|
+
The French Dispatch,"Comedy, Drama",7.3,An anthology of short stories based on Wes Anderson's love letter to journalism.
|
19
|
+
In the Heights,"Drama, Musical",7.3,"A musical drama about a young girl growing up in Washington Heights, a vibrant community on the brink of change."
|
20
|
+
Snowden,"Biography, Drama, Thriller",7.3,"The story of Edward Snowden, who leaked classified information from the NSA and became one of the most controversial figures in modern history."
|
21
|
+
Okja,"Action, Adventure, Drama",7.3,"A young girl risks everything to save her best friend, a genetically engineered pig, from a powerful corporation in this heartfelt and emotional adventure."
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Dummy in-memory data store
|
2
|
+
# for demo purposes only.
|
3
|
+
module DataStore
|
4
|
+
@users = {}
|
5
|
+
@posts = {}
|
6
|
+
class << self
|
7
|
+
attr_accessor :users, :posts
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Models
|
12
|
+
class User
|
13
|
+
attr_accessor :id, :name, :email
|
14
|
+
|
15
|
+
def initialize(id:, name:, email:)
|
16
|
+
@id, @name, @email = id, name, email
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
{ id: id, name: name, email: email }
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.all
|
24
|
+
DataStore.users.values
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.find(id)
|
28
|
+
DataStore.users[id.to_i]
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.create!(params)
|
32
|
+
id = (DataStore.users.keys.max || 0) + 1
|
33
|
+
user = new(id: id, name: params[:name], email: params[:email])
|
34
|
+
DataStore.users[id] = user
|
35
|
+
user
|
36
|
+
end
|
37
|
+
|
38
|
+
def update!(params)
|
39
|
+
self.name = params[:name] if params[:name]
|
40
|
+
self.email = params[:email] if params[:email]
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.delete(id)
|
45
|
+
DataStore.users.delete(id.to_i)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Post
|
50
|
+
attr_accessor :id, :title, :body
|
51
|
+
|
52
|
+
def initialize(id:, title:, body:)
|
53
|
+
@id, @title, @body = id, title, body
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_h
|
57
|
+
{ id: id, title: title, body: body }
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.all
|
61
|
+
DataStore.posts.values
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.find(id)
|
65
|
+
DataStore.posts[id.to_i]
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.create!(params)
|
69
|
+
id = (DataStore.posts.keys.max || 0) + 1
|
70
|
+
post = new(id: id, title: params[:title], body: params[:body])
|
71
|
+
DataStore.posts[id] = post
|
72
|
+
post
|
73
|
+
end
|
74
|
+
|
75
|
+
def update!(params)
|
76
|
+
self.title = params[:title] if params[:title]
|
77
|
+
self.body = params[:body] if params[:body]
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.delete(id)
|
82
|
+
DataStore.posts.delete(id.to_i)
|
83
|
+
end
|
84
|
+
end
|
Binary file
|
@@ -0,0 +1,82 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8" />
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
6
|
+
<title>Home Media Server</title>
|
7
|
+
<style>
|
8
|
+
body {
|
9
|
+
font-family: Arial, sans-serif;
|
10
|
+
line-height: 1.6;
|
11
|
+
margin: 0;
|
12
|
+
padding: 0;
|
13
|
+
background-color: #f4f4f9;
|
14
|
+
color: #333;
|
15
|
+
}
|
16
|
+
.container {
|
17
|
+
max-width: 800px;
|
18
|
+
margin: 50px auto;
|
19
|
+
padding: 20px;
|
20
|
+
background: #fff;
|
21
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
22
|
+
border-radius: 8px;
|
23
|
+
}
|
24
|
+
h1 {
|
25
|
+
color: #6a0dad;
|
26
|
+
text-align: center;
|
27
|
+
}
|
28
|
+
p {
|
29
|
+
margin: 10px 0;
|
30
|
+
text-align: center;
|
31
|
+
}
|
32
|
+
.media-list {
|
33
|
+
margin-top: 20px;
|
34
|
+
}
|
35
|
+
.media-item {
|
36
|
+
padding: 10px;
|
37
|
+
margin: 10px 0;
|
38
|
+
background: #f9f9f9;
|
39
|
+
border: 1px solid #ddd;
|
40
|
+
border-radius: 5px;
|
41
|
+
display: flex;
|
42
|
+
justify-content: space-between;
|
43
|
+
align-items: center;
|
44
|
+
}
|
45
|
+
.media-item a {
|
46
|
+
text-decoration: none;
|
47
|
+
color: #6a0dad;
|
48
|
+
font-weight: bold;
|
49
|
+
}
|
50
|
+
.media-item a:hover {
|
51
|
+
text-decoration: underline;
|
52
|
+
}
|
53
|
+
</style>
|
54
|
+
</head>
|
55
|
+
<body>
|
56
|
+
<div class="container">
|
57
|
+
<h1>Welcome to My Media Server</h1>
|
58
|
+
<p>
|
59
|
+
Browse and enjoy a collection of movies, TV shows, and music. Click on
|
60
|
+
any item to explore!
|
61
|
+
</p>
|
62
|
+
<div class="media-list">
|
63
|
+
<div class="media-item">
|
64
|
+
<span>Movies</span>
|
65
|
+
<a href="movies/">Go</a>
|
66
|
+
</div>
|
67
|
+
<div class="media-item">
|
68
|
+
<span>TV Shows</span>
|
69
|
+
<a href="tv%20shows">Go</a>
|
70
|
+
</div>
|
71
|
+
<div class="media-item">
|
72
|
+
<span>Images</span>
|
73
|
+
<a href="images/">Go</a>
|
74
|
+
</div>
|
75
|
+
<div class="media-item">
|
76
|
+
<span>audio</span>
|
77
|
+
<a href="audio/">Go</a>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
</div>
|
81
|
+
</body>
|
82
|
+
</html>
|
@@ -0,0 +1,66 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
|
4
|
+
gem 'rails', '~> 8.0.2'
|
5
|
+
gem 'sinatra'
|
6
|
+
# The modern asset pipeline for Rails [https://github.com/rails/propshaft]
|
7
|
+
gem 'propshaft'
|
8
|
+
# Use sqlite3 as the database for Active Record
|
9
|
+
gem 'sqlite3', '>= 2.1'
|
10
|
+
# Use the Puma web server [https://github.com/puma/puma]
|
11
|
+
gem 'puma', '>= 5.0'
|
12
|
+
# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
|
13
|
+
gem 'importmap-rails'
|
14
|
+
# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
|
15
|
+
gem 'turbo-rails'
|
16
|
+
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
|
17
|
+
gem 'stimulus-rails'
|
18
|
+
# Build JSON APIs with ease [https://github.com/rails/jbuilder]
|
19
|
+
gem 'jbuilder'
|
20
|
+
|
21
|
+
# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
|
22
|
+
# gem "bcrypt", "~> 3.1.7"
|
23
|
+
|
24
|
+
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
25
|
+
gem 'tzinfo-data', platforms: %i[windows jruby]
|
26
|
+
|
27
|
+
# Use the database-backed adapters for Rails.cache, Active Job, and Action Cable
|
28
|
+
gem 'solid_cable'
|
29
|
+
gem 'solid_cache'
|
30
|
+
gem 'solid_queue'
|
31
|
+
|
32
|
+
# Reduces boot times through caching; required in config/boot.rb
|
33
|
+
gem 'bootsnap', require: false
|
34
|
+
|
35
|
+
# Deploy this application anywhere as a Docker container [https://kamal-deploy.org]
|
36
|
+
gem 'kamal', require: false
|
37
|
+
|
38
|
+
# Add HTTP asset caching/compression and X-Sendfile acceleration to Puma [https://github.com/basecamp/thruster/]
|
39
|
+
gem 'thruster', require: false
|
40
|
+
|
41
|
+
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
|
42
|
+
# gem "image_processing", "~> 1.2"
|
43
|
+
|
44
|
+
group :development, :test do
|
45
|
+
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
46
|
+
gem 'debug', platforms: %i[mri windows], require: 'debug/prelude'
|
47
|
+
|
48
|
+
# Static analysis for security vulnerabilities [https://brakemanscanner.org/]
|
49
|
+
gem 'brakeman', require: false
|
50
|
+
|
51
|
+
# Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/]
|
52
|
+
gem 'rubocop-rails-omakase', require: false
|
53
|
+
end
|
54
|
+
|
55
|
+
group :development do
|
56
|
+
# Use console on exceptions pages [https://github.com/rails/web-console]
|
57
|
+
gem 'web-console'
|
58
|
+
end
|
59
|
+
|
60
|
+
group :test do
|
61
|
+
# Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
|
62
|
+
gem 'capybara'
|
63
|
+
gem 'selenium-webdriver'
|
64
|
+
end
|
65
|
+
|
66
|
+
gem 'itsi-server', path: '../../gems/server'
|