# Qspawn filter
package PublicInbox::GzipFilter;
use strict;
+use parent qw(Exporter);
use Compress::Raw::Zlib qw(Z_FINISH Z_OK);
+our @EXPORT_OK = qw(gzip_maybe);
my %OPT = (-WindowBits => 15 + 16, -AppendOutput => 1);
sub new { bless {}, shift }
$self
}
+sub gzip_maybe ($) {
+ my ($env) = @_;
+ return if (($env->{HTTP_ACCEPT_ENCODING}) // '') !~ /\bgzip\b/;
+
+ # in case Plack::Middleware::Deflater is loaded:
+ $env->{'plack.skip-deflater'} = 1;
+
+ my ($gz, $err) = Compress::Raw::Zlib::Deflate->new(%OPT);
+ $err == Z_OK ? $gz : undef;
+}
+
# for GetlineBody (via Qspawn) when NOT using $env->{'pi-httpd.async'}
sub translate ($$) {
my $self = $_[0];
our @EXPORT_OK = qw(html_oneshot);
use bytes (); # length
use PublicInbox::Hval qw(ascii_html prurl);
+use Compress::Raw::Zlib qw(Z_FINISH Z_OK);
+use PublicInbox::GzipFilter qw(gzip_maybe);
our $TOR_URL = 'https://www.torproject.org/';
our $CODE_URL = 'https://public-inbox.org/public-inbox.git';
ctx => $ctx,
base_url => base_url($ctx),
}, __PACKAGE__;
- my @x = (_html_top($self), $sref ? $$sref : (), _html_end($self));
+ my @x;
+ my @h = ('Content-Type' => 'text/html; charset=UTF-8');
+ if (my $gz = gzip_maybe($ctx->{env})) {
+ my $err = $gz->deflate(_html_top($self), $x[0]);
+ die "gzip->deflate: $err" if $err != Z_OK;
+ if ($sref) {
+ $err = $gz->deflate($sref, $x[0]);
+ die "gzip->deflate: $err" if $err != Z_OK;
+ }
+ $err = $gz->deflate(_html_end($self), $x[0]);
+ die "gzip->deflate: $err" if $err != Z_OK;
+ $err = $gz->flush($x[0], Z_FINISH);
+ die "gzip->flush: $err" if $err != Z_OK;
+ push @h, qw(Vary Accept-Encoding Content-Encoding gzip);
+ } else {
+ @x = (_html_top($self), $sref ? $$sref : (), _html_end($self));
+ }
+
my $len = 0;
$len += bytes::length($_) for @x;
- [ $code, [
- 'Content-Type' => 'text/html; charset=UTF-8',
- 'Content-Length' => $len
- ], \@x ];
+ push @h, 'Content-Length', $len;
+ [ $code, \@h, \@x ]
}
1;