diff --git a/lib/utopia/controller/rewrite.rb b/lib/utopia/controller/rewrite.rb index 56818aa8..a18ab2b4 100644 --- a/lib/utopia/controller/rewrite.rb +++ b/lib/utopia/controller/rewrite.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2015-2025, by Samuel Williams. +# Copyright, 2015-2026, by Samuel Williams. require_relative "../http" require_relative "../path/matcher" @@ -48,6 +48,8 @@ def initialize(patterns, block) # Freeze this object and its internal state. # @returns [self] This object. def freeze + return self if frozen? + @matcher.freeze @block.freeze diff --git a/test/utopia/content.rb b/test/utopia/content.rb index 2eed7af6..dfe9f488 100755 --- a/test/utopia/content.rb +++ b/test/utopia/content.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2012-2025, by Samuel Williams. +# Copyright, 2012-2026, by Samuel Williams. require "sus/fixtures/protocol/http/middleware_context" require "utopia/application" @@ -10,6 +10,28 @@ describe Utopia::Content do include Sus::Fixtures::Protocol::HTTP::MiddlewareContext + it "freezes its configuration" do + root = +File.expand_path(".content", __dir__) + namespaces = { + Utopia::Content::Middleware::CONTENT_NAMESPACE => Object.new, + Utopia::Content::Middleware::RELATIVE_NAMESPACE => Object.new, + Utopia::Content::Middleware::UTOPIA_NAMESPACE => Object.new, + } + middleware = Utopia::Content::Middleware.new( + Protocol::HTTP::Middleware::NotFound, + root: root, + namespaces: namespaces, + ) + + expect(middleware.freeze).to be_equal(middleware) + expect(middleware).to be(:frozen?) + expect(middleware.freeze).to be_equal(middleware) + + expect(root).to be(:frozen?) + expect(namespaces).to be(:frozen?) + namespaces.each_value{|namespace| expect(namespace).to be(:frozen?)} + end + let(:middleware) do root = File.expand_path(".content", __dir__) diff --git a/test/utopia/controller/middleware.rb b/test/utopia/controller/middleware.rb index 2db0c79e..9a6050ee 100755 --- a/test/utopia/controller/middleware.rb +++ b/test/utopia/controller/middleware.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2013-2025, by Samuel Williams. +# Copyright, 2013-2026, by Samuel Williams. require "sus/fixtures/protocol/http/middleware_context" require "utopia/application" @@ -10,6 +10,23 @@ describe Utopia::Controller do include Sus::Fixtures::Protocol::HTTP::MiddlewareContext + it "freezes its configuration" do + root = +File.expand_path(".middleware", __dir__) + base = Class.new(Utopia::Controller::Base) + middleware = Utopia::Controller::Middleware.new( + Protocol::HTTP::Middleware::NotFound, + root: root, + base: base, + ) + + expect(middleware.freeze).to be_equal(middleware) + expect(middleware).to be(:frozen?) + expect(middleware.freeze).to be_equal(middleware) + + expect(root).to be(:frozen?) + expect(base).to be(:frozen?) + end + let(:middleware) do root = File.expand_path(".middleware", __dir__) diff --git a/test/utopia/controller/rewrite.rb b/test/utopia/controller/rewrite.rb index b0fe920c..f8f555a2 100644 --- a/test/utopia/controller/rewrite.rb +++ b/test/utopia/controller/rewrite.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2015-2025, by Samuel Williams. +# Copyright, 2015-2026, by Samuel Williams. require "utopia/controller" require "utopia/request" @@ -38,6 +38,18 @@ def mock_request(path) return request, request.path end + it "freezes extraction rules" do + callback = proc{} + rule = Utopia::Controller::Rewrite::ExtractPrefixRule.new({id: Integer}, callback) + + expect(rule.freeze).to be_equal(rule) + expect(rule).to be(:frozen?) + expect(rule.freeze).to be_equal(rule) + + expect(rule.instance_variable_get(:@matcher)).to be(:frozen?) + expect(callback).to be(:frozen?) + end + it "should match path prefix and extract parameters" do request, path = mock_request("/10/summary/20/edit") relative_path = path - controller.class.uri_path diff --git a/test/utopia/exceptions/handler.rb b/test/utopia/exceptions/handler.rb index 77d008bb..8c948206 100644 --- a/test/utopia/exceptions/handler.rb +++ b/test/utopia/exceptions/handler.rb @@ -20,6 +20,16 @@ end end + it "freezes its configuration" do + location = +"/exception" + middleware = subject.new(Protocol::HTTP::Middleware::NotFound, location) + + expect(middleware.freeze).to be_equal(middleware) + expect(middleware).to be(:frozen?) + expect(middleware.freeze).to be_equal(middleware) + expect(location).to be(:frozen?) + end + it "should successfully call the controller method" do # This request will raise an exception, and then redirect to the /exception url which will fail again, and cause a fatal error. client.get "/blow?fatal=true" diff --git a/test/utopia/exceptions/mailer.rb b/test/utopia/exceptions/mailer.rb index 7c07705c..704c3e92 100644 --- a/test/utopia/exceptions/mailer.rb +++ b/test/utopia/exceptions/mailer.rb @@ -29,6 +29,29 @@ def before super end + it "freezes its configuration" do + to = +"postmaster@example.com" + from = +"utopia@example.com" + template = +"%{exception}" + delivery_method = [:test, {}] + middleware = subject.new( + Protocol::HTTP::Middleware::NotFound, + to: to, + from: from, + subject: template, + delivery_method: delivery_method, + ) + + expect(middleware.freeze).to be_equal(middleware) + expect(middleware).to be(:frozen?) + expect(middleware.freeze).to be_equal(middleware) + + expect(to).to be(:frozen?) + expect(from).to be(:frozen?) + expect(template).to be(:frozen?) + expect(delivery_method).to be(:frozen?) + end + it "should send an email to report the failure" do client.headers["accept"] = "text/plain" diff --git a/test/utopia/localization.rb b/test/utopia/localization.rb index 47a6f1e7..dd8fda3a 100755 --- a/test/utopia/localization.rb +++ b/test/utopia/localization.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2014-2025, by Samuel Williams. +# Copyright, 2014-2026, by Samuel Williams. require "sus/fixtures/protocol/http/middleware_context" require "utopia/application" @@ -13,6 +13,31 @@ describe Utopia::Localization do include Sus::Fixtures::Protocol::HTTP::MiddlewareContext + it "freezes its configuration" do + default_locale = +"en" + default_locales = [default_locale, nil] + hosts = {/example\.com$/ => default_locale} + ignore = ["/health"] + middleware = Utopia::Localization::Middleware.new( + Protocol::HTTP::Middleware::NotFound, + locales: ["en"], + default_locale: default_locale, + default_locales: default_locales, + hosts: hosts, + ignore: ignore, + ) + + expect(middleware.freeze).to be_equal(middleware) + expect(middleware).to be(:frozen?) + expect(middleware.freeze).to be_equal(middleware) + + expect(middleware.all_locales).to be(:frozen?) + expect(default_locales).to be(:frozen?) + expect(default_locale).to be(:frozen?) + expect(hosts).to be(:frozen?) + expect(ignore).to be(:frozen?) + end + let(:middleware) do root = File.expand_path(".localization", __dir__) diff --git a/test/utopia/redirection.rb b/test/utopia/redirection.rb index cb679ce8..3900e27d 100644 --- a/test/utopia/redirection.rb +++ b/test/utopia/redirection.rb @@ -53,6 +53,16 @@ def tracked_body(name, events) expect(prefix).to be(:frozen?) end + it "freezes error document configuration" do + codes = {404 => "/error"} + middleware = Utopia::Redirection::Errors.new(Protocol::HTTP::Middleware::NotFound, codes) + + expect(middleware.freeze).to be_equal(middleware) + expect(middleware).to be(:frozen?) + expect(middleware.freeze).to be_equal(middleware) + expect(codes).to be(:frozen?) + end + let(:middleware) do Utopia::Application.build(Protocol::HTTP::Middleware.for{|request| case request.url.path.encoded diff --git a/test/utopia/session.rb b/test/utopia/session.rb index 00958fc6..3da882d3 100755 --- a/test/utopia/session.rb +++ b/test/utopia/session.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2014-2025, by Samuel Williams. +# Copyright, 2014-2026, by Samuel Williams. # Copyright, 2019, by Huba Nagy. require "sus/fixtures/protocol/http/middleware_context" @@ -85,6 +85,26 @@ end describe Utopia::Session::Middleware do + it "freezes its configuration" do + middleware = subject.new( + Protocol::HTTP::Middleware::NotFound, + session_name: "test.session", + secret: "secret", + expires_after: 3600, + update_timeout: 60, + ) + + expect(middleware.freeze).to be_equal(middleware) + expect(middleware).to be(:frozen?) + expect(middleware.freeze).to be_equal(middleware) + + expect(middleware.cookie_name).to be(:frozen?) + expect(middleware.key).to be(:frozen?) + expect(middleware.expires_after).to be(:frozen?) + expect(middleware.update_timeout).to be(:frozen?) + expect(middleware.cookie_defaults).to be(:frozen?) + end + let(:delegate) do Protocol::HTTP::Middleware.for do |request| request.session[:updated] = true diff --git a/test/utopia/static.rb b/test/utopia/static.rb index 6922057e..f81d5719 100755 --- a/test/utopia/static.rb +++ b/test/utopia/static.rb @@ -12,6 +12,23 @@ describe Utopia::Static do include Sus::Fixtures::Protocol::HTTP::MiddlewareContext + it "freezes its configuration" do + cache_control = proc{"private"} + middleware = Utopia::Static::Middleware.new( + Protocol::HTTP::Middleware::NotFound, + root: File.expand_path(".static", __dir__), + cache_control: cache_control, + ) + + expect(middleware.freeze).to be_equal(middleware) + expect(middleware).to be(:frozen?) + expect(middleware.freeze).to be_equal(middleware) + + expect(middleware.instance_variable_get(:@root)).to be(:frozen?) + expect(middleware.extensions).to be(:frozen?) + expect(cache_control).to be(:frozen?) + end + let(:middleware) do root = File.expand_path(".static", __dir__)