roxen.lists.roxen.general

Subject Author Date
[PATCH 14/17] New module: gzip-on-the-fly Stephen R. van den Berg <srb[at]cuci[dot]nl> 20-01-2009
---

 server/modules/filters/gziponthefly.pike |  102 ++++++++++++++++++++++++++++++
 1 files changed, 102 insertions(+), 0 deletions(-)
 create mode 100644 server/modules/filters/gziponthefly.pike

diff --git a/server/modules/filters/gziponthefly.pike
b/server/modules/filters/gziponthefly.pike
new file mode 100644
index 0000000..dae088e
--- /dev/null
+++ b/server/modules/filters/gziponthefly.pike
@@ -0,0 +1,102 @@
+// This is a roxen module which provides gzip-on-the-fly compression support.
+// Copyright (c) 2002-2009, Stephen R. van den Berg, The Netherlands.
+//                     <<srb[at]cuci.nl>>
+//
+// This module is open source software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published
+// by the Free Software Foundation; either version 2, or (at your option) any
+// later version.
+//
+
+#define _(X,Y)  _DEF_LOCALE("mod_gziponthefly",X,Y)
+
+constant thread_safe = 1;
+
+#include <module.h>
+
+inherit "module";
+
+constant module_type = MODULE_FILTER;
+LocaleString module_name = _(1,"Filters: Gzip-on-the-fly");
+LocaleString module_doc =  _(2,
+ "This module provides the gzip-on-the-fly filter.<br />"
+ "<p>Copyright &copy; 2002-2009, by "
+ "<a href='mailto:<srb[at]cuci.nl>'>Stephen R. van den Berg</a>, "
+ "The Netherlands.</p>"
+ "<p>Due to implementation mistakes by Microsoft this filter "
+ "uses the gzip format instead of deflate. </p> "
+ "<p>By setting a browser-cookie of gzip=0 one can disable compression, "
+ "whereas setting gzip=1 will force compression. </p> "
+ "<p>This module is open source software; you can redistribute it and/or "
+ "modify it under the terms of the GNU General Public License as published "
+ "by the Free Software Foundation; either version 2, or (at your option) any "
+ "later version.</p>");
+
+#define COMPRESSION_LEVEL  1
+
+void create() {
+  set_module_creator("Stephen R. van den Berg <<srb[at]cuci.nl>>");
+  defvar ("compressionlevel", 1,
+        _(3,"Compressionlevel"), TYPE_INT,
+        _(4,"Use 1 for fast compression, use 9 for slow compression.")
+          );
+  defvar ("minfilesize", 1024,
+        _(5,"Minimum file size"), TYPE_INT,
+        _(6,"Any data equal to or below this size limit will be sent "
+          "uncompressed.")
+          );
+}
+
+int before, after, nosupport, fixed, nowant;
+float time_spent;
+
+string status()
+{
+    return sprintf("%.1fM of %.1fM (%.1f%%) have been gained "
+		   "by using %.2f CPU seconds."
+		   "<br/>%d+%d/%d request%s were sent uncompressed "
+		   "due to lack of gzip support", 
+		   (before-after)/1024.0/1024.0, before/1024.0/1024.0,
+		   (before-after)*100 / (before+0.1), time_spent,
+		   nowant,nosupport, fixed, ((nowant+nosupport)==1?"":"s"));
+}
+
+mapping filter( mapping result, RequestID id )
+{
+  int len;
+  if(  id->misc->internal_get
+    || id->misc->gzippedalready
+    || !result
+    || !stringp(result->data)
+    || String.width(result->data)>8
+    || (len=sizeof(result->data))<=query("minfilesize")
+    || result->type
+     && !has_prefix(result->type, "text/")
+     && !has_prefix(result->type, "application/x-javascript"))
+    return 0;
+
+  id->misc->gzippedalready = 1;
+  before+=len;
+  fixed++;
+  if( (id->cookies->gzip != "1"
+      && (!id->request_headers["accept-encoding"] || 
+          !has_value(id->request_headers["accept-encoding"], "gzip" )))
+      || id->cookies->gzip=="0")
+  {
+    if( id->cookies->gzip=="0" )
+      nowant++;
+    else
+      nosupport++;
+    return 0;
+  }
+  time_spent+=gauge {
+    StringFile out=StringFile();
+    Gz._file c = Gz._file(out,"ab");
+    c->setparams(query("compressionlevel"),Gz.DEFAULT_STRATEGY);
+    c->write(result->data);
+    c->close();
+    result->data = out->outdata*"";   // Transform back to single string
+  };
+  after+=sizeof(result->data);
+  result->encoding="gzip";
+}