LCOV - code coverage report
Current view: top level - util/http - CacheHeaders.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 27 30 90.0 %
Date: 2022-11-19 15:00:39 Functions: 8 9 88.9 %

          Line data    Source code
       1             : // Copyright (C) 2013 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.util.http;
      16             : 
      17             : import static java.util.concurrent.TimeUnit.DAYS;
      18             : import static java.util.concurrent.TimeUnit.SECONDS;
      19             : 
      20             : import java.util.concurrent.TimeUnit;
      21             : import javax.servlet.http.HttpServletRequest;
      22             : import javax.servlet.http.HttpServletResponse;
      23             : 
      24             : /** Utilities to manage HTTP caching directives in responses. */
      25             : public class CacheHeaders {
      26          32 :   private static final long MAX_CACHE_DURATION = DAYS.toSeconds(365);
      27             : 
      28             :   /**
      29             :    * Do not cache the response, anywhere.
      30             :    *
      31             :    * @param res response being returned.
      32             :    */
      33             :   public static void setNotCacheable(HttpServletResponse res) {
      34          32 :     String cc = "no-cache, no-store, max-age=0, must-revalidate";
      35          32 :     res.setHeader("Cache-Control", cc);
      36          32 :     res.setHeader("Pragma", "no-cache");
      37          32 :     res.setHeader("Expires", "Mon, 01 Jan 1990 00:00:00 GMT");
      38          32 :     res.setDateHeader("Date", System.currentTimeMillis());
      39          32 :   }
      40             : 
      41             :   /**
      42             :    * Permit caching the response for up to the age specified.
      43             :    *
      44             :    * <p>If the request is on a secure connection (e.g. SSL) private caching is used. This allows the
      45             :    * user-agent to cache the response, but requests intermediate proxies to not cache. This may
      46             :    * offer better protection for Set-Cookie headers.
      47             :    *
      48             :    * <p>If the request is on plaintext (insecure), public caching is used. This may allow an
      49             :    * intermediate proxy to cache the response, including any Set-Cookie header that may have also
      50             :    * been included.
      51             :    *
      52             :    * @param req current request.
      53             :    * @param res response being returned.
      54             :    * @param age how long the response can be cached.
      55             :    * @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
      56             :    */
      57             :   public static void setCacheable(
      58             :       HttpServletRequest req, HttpServletResponse res, long age, TimeUnit unit) {
      59           0 :     setCacheable(req, res, age, unit, false);
      60           0 :   }
      61             : 
      62             :   /**
      63             :    * Permit caching the response for up to the age specified.
      64             :    *
      65             :    * <p>If the request is on a secure connection (e.g. SSL) private caching is used. This allows the
      66             :    * user-agent to cache the response, but requests intermediate proxies to not cache. This may
      67             :    * offer better protection for Set-Cookie headers.
      68             :    *
      69             :    * <p>If the request is on plaintext (insecure), public caching is used. This may allow an
      70             :    * intermediate proxy to cache the response, including any Set-Cookie header that may have also
      71             :    * been included.
      72             :    *
      73             :    * @param req current request.
      74             :    * @param res response being returned.
      75             :    * @param age how long the response can be cached.
      76             :    * @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
      77             :    * @param mustRevalidate true if the client must validate the cached entity.
      78             :    */
      79             :   public static void setCacheable(
      80             :       HttpServletRequest req,
      81             :       HttpServletResponse res,
      82             :       long age,
      83             :       TimeUnit unit,
      84             :       boolean mustRevalidate) {
      85           1 :     if (req.isSecure()) {
      86           0 :       setCacheablePrivate(res, age, unit, mustRevalidate);
      87             :     } else {
      88           1 :       setCacheablePublic(res, age, unit, mustRevalidate);
      89             :     }
      90           1 :   }
      91             : 
      92             :   /**
      93             :    * Allow the response to be cached by proxies and user-agents.
      94             :    *
      95             :    * <p>If the response includes a Set-Cookie header the cookie may be cached by a proxy and
      96             :    * returned to multiple browsers behind the same proxy. This is insecure for authenticated
      97             :    * connections.
      98             :    *
      99             :    * @param res response being returned.
     100             :    * @param age how long the response can be cached.
     101             :    * @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
     102             :    * @param mustRevalidate true if the client must validate the cached entity.
     103             :    */
     104             :   public static void setCacheablePublic(
     105             :       HttpServletResponse res, long age, TimeUnit unit, boolean mustRevalidate) {
     106           1 :     long now = System.currentTimeMillis();
     107           1 :     long sec = maxAgeSeconds(age, unit);
     108             : 
     109           1 :     res.setDateHeader("Expires", now + SECONDS.toMillis(sec));
     110           1 :     res.setDateHeader("Date", now);
     111           1 :     cache(res, "public", age, unit, mustRevalidate);
     112           1 :   }
     113             : 
     114             :   /**
     115             :    * Allow the response to be cached only by the user-agent.
     116             :    *
     117             :    * @param res response being returned.
     118             :    * @param age how long the response can be cached.
     119             :    * @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
     120             :    * @param mustRevalidate true if the client must validate the cached entity.
     121             :    */
     122             :   public static void setCacheablePrivate(
     123             :       HttpServletResponse res, long age, TimeUnit unit, boolean mustRevalidate) {
     124           7 :     long now = System.currentTimeMillis();
     125           7 :     res.setDateHeader("Expires", now);
     126           7 :     res.setDateHeader("Date", now);
     127           7 :     cache(res, "private", age, unit, mustRevalidate);
     128           7 :   }
     129             : 
     130             :   public static boolean hasCacheHeader(HttpServletResponse res) {
     131           1 :     return res.containsHeader("Cache-Control") || res.containsHeader("Expires");
     132             :   }
     133             : 
     134             :   private static void cache(
     135             :       HttpServletResponse res, String type, long age, TimeUnit unit, boolean revalidate) {
     136           8 :     res.setHeader(
     137             :         "Cache-Control",
     138           8 :         String.format(
     139             :             "%s, max-age=%d%s",
     140           8 :             type, maxAgeSeconds(age, unit), revalidate ? ", must-revalidate" : ""));
     141           8 :   }
     142             : 
     143             :   private static long maxAgeSeconds(long age, TimeUnit unit) {
     144           8 :     return Math.min(unit.toSeconds(age), MAX_CACHE_DURATION);
     145             :   }
     146             : 
     147             :   private CacheHeaders() {}
     148             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750