Author: sshyrkov
Date: Mon Oct 15 11:23:32 2007
New Revision: 18858

URL: https://svndev.jahia.net/websvn/listing.php?sc=3D1&rev=3D18858&repname=
=3Djahia
Log:
JAHIA-2528: Proper caching for static resources =

http://www.jahia.net/jira/browse/JAHIA-2528
Resolution: set 'Cache-control' and 'Expires' response headers to correctly=
 cache static resources under /jsp/jahia

Modified:
    branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/bin/filters/zimbra=
/SetHeaderFilter.java
    branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/WEB-INF/web.xml
    branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/jsp/jahia/css/core_css.jsp
    branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/jsp/jahia/css/pngbehavior.=
jsp

Modified: branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/bin/filters/=
zimbra/SetHeaderFilter.java
URL: https://svndev.jahia.net/websvn/diff.php?path=3D/branches/JAHIA-5-0-SP=
-BRANCH/core/src/java/org/jahia/bin/filters/zimbra/SetHeaderFilter.java&rev=
=3D18858&repname=3Djahia
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/bin/filters/zimbra=
/SetHeaderFilter.java (original)
+++ branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/bin/filters/zimbra=
/SetHeaderFilter.java Mon Oct 15 11:23:32 2007
@@ -17,28 +17,31 @@
  */
 package org.jahia.bin.filters.zimbra;
 =

-import org.org.apache.commons.httpclient.util.DateUtil;
-
-import javax.servlet.*;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
 import java.util.Enumeration;
-import java.util.TimeZone;
-import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 =

+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+
 /**
  * @author Xavier Lawrence
  */
 public class SetHeaderFilter implements Filter {
 =

-    private static final org.apache.log4j.Logger logger =3D
-            org.apache.log4j.Logger.getLogger(SetHeaderFilter.class);
+    private static final Logger logger =3D Logger
+            .getLogger(SetHeaderFilter.class);
 =

     private static final String FALSE =3D "false";
     private static final String TRUE =3D "true";
@@ -54,8 +57,7 @@
     private static final String HEADER_EXPIRES =3D "Expires";
     private static final String ALREADY_EXPIRED =3D "Tue, 24 Jan 2000 20:4=
6:50 GMT";
     private static final String HEADER_CONTENT_ENCODING =3D "Content-encod=
ing";
-    private static final String TIME_FORMAT =3D "EEE, d MMM yyyy HH:mm:ss";
-    private static final String GMT =3D "GMT";
+    private static final String PARAM_CACHED_RESOURCES_REGEXP =3D "cachedR=
esourcesRegexp";
 =

     protected String jsVersion =3D null;
     protected FilterConfig config =3D null;
@@ -66,6 +68,7 @@
     protected static boolean isProdMode =3D true;
     protected String futureCacheControl =3D null;
     protected Pattern noCachePattern =3D null;
+    protected Pattern cachedResourcesPattern;
 =

     private String getInitParameter(String key, String def) {
         String value =3D this.config.getInitParameter(key);
@@ -143,6 +146,12 @@
             // http://msdn.microsoft.com/workshop/author/perf/perftips.asp=
#Use_Cache-Control_Extensions
             futureCacheControl =3D "public, max-age=3D" + expiresValue + "=
, post-check=3D7200, pre-check=3D" + expiresValue;
             isProdMode =3D getInitParameterBool("ProdMode", true);
+            =

+            String cachedResourcesRegexp =3D getInitParameter(
+                    PARAM_CACHED_RESOURCES_REGEXP, "").trim();
+            cachedResourcesPattern =3D cachedResourcesRegexp.length() > 0
+                    && !cachedResourcesRegexp.equals(".*") ? Pattern.compi=
le(
+                    cachedResourcesRegexp, Pattern.CASE_INSENSITIVE) : nul=
l; =

 =

             logger.debug("Filter variables:");
             logger.debug("  jsVersion =3D " + jsVersion);
@@ -153,6 +162,9 @@
             logger.debug("  extensionRegex =3D " + extensionPattern.patter=
n());
             logger.debug("  noCachPattern =3D " + noCachePattern.pattern()=
);
             logger.debug("  noCachPattern =3D " + noCachePattern.pattern()=
);
+            logger.debug("  cachedResourcesPattern =3D "
+                    + (cachedResourcesPattern !=3D null ? cachedResourcesP=
attern
+                            .pattern() : "null"));
         }
     }
 =

