summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2009-03-30 16:12:26 -0700
committerShawn O. Pearce <sop@google.com>2009-03-30 16:12:26 -0700
commit082d64ade8938701a41a62c2f0ce219a10f8f29d (patch)
tree2827df953f081d6cd96ca0df09a0ecd0e2a402f3
parent759dfc4db0f28c87f2ac12c62b4c370a52610a6a (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.xml2
-rw-r--r--src/main/java/com/google/gerrit/public/Gerrit.html4
-rw-r--r--src/main/java/com/google/gerrit/server/HostPageServlet.java46
3 files changed, 44 insertions, 8 deletions
diff --git a/pom.xml b/pom.xml
index 5b06d08715..9d72d5351e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -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);