summary refs log tree commit
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2017-03-21 08:58:50 -0700
committerGitHub <noreply@github.com>2017-03-21 08:58:50 -0700
commit647438af0019c9cf5e0e1418997b551f7b580b35 (patch)
treeea15432016a718feb69f0487460828ebcbdfc293
parent561daa3c416f712b1f7736706e67282fc6cb6d84 (diff)
parent650659f439720bb88001d3c1d3f91576eaa7c1bd (diff)
downloadrack-647438af0019c9cf5e0e1418997b551f7b580b35.tar.gz
Merge pull request #1149 from jeremyevans/freeze-app
Add Builder#freeze_app to freeze application and all middleware instances
-rw-r--r--lib/rack/builder.rb11
-rw-r--r--test/spec_builder.rb21
2 files changed, 30 insertions, 2 deletions
diff --git a/lib/rack/builder.rb b/lib/rack/builder.rb
index 975cf1e1..11f596bd 100644
--- a/lib/rack/builder.rb
+++ b/lib/rack/builder.rb
@@ -51,7 +51,7 @@ module Rack
     end
 
     def initialize(default_app = nil, &block)
-      @use, @map, @run, @warmup = [], nil, default_app, nil
+      @use, @map, @run, @warmup, @freeze_app = [], nil, default_app, nil, false
       instance_eval(&block) if block_given?
     end
 
@@ -141,10 +141,17 @@ module Rack
       @map[path] = block
     end
 
+    # Freeze the app (set using run) and all middleware instances when building the application
+    # in to_app.
+    def freeze_app
+      @freeze_app = true
+    end
+
     def to_app
       app = @map ? generate_map(@run, @map) : @run
       fail "missing run or map statement" unless app
-      app = @use.reverse.inject(app) { |a,e| e[a] }
+      app.freeze if @freeze_app
+      app = @use.reverse.inject(app) { |a,e| e[a].tap { |x| x.freeze if @freeze_app } }
       @warmup.call(app) if @warmup
       app
     end
diff --git a/test/spec_builder.rb b/test/spec_builder.rb
index ae1c4006..111d7b55 100644
--- a/test/spec_builder.rb
+++ b/test/spec_builder.rb
@@ -174,6 +174,27 @@ describe Rack::Builder do
     Rack::MockRequest.new(app).get("/").must_be :server_error?
   end
 
+  it "supports #freeze_app for freezing app and middleware" do
+    app = builder do
+      freeze_app
+      use Rack::ShowExceptions
+      use(Class.new do
+        def initialize(app) @app = app end
+        def call(env) @a = 1 if env['PATH_INFO'] == '/a'; @app.call(env) end
+      end)
+      o = Object.new
+      def o.call(env)
+        @a = 1 if env['PATH_INFO'] == '/b';
+        [200, {}, []]
+      end
+      run o
+    end
+
+    Rack::MockRequest.new(app).get("/a").must_be :server_error?
+    Rack::MockRequest.new(app).get("/b").must_be :server_error?
+    Rack::MockRequest.new(app).get("/c").status.must_equal 200
+  end
+
   it 'complains about a missing run' do
     proc do
       Rack::Lint.new Rack::Builder.app { use Rack::ShowExceptions }