@@ -176,11 +188,7 @@
 =

     private boolean shouldProcess(ServletRequest request,
                                   ServletResponse response) {
-        boolean process =3D false;
-        if (isHttpRequest(request, response) && extensionPattern !=3D null=
) {
-            process =3D true;
-        }
-        return process;
+        return isHttpRequest(request, response);
     }
 =

     /**
@@ -189,72 +197,59 @@
     public void doFilter(ServletRequest request,
                          ServletResponse response,
                          FilterChain chain) throws IOException, ServletExc=
eption {
-        logger.debug("doFilter...");
-
         // make sure we're dealing with an http request
-        HttpServletRequest req;
-        HttpServletResponse resp;
-        boolean proceed =3D shouldProcess(request, response);
-        if (proceed) {
-            req =3D (HttpServletRequest) request;
-            resp =3D (HttpServletResponse) response;
-
-        } else {
-            logger.debug("not proceeding with filter");
-            chain.doFilter(request, response);
-            return;
-        }
+        if (shouldProcess(request, response)) {
+            HttpServletRequest req =3D (HttpServletRequest) request;
+            HttpServletResponse resp =3D (HttpServletResponse) response;
+
+            String uri =3D req.getRequestURI();
+
+            //if (true) throw new RuntimeException("URI=3D"+uri);
+
+            if (uri.toLowerCase().indexOf("microsoft-server-activesync") !=
=3D -1) {
+
+                logger.debug("ZimbraSync client detected...");
+
+                try {
+                    String targetContextStr =3D "/service/";
+                    ServletContext myContext =3D config.getServletContext(=
);
+                    ServletContext targetContext =3D myContext.getContext(=
targetContextStr);
+                    RequestDispatcher dispatcher =3D targetContext.getRequ=
estDispatcher("/extension/zimbrasync");
+                    dispatcher.forward(request, response);
+                    return;
+                } catch (NullPointerException npe) {
+                    //if this happens, make sure in server.xml the context=
 element for the zimbra app
+                    //has crossContext=3Dtrue
 =

-        String uri =3D req.getRequestURI();
-
-        //if (true) throw new RuntimeException("URI=3D"+uri);
-
-        if (uri.toLowerCase().indexOf("microsoft-server-activesync") !=3D =
-1) {
-
-            logger.debug("ZimbraSync client detected...");
-
-            try {
-                String targetContextStr =3D "/service/";
-                ServletContext myContext =3D config.getServletContext();
-                ServletContext targetContext =3D myContext.getContext(targ=
etContextStr);
-                RequestDispatcher dispatcher =3D targetContext.getRequestD=
ispatcher("/extension/zimbrasync");
-                dispatcher.forward(request, response);
-                return;
-            } catch (NullPointerException npe) {
-                //if this happens, make sure in server.xml the context ele=
ment for the zimbra app
-                //has crossContext=3Dtrue
-
-                logger.debug("unable to forward zimbrasync request");
+                    logger.debug("unable to forward zimbrasync request");
+                }
             }
-        }
-
-        // before we check whether we can compress, let's check
-        // what sort of cache control headers we should use for this
-        // request.
-        logger.debug("checking cache-control for "+uri);
-        setCacheControlHeaders(req, resp);
-
-        boolean supportCompression;
-        supportCompression =3D supportsGzip(req);
-        //logger.debug("supportCompression: " + supportCompression);
-        setRequestAttributes(req, supportCompression);
-        if (!supportCompression) {
-            logger.debug("doFilter gets called wo gzip");
-            chain.doFilter(req, resp);
 =

-        } else {
-            final Matcher m =3D extensionPattern.matcher(uri);
-            if (m.matches()) {
-                logger.debug("the file "+uri+ " match "+extensionPattern.p=
attern()+": we set the content-encoding header accordingly");
-                // not sure why I can't set the headers after
-                // the chain.doFilter call, but ...
-                // I can't.
-                //logger.debug("setting headers "+HEADER_CONTENT_ENCODING+=
":"+HEADER_VAL_GZIP);
-                resp.setHeader(HEADER_CONTENT_ENCODING, HEADER_VAL_GZIP);
-                //resp.setHeader(HEADER_CONTENT_TYPE,"text/javascript");
+            // before we check whether we can compress, let's check
+            // what sort of cache control headers we should use for this
+            // request.
+            setCacheControlHeaders(req, resp);
+
+            boolean supportCompression =3D supportsGzip(req);
+
+            setRequestAttributes(req, supportCompression);
+            =

+            if (supportCompression) {
+                if (extensionPattern.matcher(uri).matches()) {
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("the file "+uri+ " match "+extensionP=
attern.pattern()+": we set the content-encoding header accordingly");
+                    }
+                    // not sure why I can't set the headers after
+                    // the chain.doFilter call, but ...
+                    // I can't.
+                    //logger.debug("setting headers "+HEADER_CONTENT_ENCOD=
ING+":"+HEADER_VAL_GZIP);
+                    resp.setHeader(HEADER_CONTENT_ENCODING, HEADER_VAL_GZI=
P);
+                    //resp.setHeader(HEADER_CONTENT_TYPE,"text/javascript"=
);
+                }
             }
-            chain.doFilter(req, resp);
         }
+        =

+        chain.doFilter(request, response);
     }
 =

     private void setRequestAttributes(HttpServletRequest req,
@@ -296,7 +291,7 @@
         // Check for the query parameter first, to see if they are
         // trying to override what the browser is saying.
         String s =3D req.getParameter(HEADER_VAL_GZIP);
-        if(s!=3Dnull) logger.debug("found request parameter " + HEADER_VAL=
_GZIP + " =3D " + s);
+        if(s!=3Dnull && logger.isDebugEnabled()) logger.debug("found reque=
st parameter " + HEADER_VAL_GZIP + " =3D " + s);
 =

         // We'll handle dev mode as an odd case, where only if
         // the user specifies that he wants gzip, will he get it.
@@ -351,10 +346,11 @@
     public void setCacheControlHeaders(HttpServletRequest req,
                                        HttpServletResponse resp) {
 =

-
         if (isDynamicContent(req.getRequestURI())) {
             setJspCacheControlHeaders(resp);
-        } else {
+        } else if (cachedResourcesPattern =3D=3D null
+                || cachedResourcesPattern.matcher(req.getRequestURI())
+                        .matches()) {
             setStaticResourceCacheControlHeaders(resp);
         }
     }
@@ -365,7 +361,7 @@
     }
 =

     private void setJspCacheControlHeaders(HttpServletResponse resp) {
-        logger.debug("is jsp: set dynamic cache-control");
+//        logger.debug("is jsp: set dynamic cache-control");
         resp.setHeader(HEADER_EXPIRES, ALREADY_EXPIRED);
         resp.setHeader(HEADER_CACHE_CONTROL, NO_CACHE_CONTROL_VALUE);
         resp.addHeader(HEADER_CACHE_CONTROL, NO_CACHE_CONTROL_IE_VALUE);
@@ -376,13 +372,14 @@
     private void setStaticResourceCacheControlHeaders(HttpServletResponse =
resp) {
         if (expiresValue > 0) {
             if(logger.isDebugEnabled()) logger.debug("is static file: set =
static cache-control");
-            final TimeZone gmt =3D TimeZone.getTimeZone(GMT);
-            final long now =3D System.currentTimeMillis();
-            final Date expiresDate =3D new Date(now + (expiresValue * 1000=
));
-            final DateFormat df =3D new SimpleDateFormat(DateUtil.PATTERN_=
RFC1123, Locale.US);
-            df.setTimeZone(gmt);
-            if(logger.isDebugEnabled()) logger.debug("expire:"+df.format(e=
xpiresDate));
-            resp.setHeader(HEADER_EXPIRES, df.format(expiresDate) + " " + =
GMT);
+//            final TimeZone gmt =3D TimeZone.getTimeZone(GMT);
+//            final long now =3D System.currentTimeMillis();
+//            final Date expiresDate =3D new Date(now + (expiresValue * 10=
00));
+//            final DateFormat df =3D new SimpleDateFormat(DateUtil.PATTER=
N_RFC1123, Locale.US);
+//            df.setTimeZone(gmt);
+//            if(logger.isDebugEnabled()) logger.debug("expire:"+df.format=
(expiresDate));
+//            resp.setHeader(HEADER_EXPIRES, df.format(expiresDate) + " " =
+ GMT);
+            resp.setDateHeader(HEADER_EXPIRES, System.currentTimeMillis() =
+ expiresValue * 1000);
             if(futureCacheControl!=3Dnull){
             if(logger.isDebugEnabled()) logger.debug("cache-control:"+futu=
reCacheControl);
             resp.setHeader(HEADER_CACHE_CONTROL, futureCacheControl);

Modified: branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/WEB-INF/web.xml
URL: https://svndev.jahia.net/websvn/diff.php?path=3D/branches/JAHIA-5-0-SP=
-BRANCH/core/src/webapp/WEB-INF/web.xml&rev=3D18858&repname=3Djahia
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/WEB-INF/web.xml (original)
+++ branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/WEB-INF/web.xml Mon Oct 15=
 11:23:32 2007
@@ -125,28 +125,42 @@
         <init-param>
             <param-name>Expires</param-name>
             <param-value>604800</param-value>
-            <!--
-                   Expires should be the number of seconds from now when a
-                   given static resource should expire
-               -->
+            <description>
+                Expires should be the number of seconds from now when a gi=
ven static resource should expire
+            </description>
         </init-param>
         <init-param>
             <param-name>ProdMode</param-name>
             <param-value>true</param-value>
         </init-param>
         <init-param>
+            <param-name>cachedResourcesRegexp</param-name>
+            <!-- Cache everything that is not dynamic (see noCachePatternL=
ist param) -->
+            <param-value>.*</param-value>
+            <!-- Cache only JS, CCS and images =

+            <param-value>^/jsp/jahia/.*\.(js|css|gif|png|jpg|ico|htc)(\?.*=
)?</param-value>
+             -->
+            <description>
+                Regular expression pattern for resources, which should be =
cached by the browser by setting 'Expires' header to the configured value (=
see 'Expires' init param above).
+            </description>
+        </init-param>
+        <init-param>
             <param-name>noCachePatternList</param-name>
-            <param-value>
-               .jsp
-            </param-value>
-            <!--
-                   List of patterns for which no-cache headers will be ret=
urned.
-               -->
+            <param-value>.jsp</param-value>
+            <description>
+                List of patterns for which no-cache headers will be return=
ed.
+                This condition takes precedence over the 'cachedResourcesR=
egexp' parameter.
+            </description>
         </init-param>
     </filter>
 =

     <filter-mapping>
         <filter-name>Set Header Filter</filter-name>
+        <url-pattern>/jsp/jahia/*</url-pattern>
+    </filter-mapping>
+<!-- =

+    <filter-mapping>
+        <filter-name>Set Header Filter</filter-name>
         <url-pattern>/jsp/jahia/javascript/zimbra/*</url-pattern>
     </filter-mapping>
 =

@@ -159,6 +173,7 @@
         <filter-name>Set Header Filter</filter-name>
         <url-pattern>/jsp/jahia/javascript/scriptaculous/*</url-pattern>
     </filter-mapping>
+ -->    =

 =

     <!-- Display request URLs - Pattern-->
     <filter-mapping>

Modified: branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/jsp/jahia/css/core_c=
ss.jsp
URL: https://svndev.jahia.net/websvn/diff.php?path=3D/branches/JAHIA-5-0-SP=
-BRANCH/core/src/webapp/jsp/jahia/css/core_css.jsp&rev=3D18858&repname=3Dja=
hia
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/jsp/jahia/css/core_css.jsp=
 (original)
+++ branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/jsp/jahia/css/core_css.jsp=
 Mon Oct 15 11:23:32 2007
@@ -14,31 +14,21 @@
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
---%><%@ page language=3D"java" contentType=3D"text/css" %>
-<%
-    org.apache.log4j.Logger logger =3D org.apache.log4j.Logger.getLogger(g=
etClass());
-    org.jahia.settings.SettingsBean siteSetting =3D org.jahia.bin.Jahia.ge=
tSettings();
-    if (siteSetting !=3D null) {
-        if (siteSetting.isDevelopmentMode()) {
-        logger.debug("We are in dev mode -> Disable browser cache for core=
_css.jsp");
-        response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
+--%><%@ page language=3D"java" contentType=3D"text/css" %><%
+org.jahia.settings.SettingsBean siteSetting =3D org.jahia.bin.Jahia.getSet=
tings();
+if (siteSetting !=3D null) {
+    if (siteSetting.isDevelopmentMode()) {
+        response.setHeader("Cache-Control","no-store, no-cache, must-reval=
idate, max-age=3D0"); //HTTP 1.1
+        response.addHeader("Cache-Control","post-check=3D0, pre-check=3D0"=
);
         response.setHeader("Pragma","no-cache"); //HTTP 1.0
         response.setDateHeader ("Expires", -1);
-        } else {
-        logger.debug("We are in production mode -> Set browser cache for c=
ore_css.jsp to 1 hour");
-        long now =3D System.currentTimeMillis();
-        response.setDateHeader("Expires", now + 3600000); // 1 hour
-        response.addHeader("Cache-Control", "max-age=3D3600");
-        }
-    }
-    logger.debug("Opening core_css.jsp");
-    String bv=3D"";
-    bv=3D(String)request.getParameter("bval");
-    if(bv=3D=3Dnull || bv.equalsIgnoreCase("")) bv=3D"3";
-    int bval=3DInteger.parseInt(bv);
-
+    } else {
+        response.setHeader("Cache-Control", "public, max-age=3D604800, pos=
t-check=3D7200, pre-check=3D604800");
+        response.setHeader("Pragma", "");
+        response.setDateHeader("Expires", System.currentTimeMillis() + 604=
800 * 1000); // 7 days
+    }
+}
 %>
-/* <%=3Dbv%> : <%=3Dbval%>  */
 /* ENGINES MENU ****************************
 */
 #menuwrapper{background:url( "menubg.gif" ) repeat-y right 50% #fff;displa=
