roxen.lists.roxen.general

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

>  server/modules/filters/gziponthefly.pike |  102 ++++++++++++++++++++++++++++++

Just recently, Marty (cc'd) made an experimental patch to get
compression directly in the http protocol. One reason to do that was
to make it happen after the protocol module has fixed the charset
encoding. Another is that it can be tied in with the protocol cache
(it might not be wise to spend cpu on compressing dynamic answers).

Maybe you can compare solutions?


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";
+}