diff --git a/apps/routerconsole/jsp/flags.jsp b/apps/routerconsole/jsp/flags.jsp index c736e8b46..153b4c2f2 100644 --- a/apps/routerconsole/jsp/flags.jsp +++ b/apps/routerconsole/jsp/flags.jsp @@ -15,11 +15,27 @@ boolean rendered = false; String c = request.getParameter("c"); if (c != null && c.length() > 0) { java.io.OutputStream cout = response.getOutputStream(); - response.setContentType("image/png"); - response.setHeader("Cache-Control", "max-age=86400"); // cache for a day String base = net.i2p.I2PAppContext.getGlobalContext().getBaseDir().getAbsolutePath(); String file = "docs" + java.io.File.separatorChar + "icons" + java.io.File.separatorChar + "flags" + java.io.File.separatorChar + c + ".png"; + java.io.File ffile = new java.io.File(base, file); + long lastmod = ffile.lastModified(); + if (lastmod > 0) { + long iflast = request.getDateHeader("If-Modified-Since"); + // iflast is -1 if not present; round down file time + if (iflast >= ((lastmod / 1000) * 1000)) { + response.sendError(304, "Not Modified"); + return; + } + response.setDateHeader("Last-Modified", lastmod); + // cache for a day + response.setDateHeader("Expires", net.i2p.I2PAppContext.getGlobalContext().clock().now() + 86400000l); + response.setHeader("Cache-Control", "public, max-age=86400"); + } + long length = ffile.length(); + if (length > 0) + response.setHeader("Content-Length", Long.toString(length)); + response.setContentType("image/png"); try { net.i2p.util.FileUtil.readFile(file, base, cout); rendered = true; diff --git a/apps/routerconsole/jsp/viewtheme.jsp b/apps/routerconsole/jsp/viewtheme.jsp index 723b0ec32..814705e14 100644 --- a/apps/routerconsole/jsp/viewtheme.jsp +++ b/apps/routerconsole/jsp/viewtheme.jsp @@ -19,7 +19,6 @@ if (uri.endsWith(".css")) { } else if (uri.endsWith(".ico")) { response.setContentType("image/x-icon"); } -response.setHeader("Cache-Control", "max-age=86400"); // cache for a day /* * User or plugin themes * If the request is for /themes/console/foo/bar/baz, @@ -44,6 +43,23 @@ if (themePath != null) else base = net.i2p.I2PAppContext.getGlobalContext().getBaseDir().getAbsolutePath() + java.io.File.separatorChar + "docs"; +java.io.File file = new java.io.File(base, uri); +long lastmod = file.lastModified(); +if (lastmod > 0) { + long iflast = request.getDateHeader("If-Modified-Since"); + // iflast is -1 if not present; round down file time + if (iflast >= ((lastmod / 1000) * 1000)) { + response.sendError(304, "Not Modified"); + return; + } + response.setDateHeader("Last-Modified", lastmod); + // cache for a day + response.setDateHeader("Expires", net.i2p.I2PAppContext.getGlobalContext().clock().now() + 86400000l); + response.setHeader("Cache-Control", "public, max-age=86400"); +} +long length = file.length(); +if (length > 0) + response.setHeader("Content-Length", Long.toString(length)); try { net.i2p.util.FileUtil.readFile(uri, base, response.getOutputStream()); } catch (java.io.IOException ioe) { diff --git a/history.txt b/history.txt index 118de8648..31c79e052 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,10 @@ +2011-01-15 zzz + * Console: Add some HTTP headers in the view servlets + +2011-01-12 zzz + * Log: Fix rare initialization problem + * PrivateKey: Fix hashCode() + 2011-01-09 zzz * DataHelper: Speed up and annotate sortStructures() * Data Structures: More caching improvements, don't cache where we shouldn't diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 7ca1a3ec2..5a58b19bc 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 10; + public final static long BUILD = 11; /** for example "-test" */ public final static String EXTRA = "";