--- 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. +// <[email protected]> +// +// 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 © 2002-2009, by " + "<a href='mailto:[email protected]'>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 <[email protected]>"); + 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"; +}
