From 48c56062034238ddcb33d3468d4aa1e0e6d598f0 Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Wed, 9 Sep 2026 15:23:29 +0800 Subject: [PATCH 1/5] chore: resync Gemfile.lock and appraisals --- Gemfile.lock | 2 +- gemfiles/rails50_rack22.gemfile | 1 + gemfiles/rails52_rack22.gemfile | 1 + gemfiles/rails60_rack22.gemfile | 1 + gemfiles/rails61_rack22.gemfile | 1 + gemfiles/rails70_rack22.gemfile | 2 +- gemfiles/rails71_rack22.gemfile | 2 +- gemfiles/rails72_rack22.gemfile | 1 + gemfiles/rails80_rack22.gemfile | 1 + 9 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e5c533f78..fde0e3c76 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -57,4 +57,4 @@ CHECKSUMS thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73 BUNDLED WITH - 2.7.2 + 2.6.3 diff --git a/gemfiles/rails50_rack22.gemfile b/gemfiles/rails50_rack22.gemfile index 5ebe0f45f..4a99d46e8 100644 --- a/gemfiles/rails50_rack22.gemfile +++ b/gemfiles/rails50_rack22.gemfile @@ -13,6 +13,7 @@ end group :development do gem "appraisal", require: nil + gem "rexml" end group :test do diff --git a/gemfiles/rails52_rack22.gemfile b/gemfiles/rails52_rack22.gemfile index 242654abf..8242bba4e 100644 --- a/gemfiles/rails52_rack22.gemfile +++ b/gemfiles/rails52_rack22.gemfile @@ -12,6 +12,7 @@ end group :development do gem "appraisal", require: nil + gem "rexml" end group :test do diff --git a/gemfiles/rails60_rack22.gemfile b/gemfiles/rails60_rack22.gemfile index b7d7b5c1d..e26305589 100644 --- a/gemfiles/rails60_rack22.gemfile +++ b/gemfiles/rails60_rack22.gemfile @@ -12,6 +12,7 @@ end group :development do gem "appraisal", require: nil + gem "rexml" end group :test do diff --git a/gemfiles/rails61_rack22.gemfile b/gemfiles/rails61_rack22.gemfile index 8009c3653..600306ab5 100644 --- a/gemfiles/rails61_rack22.gemfile +++ b/gemfiles/rails61_rack22.gemfile @@ -12,6 +12,7 @@ end group :development do gem "appraisal", require: nil + gem "rexml" end group :test do diff --git a/gemfiles/rails70_rack22.gemfile b/gemfiles/rails70_rack22.gemfile index b7b1c5dcd..27cf5e876 100644 --- a/gemfiles/rails70_rack22.gemfile +++ b/gemfiles/rails70_rack22.gemfile @@ -5,11 +5,11 @@ source "https://rubygems.org" group :default do gem "rack", "~> 2.2.0" gem "rails", "~> 7.0.0" - gem "rdoc", "!= 8.0.0" end group :development do gem "appraisal", require: nil + gem "rexml" end group :test do diff --git a/gemfiles/rails71_rack22.gemfile b/gemfiles/rails71_rack22.gemfile index d13b8451c..f9dce538e 100644 --- a/gemfiles/rails71_rack22.gemfile +++ b/gemfiles/rails71_rack22.gemfile @@ -5,11 +5,11 @@ source "https://rubygems.org" group :default do gem "rack", "~> 2.2.0" gem "rails", "~> 7.1.0" - gem "rdoc", "!= 8.0.0" end group :development do gem "appraisal", require: nil + gem "rexml" end group :test do diff --git a/gemfiles/rails72_rack22.gemfile b/gemfiles/rails72_rack22.gemfile index d70ca9e0d..5f93aaec8 100644 --- a/gemfiles/rails72_rack22.gemfile +++ b/gemfiles/rails72_rack22.gemfile @@ -9,6 +9,7 @@ end group :development do gem "appraisal", require: nil + gem "rexml" end group :test do diff --git a/gemfiles/rails80_rack22.gemfile b/gemfiles/rails80_rack22.gemfile index ce87d96c5..23603faa4 100644 --- a/gemfiles/rails80_rack22.gemfile +++ b/gemfiles/rails80_rack22.gemfile @@ -9,6 +9,7 @@ end group :development do gem "appraisal", require: nil + gem "rexml" end group :test do From 2c3a66f98fdb988b438610b0a70d6a2566f17fa7 Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Tue, 8 Sep 2026 14:51:37 +0800 Subject: [PATCH 2/5] test: add a Rack::Lint conformance spec (#480) Runs a Lint wrapped app through Rack::Handler::Servlet (both DefaultEnv and ServletEnv modes) and writes the response back through the servlet response path, so env construction, rack.input behavior and body close handling are validated against the loaded Rack version's SPEC. Also fixes the Rack 2.x arm's rack.version value to be Rack::VERSION (the protocol version Array the Rack 2 SPEC and Lint expect) (cherry picked from commit 84f2d49f2f120caf82d733e19eb1793bbc986641) --- CHANGELOG.md | 1 + .../ruby/rack/handler/servlet_lint_spec.rb | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/spec/ruby/rack/handler/servlet_lint_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a9b46b42..5178ae468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - fix: JRuby::Rack::Input#read(0) should return an empty string - fix: close the original body when ShowStatus replaces it - fix: detect Transfer-Encoding/Content-Length headers case-insensitively +- chore: revert `rack.version` value to be Rack 2.2 spec conformant ## 1.2.8 diff --git a/src/spec/ruby/rack/handler/servlet_lint_spec.rb b/src/spec/ruby/rack/handler/servlet_lint_spec.rb new file mode 100644 index 000000000..b3394f2ec --- /dev/null +++ b/src/spec/ruby/rack/handler/servlet_lint_spec.rb @@ -0,0 +1,75 @@ +#-- +# This source code is available under the MIT license. +# See the file LICENSE.txt for details. +#++ + +require File.expand_path('../../spec_helper', File.dirname(__FILE__)) + +require 'rack' +require 'rack/lint' +require 'uri' +require 'rack/handler/servlet' + +# End-to-end conformance check: the env built from the servlet request and the +# handling of the (Lint wrapped) response must satisfy the loaded Rack version's +# SPEC - Rack::Lint raises when either side of the contract is broken. +describe 'Rack::Handler::Servlet (Rack::Lint)' do + + before :each do + @servlet_context = mock_servlet_context + allow(@rack_context).to receive(:getServerInfo).and_return 'Mock-Container/1.0' + @servlet_request = org.springframework.mock.web.MockHttpServletRequest.new(@servlet_context) + @servlet_response = org.springframework.mock.web.MockHttpServletResponse.new + @servlet_env = org.jruby.rack.servlet.ServletRackEnvironment.new( + @servlet_request, @servlet_response, @rack_context + ) + + @servlet_request.setMethod('GET') + @servlet_request.setContextPath('') + @servlet_request.setRequestURI('/some/path') + @servlet_request.setQueryString('a=1&b=2') + @servlet_request.addParameter('a', '1') + @servlet_request.addParameter('b', '2') + @servlet_request.setServerName('lint.example.com') + @servlet_request.setServerPort(8080) + @servlet_request.setProtocol('HTTP/1.1') + @servlet_request.setRemoteAddr('127.0.0.1') + @servlet_request.setContent(''.to_java_bytes) + @servlet_request.addHeader('Accept', 'text/plain') + end + + let(:inner_app) do + lambda do |env| + env['rack.input'].read # exercises the Lint wrapped input contract + [ 200, { 'Content-Type' => 'text/plain', 'Content-Length' => '2' }, [ 'OK' ] ] + end + end + + let(:servlet) { Rack::Handler::Servlet.new Rack::Lint.new(inner_app) } + + shared_examples 'lint-compatible env' do + + it "creates a SPEC compatible env and writes the response" do + response = servlet.call(@servlet_env) + expect(response.to_java.getStatus).to eql 200 + + response_env = org.jruby.rack.servlet.ServletRackResponseEnvironment.new(@servlet_response) + response.to_java.respond(response_env) + expect(@servlet_response.getStatus).to eql 200 + expect(@servlet_response.getContentAsString).to eql 'OK' + end + + end + + describe 'with (default) env' do + it_behaves_like 'lint-compatible env' + end + + describe 'with servlet env' do + before { Rack::Handler::Servlet.env = :servlet } + after { Rack::Handler::Servlet.env = nil } + + it_behaves_like 'lint-compatible env' + end + +end From 0071da756d5251fc946628f3105edcd3c803fc99 Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Tue, 8 Sep 2026 13:56:54 +0800 Subject: [PATCH 3/5] fix: do not mutate (potentially frozen) header values when writing The newline-splitting header write path called chomp! on each yielded value - a frozen String ending in a newline raised FrozenError, and non-frozen app-owned header values were being modified in place. Co-Authored-By: Claude Fable 5 (cherry picked from commit 6e843d65c84eb6a3c1841ba6985bfb3efafb5e3c) --- CHANGELOG.md | 1 + src/main/java/org/jruby/rack/ext/Response.java | 12 ++++-------- src/spec/ruby/jruby/rack/response_spec.rb | 7 +++++++ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5178ae468..ffccccdf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - fix: close the original body when ShowStatus replaces it - fix: detect Transfer-Encoding/Content-Length headers case-insensitively - chore: revert `rack.version` value to be Rack 2.2 spec conformant +- fix: do not mutate (potentially frozen) response header values when writing ## 1.2.8 diff --git a/src/main/java/org/jruby/rack/ext/Response.java b/src/main/java/org/jruby/rack/ext/Response.java index 8c9bee154..c7aaed8c1 100644 --- a/src/main/java/org/jruby/rack/ext/Response.java +++ b/src/main/java/org/jruby/rack/ext/Response.java @@ -356,8 +356,7 @@ protected void writeStatus(final RackResponseEnvironment response) { } @JRubyMethod(name = "write_headers") - public IRubyObject write_headers(final ThreadContext context, final IRubyObject response) - throws IOException { + public IRubyObject write_headers(final ThreadContext context, final IRubyObject response) { writeHeaders(response.toJava(RackResponseEnvironment.class)); return context.nil; } @@ -406,7 +405,7 @@ public IRubyObject yield(ThreadContext context, IRubyObject[] args) { @Override public IRubyObject yield(ThreadContext context, IRubyObject value) { - value.callMethod(context, "chomp!", newLine); + value = value.callMethod(context, "chomp", newLine); response.addHeader(name, value.toString()); return value; } @@ -439,10 +438,10 @@ public IRubyObject write_body(final ThreadContext context, final IRubyObject res } protected void writeBody(final RackResponseEnvironment response) throws IOException { + final ThreadContext context = currentContext(); Channel bodyChannel = null; IRubyObject body = this.body; try { if ( body.respondsTo("call") && ! body.respondsTo("each") ) { - final ThreadContext context = currentContext(); final IRubyObject outputStream = JavaUtil.convertJavaToRuby(context.runtime, response.getOutputStream()); this.body.callMethod(context, "call", outputStream); @@ -450,7 +449,6 @@ protected void writeBody(final RackResponseEnvironment response) throws IOExcept } if ( body.respondsTo("to_path") ) { // send_file - final ThreadContext context = currentContext(); final IRubyObject path = body.callMethod(context, "to_path"); callMethod("send_file", path, JavaUtil.convertJavaToRuby(context.runtime, response)); return; @@ -465,7 +463,6 @@ protected void writeBody(final RackResponseEnvironment response) throws IOExcept bodyChannel = ((RubyIO) body).getChannel(); } else { - final ThreadContext context = currentContext(); final IRubyObject channel = body.callMethod(context, "to_channel"); bodyChannel = channel.toJava(Channel.class); } @@ -480,8 +477,6 @@ protected void writeBody(final RackResponseEnvironment response) throws IOExcept // NOTE: we no longer handle "to_inputstream" since in 1.7 "to_channel" covers those ... final OutputStream output = response.getOutputStream(); - final ThreadContext context = currentContext(); - IOException error = null; if ( doDechunk() ) { final IRubyObject output_stream = JavaUtil.convertJavaToRuby(context.runtime, output); callMethod(context, "write_body_dechunked", output_stream); @@ -706,6 +701,7 @@ private void transferChannel(final ReadableByteChannel channel, final OutputStre ThreadContext currentContext() { return getRuntime().getCurrentContext(); } + @SuppressWarnings("UnusedReturnValue") static IRubyObject invoke( final ThreadContext context, final IRubyObject self, final String method, final BlockBody body) { diff --git a/src/spec/ruby/jruby/rack/response_spec.rb b/src/spec/ruby/jruby/rack/response_spec.rb index eb44b8731..3310ac9f1 100644 --- a/src/spec/ruby/jruby/rack/response_spec.rb +++ b/src/spec/ruby/jruby/rack/response_spec.rb @@ -86,6 +86,13 @@ class << value response.write_headers(response_environment) end + it "writes frozen header values containing newlines without raising" do + response.to_java.getHeaders.update({ "Set-Cookie" => "cookie1\ncookie2".freeze }) + expect(servlet_response).to receive(:addHeader).with("Set-Cookie", "cookie1") + expect(servlet_response).to receive(:addHeader).with("Set-Cookie", "cookie2") + response.write_headers(response_environment) + end + it "adds an int header when values is a fixnum" do update_response_headers "Expires" => 0 expect(response_environment).to receive(:addIntHeader).with("Expires", 0) From 09768547e30c789e5f071aa5ec484c609b6640bc Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Wed, 9 Sep 2026 15:30:19 +0800 Subject: [PATCH 4/5] chore: remove dead code --- .../java/org/jruby/rack/util/IOHelpers.java | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/main/java/org/jruby/rack/util/IOHelpers.java b/src/main/java/org/jruby/rack/util/IOHelpers.java index eec8f4d9d..2db8d1072 100644 --- a/src/main/java/org/jruby/rack/util/IOHelpers.java +++ b/src/main/java/org/jruby/rack/util/IOHelpers.java @@ -73,24 +73,6 @@ public static String inputStreamToString(final InputStream stream) return str.toString(); } - public static ByteList readURL(final Ruby runtime, final URL url) - throws IOException { - if ( url == null ) return null; - - final int chunk = 256; - - final InputStream stream = url.openStream(); - final ByteList bytes = new ByteList(chunk); - - try { - while ( true ) bytes.append(stream, chunk); - } - catch (EOFException e) { /* read whole stream */ } - finally { stream.close(); } - - return bytes; - } - public static String rubyMagicCommentValue(final String script, final String prefix) throws IOException { if ( script == null ) return null; @@ -100,7 +82,7 @@ public static String rubyMagicCommentValue(final String script, final String pre String line, comment = null; Pattern pattern = null; while ( (line = reader.readLine()) != null ) { // we only support (magic) comments at the beginning : - if ( line.length() == 0 || line.charAt(0) != '#' ) break; + if (line.isEmpty() || line.charAt(0) != '#' ) break; if (pattern == null) { pattern = Pattern.compile(prefix + "\\s*(\\S+)"); From 9e5ee83fbeda96d2f609bda18a30ccdc8f9712d2 Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Wed, 9 Sep 2026 02:16:41 +0800 Subject: [PATCH 5/5] test: add Rack 2.2 / Rails 8.1 appraisal I could swear I thought Rails 8.1 didn't support Rack 2.2 when it was released... (cherry picked from commit d10e3c3ee53b61daa507616a7d670492a0d70dcd) --- .github/workflows/maven.yml | 5 ++ Appraisals | 1 + README.md | 2 +- gemfiles/rails81_rack22.gemfile | 19 +++++ src/spec/ruby/jruby/rack/integration_spec.rb | 4 + .../app/controllers/application_controller.rb | 4 + .../rails81/app/helpers/application_helper.rb | 2 + src/spec/stub/rails81/config/application.rb | 42 +++++++++++ src/spec/stub/rails81/config/boot.rb | 3 + .../stub/rails81/config/credentials.yml.enc | 1 + src/spec/stub/rails81/config/environment.rb | 5 ++ .../config/environments/development.rb | 42 +++++++++++ .../rails81/config/environments/production.rb | 73 +++++++++++++++++++ .../stub/rails81/config/environments/test.rb | 42 +++++++++++ .../initializers/content_security_policy.rb | 29 ++++++++ .../initializers/filter_parameter_logging.rb | 8 ++ .../config/initializers/inflections.rb | 16 ++++ src/spec/stub/rails81/config/locales/en.yml | 31 ++++++++ src/spec/stub/rails81/config/master.key | 1 + src/spec/stub/rails81/config/routes.rb | 14 ++++ src/spec/stub/rails81/public/robots.txt | 1 + 21 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 gemfiles/rails81_rack22.gemfile create mode 100644 src/spec/stub/rails81/app/controllers/application_controller.rb create mode 100644 src/spec/stub/rails81/app/helpers/application_helper.rb create mode 100644 src/spec/stub/rails81/config/application.rb create mode 100644 src/spec/stub/rails81/config/boot.rb create mode 100644 src/spec/stub/rails81/config/credentials.yml.enc create mode 100644 src/spec/stub/rails81/config/environment.rb create mode 100644 src/spec/stub/rails81/config/environments/development.rb create mode 100644 src/spec/stub/rails81/config/environments/production.rb create mode 100644 src/spec/stub/rails81/config/environments/test.rb create mode 100644 src/spec/stub/rails81/config/initializers/content_security_policy.rb create mode 100644 src/spec/stub/rails81/config/initializers/filter_parameter_logging.rb create mode 100644 src/spec/stub/rails81/config/initializers/inflections.rb create mode 100644 src/spec/stub/rails81/config/locales/en.yml create mode 100644 src/spec/stub/rails81/config/master.key create mode 100644 src/spec/stub/rails81/config/routes.rb create mode 100644 src/spec/stub/rails81/public/robots.txt diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 8b7a1fad0..8cbeb0286 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -73,6 +73,7 @@ jobs: 'rails71_rack22', 'rails72_rack22', 'rails80_rack22', + 'rails81_rack22', ] jruby_version: [ '9.3.15.0', '9.4.15.0', '10.0.6.0', '10.1.1.0' ] java_version: [ '8', '11', '17', '21', '25' ] @@ -99,6 +100,10 @@ jobs: jruby_version: '9.3.15.0' - appraisal: 'rails80_rack22' # Requires Ruby 3.4 compatibility, which JRuby 9.4 does not support jruby_version: '9.4.15.0' + - appraisal: 'rails81_rack22' # Requires Ruby 3.4 compatibility, which JRuby 9.3 does not support + jruby_version: '9.3.15.0' + - appraisal: 'rails81_rack22' # Requires Ruby 3.4 compatibility, which JRuby 9.4 does not support + jruby_version: '9.4.15.0' fail-fast: false env: diff --git a/Appraisals b/Appraisals index 70781847c..da0fa58af 100644 --- a/Appraisals +++ b/Appraisals @@ -11,6 +11,7 @@ version_spec = ->(prefix, desc) { "~> #{major_minor.call(prefix, desc)}.0" } "rails71" => {racks: %w[rack22]}, "rails72" => {racks: %w[rack22]}, "rails80" => {racks: %w[rack22]}, + "rails81" => {racks: %w[rack22]} }.each do |rails_desc, c| c[:racks].each do |rack_desc| diff --git a/README.md b/README.md index f0110749a..e3f43f12a 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ For more information on Rack, visit http://rack.github.io/. | JRuby-Rack Series | Status | Rack | JRuby | Java | Rails | Servlet API (min → mostly supported) | Notes | |----------------------------------------------------------------|---------------|-----------|------------|------|-----------|--------------------------------------|-------| -| [**1.2**](https://github.com/jruby/jruby-rack/tree/1.2-stable) | EOL @ 2026-09 | 2.2 | 9.3 → 10.1 | 8+ | 5.0 → 8.0 | 3.0 → 4.0 (Java EE 6 → 7) | | +| [**1.2**](https://github.com/jruby/jruby-rack/tree/1.2-stable) | EOL @ 2026-09 | 2.2 | 9.3 → 10.1 | 8+ | 5.0 → 8.1 | 3.0 → 4.0 (Java EE 6 → 7) | | | [**1.1**](https://github.com/jruby/jruby-rack/tree/1.1-stable) | EOL @ 2024-05 | 1.x → 2.2 | 1.6 → 9.4 | 6+ | 2.1 → 5.2 | 2.5 → 4.0 (Java EE 5 → 7) | | | [**1.0**](https://github.com/jruby/jruby-rack/tree/1.0.10) | EOL @ 2011-11 | 0.9 → 1.x | 1.1 → 1.9 | 5+ | 2.1 → 3.x | 2.5 (Java EE 5) | | diff --git a/gemfiles/rails81_rack22.gemfile b/gemfiles/rails81_rack22.gemfile new file mode 100644 index 000000000..9549db803 --- /dev/null +++ b/gemfiles/rails81_rack22.gemfile @@ -0,0 +1,19 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +group :default do + gem "rack", "~> 2.2.0" + gem "rails", "~> 8.1.0" +end + +group :development do + gem "appraisal", require: nil + gem "rexml" +end + +group :test do + gem "rake", "~> 13.4", require: nil + gem "rspec" + gem "logger" +end diff --git a/src/spec/ruby/jruby/rack/integration_spec.rb b/src/spec/ruby/jruby/rack/integration_spec.rb index c30982598..9f91fc939 100644 --- a/src/spec/ruby/jruby/rack/integration_spec.rb +++ b/src/spec/ruby/jruby/rack/integration_spec.rb @@ -225,6 +225,10 @@ it_should_behave_like 'a rails app' end + describe 'rails 8.1', lib: :rails81 do + it_should_behave_like 'a rails app' + end + def expect_to_have_monkey_patched_chunked @runtime.evalScriptlet "require 'rack/chunked'" script = %{ diff --git a/src/spec/stub/rails81/app/controllers/application_controller.rb b/src/spec/stub/rails81/app/controllers/application_controller.rb new file mode 100644 index 000000000..0d95db22b --- /dev/null +++ b/src/spec/stub/rails81/app/controllers/application_controller.rb @@ -0,0 +1,4 @@ +class ApplicationController < ActionController::Base + # Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has. + allow_browser versions: :modern +end diff --git a/src/spec/stub/rails81/app/helpers/application_helper.rb b/src/spec/stub/rails81/app/helpers/application_helper.rb new file mode 100644 index 000000000..de6be7945 --- /dev/null +++ b/src/spec/stub/rails81/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/src/spec/stub/rails81/config/application.rb b/src/spec/stub/rails81/config/application.rb new file mode 100644 index 000000000..bba537d7f --- /dev/null +++ b/src/spec/stub/rails81/config/application.rb @@ -0,0 +1,42 @@ +require_relative "boot" + +require "rails" +# Pick the frameworks you want: +require "active_model/railtie" +# require "active_job/railtie" +# require "active_record/railtie" +# require "active_storage/engine" +require "action_controller/railtie" +# require "action_mailer/railtie" +# require "action_mailbox/engine" +# require "action_text/engine" +require "action_view/railtie" +# require "action_cable/engine" +# require "rails/test_unit/railtie" + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module Rails81 + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 8.1 + + # Please, add to the `ignore` list any other `lib` subdirectories that do + # not contain `.rb` files, or that should not be reloaded or eager loaded. + # Common ones are `templates`, `generators`, or `middleware`, for example. + config.autoload_lib(ignore: %w[assets tasks]) + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") + + # Don't generate system test files. + config.generators.system_tests = nil + end +end diff --git a/src/spec/stub/rails81/config/boot.rb b/src/spec/stub/rails81/config/boot.rb new file mode 100644 index 000000000..282011619 --- /dev/null +++ b/src/spec/stub/rails81/config/boot.rb @@ -0,0 +1,3 @@ +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "bundler/setup" # Set up gems listed in the Gemfile. diff --git a/src/spec/stub/rails81/config/credentials.yml.enc b/src/spec/stub/rails81/config/credentials.yml.enc new file mode 100644 index 000000000..e67e3468f --- /dev/null +++ b/src/spec/stub/rails81/config/credentials.yml.enc @@ -0,0 +1 @@ +82NrCVblpkSw3wDVYHqQFkuTm4oS5bQt+rYDUmlei6JtoWvmkz/K1A81ysT3RXIojUAgbe2wo3zrl3dygSEmZCSV78wfDXJpBJi5fkVC84HQBJEBg0/8yFhZtDjvWG53X532RYnSVtAaPtPeqKS9F0uHNT7/G8Gkhfgu8JEg1oT1mlT4nT3VLExtH4QrXGBrvpWbFN6VzRIqFIO7Bk/tR92v6VCoAbl44j61pqEhW6SyDLb2PNGtW3o+Lq6RTTnsS9MOXXh/eNr4PZv97ghxbLSxcgzqXh6qBKsfZTTh30oxHRmv1yf1ur7hlopok1g4DcX5yK3Cul+ttkjYUoKdiSZ8cpZojQEqiMaRtvjVBGspHquqi9OuMtBlQaVxU1z3lGCdYnx1hqQDk6RnkBTE+Y7wbTGrjyQ1urKYXjw4bvu5WEh2n/UEHJsxrmg0v7yZZaOGESnfn+pbyWlbWfbA6fhH8ZguyqgzNiMh1TGU4Tqzvmgf/FAPQVNx--Jp0qmDUTnghki/m1--9Dp76qUD7YblOugS/mioww== \ No newline at end of file diff --git a/src/spec/stub/rails81/config/environment.rb b/src/spec/stub/rails81/config/environment.rb new file mode 100644 index 000000000..cac531577 --- /dev/null +++ b/src/spec/stub/rails81/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative "application" + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/src/spec/stub/rails81/config/environments/development.rb b/src/spec/stub/rails81/config/environments/development.rb new file mode 100644 index 000000000..f68dd3575 --- /dev/null +++ b/src/spec/stub/rails81/config/environments/development.rb @@ -0,0 +1,42 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Make code changes take effect immediately without server restart. + config.enable_reloading = true + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable server timing. + config.server_timing = true + + # Enable/disable Action Controller caching. By default Action Controller caching is disabled. + # Run rails dev:cache to toggle Action Controller caching. + if Rails.root.join("tmp/caching-dev.txt").exist? + config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true + config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" } + else + config.action_controller.perform_caching = false + end + + # Change to :null_store to avoid any caching. + config.cache_store = :memory_store + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + config.action_view.annotate_rendered_view_with_filenames = true + + # Raise error when a before_action's only/except options reference missing actions. + config.action_controller.raise_on_missing_callback_actions = true +end diff --git a/src/spec/stub/rails81/config/environments/production.rb b/src/spec/stub/rails81/config/environments/production.rb new file mode 100644 index 000000000..49ed6ab53 --- /dev/null +++ b/src/spec/stub/rails81/config/environments/production.rb @@ -0,0 +1,73 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.enable_reloading = false + + # Eager load code on boot for better performance and memory savings (ignored by Rake tasks). + config.eager_load = true + + # Full error reports are disabled. + config.consider_all_requests_local = false + + # Turn on fragment caching in view templates. + config.action_controller.perform_caching = true + + # Cache digest stamped assets for far-future expiry. + # Short cache for others: robots.txt, sitemap.xml, 404.html, etc. + config.public_file_server.headers = { + "cache-control" => lambda do |path, _| + if path.start_with?("/assets/") + # Files in /assets/ are expected to be fully immutable. + # If the content change the URL too. + "public, immutable, max-age=#{1.year.to_i}" + else + # For anything else we cache for 1 minute. + "public, max-age=#{1.minute.to_i}, stale-while-revalidate=#{5.minutes.to_i}" + end + end + } + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.asset_host = "http://assets.example.com" + + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + config.assume_ssl = true + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + config.force_ssl = true + + # Skip http-to-https redirect for the default health check endpoint. + # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } + + # Log to STDOUT with the current request id as a default log tag. + config.log_tags = [ :request_id ] + # config.logger = ActiveSupport::TaggedLogging.logger(STDOUT) + + # Change to "debug" to log everything (including potentially personally-identifiable information!). + config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") + + # Prevent health checks from clogging up the logs. + config.silence_healthcheck_path = "/up" + + # Don't log any deprecations. + config.active_support.report_deprecations = false + + # Replace the default in-process memory cache store with a durable alternative. + # config.cache_store = :mem_cache_store + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Enable DNS rebinding protection and other `Host` header attacks. + # config.hosts = [ + # "example.com", # Allow requests from example.com + # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` + # ] + # + # Skip DNS rebinding protection for the default health check endpoint. + # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } +end diff --git a/src/spec/stub/rails81/config/environments/test.rb b/src/spec/stub/rails81/config/environments/test.rb new file mode 100644 index 000000000..14bc29e06 --- /dev/null +++ b/src/spec/stub/rails81/config/environments/test.rb @@ -0,0 +1,42 @@ +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # While tests run files are not watched, reloading is not necessary. + config.enable_reloading = false + + # Eager loading loads your entire application. When running a single test locally, + # this is usually not necessary, and can slow down your test suite. However, it's + # recommended that you enable it in continuous integration systems to ensure eager + # loading is working properly before deploying your code. + config.eager_load = ENV["CI"].present? + + # Configure public file server for tests with cache-control for performance. + config.public_file_server.headers = { "cache-control" => "public, max-age=3600" } + + # Show full error reports. + config.consider_all_requests_local = true + config.cache_store = :null_store + + # Render exception templates for rescuable exceptions and raise for other exceptions. + config.action_dispatch.show_exceptions = :rescuable + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true + + # Raise error when a before_action's only/except options reference missing actions. + config.action_controller.raise_on_missing_callback_actions = true +end diff --git a/src/spec/stub/rails81/config/initializers/content_security_policy.rb b/src/spec/stub/rails81/config/initializers/content_security_policy.rb new file mode 100644 index 000000000..d51d71397 --- /dev/null +++ b/src/spec/stub/rails81/config/initializers/content_security_policy.rb @@ -0,0 +1,29 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy. +# See the Securing Rails Applications Guide for more information: +# https://guides.rubyonrails.org/security.html#content-security-policy-header + +# Rails.application.configure do +# config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end +# +# # Generate session nonces for permitted importmap, inline scripts, and inline styles. +# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } +# config.content_security_policy_nonce_directives = %w(script-src style-src) +# +# # Automatically add `nonce` to `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag` +# # if the corresponding directives are specified in `content_security_policy_nonce_directives`. +# # config.content_security_policy_nonce_auto = true +# +# # Report violations without enforcing the policy. +# # config.content_security_policy_report_only = true +# end diff --git a/src/spec/stub/rails81/config/initializers/filter_parameter_logging.rb b/src/spec/stub/rails81/config/initializers/filter_parameter_logging.rb new file mode 100644 index 000000000..c0b717f7e --- /dev/null +++ b/src/spec/stub/rails81/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. +# Use this to limit dissemination of sensitive information. +# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. +Rails.application.config.filter_parameters += [ + :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc +] diff --git a/src/spec/stub/rails81/config/initializers/inflections.rb b/src/spec/stub/rails81/config/initializers/inflections.rb new file mode 100644 index 000000000..3860f659e --- /dev/null +++ b/src/spec/stub/rails81/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym "RESTful" +# end diff --git a/src/spec/stub/rails81/config/locales/en.yml b/src/spec/stub/rails81/config/locales/en.yml new file mode 100644 index 000000000..6c349ae5e --- /dev/null +++ b/src/spec/stub/rails81/config/locales/en.yml @@ -0,0 +1,31 @@ +# Files in the config/locales directory are used for internationalization and +# are automatically loaded by Rails. If you want to use locales other than +# English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t "hello" +# +# In views, this is aliased to just `t`: +# +# <%= t("hello") %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# To learn more about the API, please read the Rails Internationalization guide +# at https://guides.rubyonrails.org/i18n.html. +# +# Be aware that YAML interprets the following case-insensitive strings as +# booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings +# must be quoted to be interpreted as strings. For example: +# +# en: +# "yes": yup +# enabled: "ON" + +en: + hello: "Hello world" diff --git a/src/spec/stub/rails81/config/master.key b/src/spec/stub/rails81/config/master.key new file mode 100644 index 000000000..e7883e7b5 --- /dev/null +++ b/src/spec/stub/rails81/config/master.key @@ -0,0 +1 @@ +c8efa0d2b5305bf19054185dc011f0f7 \ No newline at end of file diff --git a/src/spec/stub/rails81/config/routes.rb b/src/spec/stub/rails81/config/routes.rb new file mode 100644 index 000000000..48254e88e --- /dev/null +++ b/src/spec/stub/rails81/config/routes.rb @@ -0,0 +1,14 @@ +Rails.application.routes.draw do + # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html + + # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. + # Can be used by load balancers and uptime monitors to verify that the app is live. + get "up" => "rails/health#show", as: :rails_health_check + + # Render dynamic PWA files from app/views/pwa/* (remember to link manifest in application.html.erb) + # get "manifest" => "rails/pwa#manifest", as: :pwa_manifest + # get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker + + # Defines the root path route ("/") + # root "posts#index" +end diff --git a/src/spec/stub/rails81/public/robots.txt b/src/spec/stub/rails81/public/robots.txt new file mode 100644 index 000000000..c19f78ab6 --- /dev/null +++ b/src/spec/stub/rails81/public/robots.txt @@ -0,0 +1 @@ +# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file