diff --git a/app/controllers/press/Press.java b/app/controllers/press/Press.java index dbfaf11..a55e2e5 100644 --- a/app/controllers/press/Press.java +++ b/app/controllers/press/Press.java @@ -1,6 +1,7 @@ package controllers.press; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -9,8 +10,10 @@ import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; +import play.Logger; import play.exceptions.UnexpectedException; import play.mvc.Controller; +import play.mvc.Http.Header; import press.CachingStrategy; import press.PluginConfig; import press.ScriptCompressedFileManager; @@ -21,6 +24,7 @@ import press.StyleRequestHandler; import press.io.CompressedFile; import press.io.FileIO; +import press.io.Gzip; public class Press extends Controller { public static final DateTimeFormatter httpDateTimeFormatter = DateTimeFormat @@ -80,6 +84,31 @@ private static void renderCompressedFile(CompressedFile compressedFile, String t } } + /* + * google wants this: "Instructs proxy servers to cache two versions + * of the resource: one compressed, and one uncompressed. This helps + * avoid issues with public proxies that do not detect the presence + * of a Content-Encoding header properly." + */ + response.headers.put("Vary", new Header("Vary", "Accept-Encoding")); + + // attempt gzip if the client requests it. + // + Header encodings = request.headers.get("accept-encoding"); + + if (PluginConfig.gzipEnabled && + (encodings != null) && + (encodings.value().indexOf("gzip") != -1)) { + try { + ByteArrayOutputStream gzip = Gzip.gzip(inputStream); + response.setHeader("Content-Encoding", "gzip"); + response.setHeader("Content-Length", gzip.size() + ""); + renderBinary(new ByteArrayInputStream(gzip.toByteArray()), compressedFile.name()); + } catch (IOException e) { + Logger.error(e, "Unable to compress output: %s", e.getMessage()); + } + } + renderBinary(inputStream, compressedFile.name()); } diff --git a/app/press/PluginConfig.java b/app/press/PluginConfig.java index 80c4967..cb4b56f 100644 --- a/app/press/PluginConfig.java +++ b/app/press/PluginConfig.java @@ -48,6 +48,9 @@ public static class DefaultConfig { // compiled, they will be output raw. public static final boolean outputRawLess = false; + // If enabled, turns on gzip when the client supports it + public static final boolean gzipEnabled = false; + public static class js { // The directory where source javascript files are read from public static final String srcDir = "/public/javascripts/"; @@ -85,6 +88,7 @@ public static class css { public static String contentHostingDomain; public static String p3pHeader; public static boolean outputRawLess; + public static boolean gzipEnabled; public static class js { public static String srcDir = DefaultConfig.js.srcDir; @@ -134,6 +138,7 @@ public static void readConfig() { DefaultConfig.contentHostingDomain); p3pHeader = ConfigHelper.getString("press.p3pHeader", DefaultConfig.p3pHeader); outputRawLess = ConfigHelper.getBoolean("press.outputRawLess", DefaultConfig.outputRawLess); + gzipEnabled = ConfigHelper.getBoolean("press.gzipEnabled", DefaultConfig.gzipEnabled); css.srcDir = ConfigHelper.getString("press.css.sourceDir", DefaultConfig.css.srcDir); css.compressedDir = ConfigHelper.getString("press.css.outputDir", diff --git a/app/press/io/Gzip.java b/app/press/io/Gzip.java new file mode 100644 index 0000000..35f8144 --- /dev/null +++ b/app/press/io/Gzip.java @@ -0,0 +1,36 @@ +package press.io; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import java.util.zip.GZIPOutputStream; + +public class Gzip { + + public static ByteArrayOutputStream gzip(final InputStream inputStream) + throws IOException + { + final ByteArrayOutputStream stringOutputStream = new ByteArrayOutputStream(); + final OutputStream gzipOutputStream = new GZIPOutputStream(stringOutputStream); + + final byte[] buf = new byte[5000]; + int len; + while ((len = inputStream.read(buf)) > 0) { + gzipOutputStream.write(buf, 0, len); + } + + inputStream.close(); + gzipOutputStream.close(); + + return stringOutputStream; + + } + + public static ByteArrayOutputStream gzip(final String input) + throws IOException { + return gzip(new ByteArrayInputStream(input.getBytes())); + } +} diff --git a/commands.pyc b/commands.pyc index 13759ef..7896042 100644 Binary files a/commands.pyc and b/commands.pyc differ