y:inline;width:100%;}

Modified: branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/jsp/jahia/css/pngbeh=
avior.jsp
URL: https://svndev.jahia.net/websvn/diff.php?path=3D/branches/JAHIA-5-0-SP=
-BRANCH/core/src/webapp/jsp/jahia/css/pngbehavior.jsp&rev=3D18858&repname=
=3Djahia
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/jsp/jahia/css/pngbehavior.=
jsp (original)
+++ branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/jsp/jahia/css/pngbehavior.=
jsp Mon Oct 15 11:23:32 2007
@@ -16,9 +16,10 @@
 limitations under the License.
 --%><[EMAIL PROTECTED] language=3D"java"%><%
     response.setContentType("text/x-component");
+       response.setHeader("Cache-Control", "public, max-age=3D604800, 
post-check=
=3D7200, pre-check=3D604800");
+       response.setDateHeader("Expires", System.currentTimeMillis() + 604800 * 
1=
000); // 7 days
     final String path =3D request.getContextPath() + "/jsp/jahia/css/blank=
.gif";
 %>
-
 <public:component lightWeight=3D"true">
 <public:attach event=3D"onpropertychange" onevent=3D"propertyChanged()" />
 <public:attach event=3D"onbeforeprint" onevent=3D"beforePrint()" for=3D"wi=
ndow"/>
@@ -44,7 +45,7 @@
  */
 =

 var supported =3D /MSIE ((5\.5)|6)/.test(navigator.userAgent) &&
-                               navigator.platform =3D=3D "Win32";
+                               (navigator.platform =3D=3D "Win32" || 
navigator.platform =3D=3D "Win64=
");
 =

 var realSrc;
 var blankSrc =3D "<%=3Dpath%>";

_______________________________________________
cvs_list mailing list
[email protected]
http://lists.jahia.org/cgi-bin/mailman/listinfo/cvs_list

Reply via email to