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
