From c1dd2285799b19b7067119b2aa121ca922b75bc3 Mon Sep 17 00:00:00 2001
From: "yuuji.yaginuma" <yuuji.yaginuma@gmail.com>
Date: Wed, 2 Jan 2019 17:11:59 +0900
Subject: Allow using combine the Cache-Control `public` and `no-cache` headers

Since #30367, if `no-cache` includes Cache-Control headers, special keys
like `public`, `must-revalidate` are ignored.
But in my understanding, `public` still need in case of want to cache
authenticated pages.
The authenticated pages to be cacheable, but still authenticated for
every user, need to specify the `Cache-Control: public, no-cache`.

For keys other than `public`, I did not know the case where it was
necessary to use it in combination with `no-cache`, so I fixed that can
be used only for `public`.

Ref: https://www.mnot.net/cache_docs/#CACHE-CONTROL

Fixes #34780.
---
 actionpack/lib/action_dispatch/http/cache.rb | 10 ++++++----
 actionpack/test/controller/render_test.rb    | 10 ++++++++++
 2 files changed, 16 insertions(+), 4 deletions(-)

(limited to 'actionpack')

diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index f67b13f657..8cc84ff36c 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -197,10 +197,12 @@ module ActionDispatch
           if control.empty?
             # Let middleware handle default behavior
           elsif control[:no_cache]
-            self._cache_control = NO_CACHE
-            if control[:extras]
-              self._cache_control = _cache_control + ", #{control[:extras].join(', ')}"
-            end
+            options = []
+            options << PUBLIC if control[:public]
+            options << NO_CACHE
+            options.concat(control[:extras]) if control[:extras]
+
+            self._cache_control = options.join(", ")
           else
             extras = control[:extras]
             max_age = control[:max_age]
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 306b245bd1..4750093c5c 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -183,6 +183,11 @@ class TestController < ActionController::Base
     render action: "hello_world"
   end
 
+  def conditional_hello_without_expires_and_public_header
+    response.headers["Cache-Control"] = "public, no-cache"
+    render action: "hello_world"
+  end
+
   def conditional_hello_with_bangs
     render action: "hello_world"
   end
@@ -418,6 +423,11 @@ class ExpiresInRenderTest < ActionController::TestCase
     assert_equal "no-cache", @response.headers["Cache-Control"]
   end
 
+  def test_no_expires_now_with_public
+    get :conditional_hello_without_expires_and_public_header
+    assert_equal "public, no-cache", @response.headers["Cache-Control"]
+  end
+
   def test_date_header_when_expires_in
     time = Time.mktime(2011, 10, 30)
     Time.stub :now, time do
-- 
cgit v1.2.3