about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@yhbt.net>2020-07-05 23:27:20 +0000
committerEric Wong <e@yhbt.net>2020-07-06 20:01:15 +0000
commit20f0d11445fc1207bc3a91e3f47abb4ba1b57256 (patch)
tree213c1850bc35a6a4ea366a7bacbd50052ac59ae7
parentcde937e3bf4c0ad343479f9711a201494e4f36ee (diff)
downloadpublic-inbox-20f0d11445fc1207bc3a91e3f47abb4ba1b57256.tar.gz
Most of our plain-text responses are config files
big enough to warrant compression.
-rw-r--r--lib/PublicInbox/WwwText.pm17
-rw-r--r--t/psgi_text.t33
2 files changed, 40 insertions, 10 deletions
diff --git a/lib/PublicInbox/WwwText.pm b/lib/PublicInbox/WwwText.pm
index b23a415e..508005fb 100644
--- a/lib/PublicInbox/WwwText.pm
+++ b/lib/PublicInbox/WwwText.pm
@@ -10,6 +10,8 @@ use PublicInbox::Linkify;
 use PublicInbox::WwwStream;
 use PublicInbox::Hval qw(ascii_html);
 use URI::Escape qw(uri_escape_utf8);
+use PublicInbox::GzipFilter qw(gzf_maybe);
+use Compress::Raw::Zlib qw(Z_FINISH Z_OK);
 our $QP_URL = 'https://xapian.org/docs/queryparser.html';
 our $WIKI_URL = 'https://en.wikipedia.org/wiki';
 my $hl = eval {
@@ -35,14 +37,23 @@ sub get_text {
                 $code = 404;
                 $txt = "404 Not Found ($key)\n";
         }
+        my $env = $ctx->{env};
         if ($raw) {
-                $hdr->[3] = bytes::length($txt);
-                return [ $code, $hdr, [ $txt ] ]
+                my $body;
+                if (my $gzf = $code == 200 ? gzf_maybe($hdr, $env) : undef) {
+                        my $zbuf = $gzf->translate($txt);
+                        undef $txt;
+                        $body = [ $zbuf .= $gzf->translate(undef) ];
+                } else {
+                        $body = [ $txt ];
+                }
+                $hdr->[3] = bytes::length($body->[0]);
+                return [ $code, $hdr, $body ]
         }
 
         # enforce trailing slash for "wget -r" compatibility
         if (!$have_tslash && $code == 200) {
-                my $url = $ctx->{-inbox}->base_url($ctx->{env});
+                my $url = $ctx->{-inbox}->base_url($env);
                 $url .= "_/text/$key/";
 
                 return [ 302, [ 'Content-Type', 'text/plain',
diff --git a/t/psgi_text.t b/t/psgi_text.t
index 833bcaba..9867feaa 100644
--- a/t/psgi_text.t
+++ b/t/psgi_text.t
@@ -10,7 +10,7 @@ my $maindir = "$tmpdir/main.git";
 my $addr = 'test-public@example.com';
 my $cfgpfx = "publicinbox.test";
 my @mods = qw(HTTP::Request::Common Plack::Test URI::Escape Plack::Builder);
-require_mods(@mods);
+require_mods(@mods, 'IO::Uncompress::Gunzip');
 use_ok $_ foreach @mods;
 use PublicInbox::Import;
 use PublicInbox::Git;
@@ -26,17 +26,36 @@ my $www = PublicInbox::WWW->new($config);
 
 test_psgi(sub { $www->call(@_) }, sub {
         my ($cb) = @_;
-        my $res;
-        $res = $cb->(GET('/test/_/text/help/'));
-        like($res->content, qr!<title>public-inbox help.*</title>!,
-                'default help');
-        $res = $cb->(GET('/test/_/text/config/raw'));
+        my $gunzipped;
+        my $req = GET('/test/_/text/help/');
+        my $res = $cb->($req);
+        my $content = $res->content;
+        like($content, qr!<title>public-inbox help.*</title>!, 'default help');
+        $req->header('Accept-Encoding' => 'gzip');
+        $res = $cb->($req);
+        is($res->header('Content-Encoding'), 'gzip', 'got gzip encoding');
+        is($res->header('Content-Type'), 'text/html; charset=UTF-8',
+                'got gzipped HTML');
+        IO::Uncompress::Gunzip::gunzip(\($res->content) => \$gunzipped);
+        is($gunzipped, $content, 'gzipped content is correct');
+
+        $req = GET('/test/_/text/config/raw');
+        $res = $cb->($req);
+        $content = $res->content;
+        my $olen = $res->header('Content-Length');
         my $f = "$tmpdir/cfg";
         open my $fh, '>', $f or die;
-        print $fh $res->content or die;
+        print $fh $content or die;
         close $fh or die;
         my $cfg = PublicInbox::Config->new($f);
         is($cfg->{"$cfgpfx.address"}, $addr, 'got expected address in config');
+
+        $req->header('Accept-Encoding' => 'gzip');
+        $res = $cb->($req);
+        is($res->header('Content-Encoding'), 'gzip', 'got gzip encoding');
+        ok($res->header('Content-Length') < $olen, 'gzipped help is smaller');
+        IO::Uncompress::Gunzip::gunzip(\($res->content) => \$gunzipped);
+        is($gunzipped, $content);
 });
 
 done_testing();