diff options
author | Shawn O. Pearce <sop@google.com> | 2009-03-30 16:12:26 -0700 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2009-03-30 16:12:26 -0700 |
commit | 082d64ade8938701a41a62c2f0ce219a10f8f29d (patch) | |
tree | 2827df953f081d6cd96ca0df09a0ecd0e2a402f3 | |
parent | 759dfc4db0f28c87f2ac12c62b4c370a52610a6a (diff) |
Cache *.nocache.js and don't cache the host page
Our host page is significantly smaller than the *.nocache.js produced
by the GWT compiler, and since its HTML it can also be transferred by
way of gzip deflate encoding.
We can improve browser loading performance (slightly) by allowing the
larger *.nocache.js to be cached at the edges, and marking the host
page as never cached. To ensure the most current code is loaded we
embed a SHA-1 hash of the *.nocache.js content within its URL, thus
allowing the CacheControlFilter to mark it as cached for 1 year, and
ensuring that new versions of code will use a different URL, causing
the browser to load the new *.nocache.js version from the server.
Signed-off-by: Shawn O. Pearce <sop@google.com>
-rw-r--r-- | pom.xml | 2 | ||||
-rw-r--r-- | src/main/java/com/google/gerrit/public/Gerrit.html | 4 | ||||
-rw-r--r-- | src/main/java/com/google/gerrit/server/HostPageServlet.java | 46 |
3 files changed, 44 insertions, 8 deletions
@@ -446,7 +446,7 @@ limitations under the License. <dependency> <groupId>gwtexpui</groupId> <artifactId>gwtexpui</artifactId> - <version>1.0.2</version> + <version>1.0.3</version> <scope>compile</scope> </dependency> diff --git a/src/main/java/com/google/gerrit/public/Gerrit.html b/src/main/java/com/google/gerrit/public/Gerrit.html index 38c8e07080..a0b4324fbc 100644 --- a/src/main/java/com/google/gerrit/public/Gerrit.html +++ b/src/main/java/com/google/gerrit/public/Gerrit.html @@ -3,8 +3,8 @@ <title>Gerrit Code Review</title> <meta name="gwt:property" content="locale=en_US" /> <script id="gerrit_gerritconfig"></script> - <script type="text/javascript" language="javascript" src="com.google.gerrit.Gerrit.nocache.js"></script> - <style type="text/css" id="gerrit_sitecss"></style> + <script id="gerrit_module" type="text/javascript" language="javascript" src="com.google.gerrit.Gerrit.nocache.js"></script> + <style id="gerrit_sitecss" type="text/css"></style> <link rel="icon" type="image/gif" href="favicon.ico" /> </head> <body> diff --git a/src/main/java/com/google/gerrit/server/HostPageServlet.java b/src/main/java/com/google/gerrit/server/HostPageServlet.java index 461b3322ab..20642a0fe2 100644 --- a/src/main/java/com/google/gerrit/server/HostPageServlet.java +++ b/src/main/java/com/google/gerrit/server/HostPageServlet.java @@ -19,13 +19,17 @@ import com.google.gwt.user.server.rpc.RPCServletUtils; import com.google.gwtjsonrpc.server.XsrfException; import com.google.gwtorm.client.OrmException; +import org.spearce.jgit.lib.Constants; +import org.spearce.jgit.lib.ObjectId; import org.w3c.dom.Document; import org.w3c.dom.Element; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.StringWriter; +import java.security.MessageDigest; import javax.servlet.ServletConfig; import javax.servlet.ServletException; @@ -35,9 +39,6 @@ import javax.servlet.http.HttpServletResponse; /** Sends the Gerrit host page to clients. */ public class HostPageServlet extends HttpServlet { - static final long MAX_AGE = 5 * 60 * 1000L/* milliseconds */; - static final String CACHE_CTRL = "public, max-age=" + (MAX_AGE / 1000L); - private String canonicalUrl; private byte[] hostPageRaw; private byte[] hostPageCompressed; @@ -64,6 +65,7 @@ public class HostPageServlet extends HttpServlet { if (hostDoc == null) { throw new ServletException("No " + hostPageName + " in CLASSPATH"); } + fixModuleReference(hostDoc); injectJson(hostDoc, "gerrit_gerritconfig", Common.getGerritConfig()); injectCssFile(hostDoc, "gerrit_sitecss", sitePath, "GerritSite.css"); injectXmlFile(hostDoc, "gerrit_header", sitePath, "GerritSiteHeader.html"); @@ -148,6 +150,39 @@ public class HostPageServlet extends HttpServlet { scriptNode.appendChild(hostDoc.createCDATASection(w.toString())); } + private void fixModuleReference(final Document hostDoc) + throws ServletException { + final Element scriptNode = HtmlDomUtil.find(hostDoc, "gerrit_module"); + if (scriptNode == null) { + throw new ServletException("No gerrit_module to rewrite in host document"); + } + + final String src = scriptNode.getAttribute("src"); + final InputStream in = getServletContext().getResourceAsStream("/" + src); + if (in == null) { + throw new ServletException("No " + src + " in webapp root"); + } + + final MessageDigest md = Constants.newMessageDigest(); + try { + try { + final byte[] buf = new byte[1024]; + int n; + while ((n = in.read(buf)) > 0) { + md.update(buf, 0, n); + } + } finally { + in.close(); + } + } catch (IOException e) { + throw new ServletException("Failed reading " + src, e); + } + + final String vstr = ObjectId.fromRaw(md.digest()).name(); + scriptNode.removeAttribute("id"); + scriptNode.setAttribute("src", src + "?content=" + vstr); + } + @Override protected long getLastModified(final HttpServletRequest req) { return lastModified; @@ -192,8 +227,9 @@ public class HostPageServlet extends HttpServlet { tosend = hostPageRaw; } - rsp.setHeader("Cache-Control", CACHE_CTRL); - rsp.setDateHeader("Expires", System.currentTimeMillis() + MAX_AGE); + rsp.setHeader("Pragma", "no-cache"); + rsp.setHeader("Cache-Control", "no-cache, must-revalidate"); + rsp.setDateHeader("Expires", 0L); rsp.setDateHeader("Last-Modified", lastModified); rsp.setContentType("text/html"); rsp.setCharacterEncoding(HtmlDomUtil.ENC); |