We are generating possibly large HTML pages (60-150kB) with embperl.
The pages benefit tremendously by compressing them on the fly
(resulting in 2-4 kb transfer size) and this is how its done (its
working since yesterday):

- if you are modifiying headers in the embperl code (eg. late
redirection) you can't use Apache::OutputChain and Apache::GzipChain
since the headers are already out before the content is generated

- so you should use Ken's Apache::Filter (v1.005 from CPAN) which is
more clever. It caches the whole page and gives you a chance to modify
headers while you are generating the page. (Hey Ken, leave the caching
for now :)

- So I took Apache::EmbperlFilter from Mike Schout <[EMAIL PROTECTED]> and
rewrote Apache::GzipChain a little to adapt to Apache::Filter

- You *need* a second filter after the Embperl Filter to have a chance
of modifying headers because Apache::Filter sends headers after using
$r->filter_input;

- In httpd.conf you have

PerlModule Apache::Filter

<FilesMatch "*.html">
SetHandler perl-script
Options ExecCGI
PerlSetVar Filter On
PerlHandler Apache::EmbperlFilter Apache::GzipFilter
</FilesMatch>

Apache-EmbperlFiler.pm from Mike:

-------------------------------------------------------------
package Apache::EmbperlFilter;

use Apache::Util qw(parsedate);
use HTML::Embperl;
use Apache::Constants;

use strict;
use vars qw($VERSION);

$VERSION = '0.03lu';
my ($r, %param, $input, $output);

sub handler {
    $r = shift;
    my ($fh, $status) = $r->filter_input();
    unless ($status == OK) {
        return $status 
    }   
    $r->deterministic(0);    # added this but does it mean that embperl
    local $/ = undef;        # compiles every time???
    $input = scalar(<$fh>);
    $param{input} = \$input;
    $param{req_rec} = $r;
    $param{output} = \$output;
    $param{mtime} = mtime();
    $param{inputfile} = $r->filename;   # added this
    $/ = "\n";                          # Hey Mike you need this!
    HTML::Embperl::ScanEnvironement(\%param);
    HTML::Embperl::Execute(\%param);
    print $output;
    return OK;
}

sub mtime {
    my $mtime = undef;
    if (my $last_modified = $r->headers_out->{'Last-Modified'}) {
        $mtime = parsedate $last_modified;
    }
    $mtime;
}

1;
--------------------------------------------------------------

and Apache-GzipFilter.pm (borrowed from Andreas Koenig from
Apache::GzipChain):

--------------------------------------------------------------
package Apache::GzipFilter;

use Apache::Constants;

use strict;
use vars qw($VERSION);

$VERSION = '0.01lu';
my ($r, %param, $input, $output);

sub handler {
    $r = shift;

    my $can_gzip;
    my @vary = $r->header_out('Vary') if $r->header_out('Vary');
    push @vary, "Accept-Encoding", "User-Agent";
    $r->header_out('Vary',
                   join ", ",
                   @vary
                  );
    my($accept_encoding) = $r->header_in("Accept-Encoding");
    $can_gzip = 1 if index($accept_encoding, 'gzip') >= 0;
    unless ($can_gzip) {
      my $user_agent = $r->header_in("User-Agent");
      if ($user_agent =~ m{
                           ^Mozilla/
                           \d+
                           \.
                           \d+
                           [\s\[\]\w\-]+
                           (
                            \(X11 |
                            Macint.+PPC,\sNav
                           )
                          }x
         ) {
        $can_gzip = 1;
      }
    }

    $r->header_out('Content-Encoding', 'gzip')
      if $can_gzip;

    my ($fh, $status) = $r->filter_input();
    return $status unless $status == OK;

    local $/ = undef;
    while (<$fh>) {
      if ($can_gzip) {
        print Compress::Zlib::memGzip($_);
      } else {
        print;
      }
    }
    return OK;
}

1;

---------------------------------------------------------------------

Have fun,

Dirk

Reply via email to