From a71cb67a1237c450a9cbbd6738c5af3b73ba4c61 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 21 Mar 2020 02:03:44 +0000 Subject: qspawn: reinstate filter support, add gzip filter We'll be supporting gzipped from sqlite3(1) dumps for altid files in future commits. In the future (and if we survive), we may replace Plack::Middleware::Deflater with our own GzipFilter to work better with asynchronous responses without relying on memory-intensive anonymous subs. --- t/gzip_filter.t | 37 +++++++++++++++++++++++++++++++++++++ t/httpd-corner.psgi | 9 +++++++++ t/httpd-corner.t | 25 +++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 t/gzip_filter.t (limited to 't') diff --git a/t/gzip_filter.t b/t/gzip_filter.t new file mode 100644 index 00000000..400214e6 --- /dev/null +++ b/t/gzip_filter.t @@ -0,0 +1,37 @@ +# Copyright (C) 2020 all contributors +# License: AGPL-3.0+ +use strict; +use Test::More; +use IO::Handle (); # autoflush +use Fcntl qw(SEEK_SET); +use PublicInbox::TestCommon; +require_mods(qw(Compress::Zlib IO::Uncompress::Gunzip)); +require_ok 'PublicInbox::GzipFilter'; + +{ + open my $fh, '+>', undef or die "open: $!"; + open my $dup, '>&', $fh or die "dup $!"; + $dup->autoflush(1); + my $filter = PublicInbox::GzipFilter->new->attach($dup); + ok($filter->write("hello"), 'wrote something'); + ok($filter->write("world"), 'wrote more'); + $filter->close; + seek($fh, 0, SEEK_SET) or die; + IO::Uncompress::Gunzip::gunzip($fh => \(my $buf)); + is($buf, 'helloworld', 'buffer matches'); +} + +{ + pipe(my ($r, $w)) or die "pipe: $!"; + $w->autoflush(1); + close $r or die; + my $filter = PublicInbox::GzipFilter->new->attach($w); + my $sigpipe; + local $SIG{PIPE} = sub { $sigpipe = 1 }; + open my $fh, '<', 'COPYING' or die "open(COPYING): $!"; + my $buf = do { local $/; <$fh> }; + while ($filter->write($buf .= rand)) {} + ok($sigpipe, 'got SIGPIPE'); + close $w; +} +done_testing; diff --git a/t/httpd-corner.psgi b/t/httpd-corner.psgi index 35d1216e..f2427234 100644 --- a/t/httpd-corner.psgi +++ b/t/httpd-corner.psgi @@ -85,6 +85,15 @@ my $app = sub { close $null; [ 200, [ qw(Content-Type application/octet-stream) ]]; }); + } elsif ($path eq '/psgi-return-gzip') { + require PublicInbox::Qspawn; + require PublicInbox::GzipFilter; + my $cmd = [qw(echo hello world)]; + my $qsp = PublicInbox::Qspawn->new($cmd); + $env->{'qspawn.filter'} = PublicInbox::GzipFilter->new; + return $qsp->psgi_return($env, undef, sub { + [ 200, [ qw(Content-Type application/octet-stream)]] + }); } elsif ($path eq '/pid') { $code = 200; push @$body, "$$\n"; diff --git a/t/httpd-corner.t b/t/httpd-corner.t index c99e5ec7..e50aa436 100644 --- a/t/httpd-corner.t +++ b/t/httpd-corner.t @@ -22,6 +22,7 @@ my $err = "$tmpdir/stderr.log"; my $out = "$tmpdir/stdout.log"; my $psgi = "./t/httpd-corner.psgi"; my $sock = tcp_server() or die; +my @zmods = qw(PublicInbox::GzipFilter IO::Uncompress::Gunzip); # make sure stdin is not a pipe for lsof test to check for leaking pipes open(STDIN, '<', '/dev/null') or die 'no /dev/null: $!'; @@ -324,6 +325,14 @@ SKIP: { close $fh or die "curl errored out \$?=$?"; is($n, 30 * 1024 * 1024, 'got expected output from curl'); is($non_zero, 0, 'read all zeros'); + + require_mods(@zmods, 1); + open $fh, '-|', qw(curl -sS), "$base/psgi-return-gzip" or die; + binmode $fh; + my $buf = do { local $/; <$fh> }; + close $fh or die "curl errored out \$?=$?"; + IO::Uncompress::Gunzip::gunzip(\$buf => \(my $out)); + is($out, "hello world\n"); } { @@ -596,6 +605,22 @@ SKIP: { is_deeply([], [keys %child], 'no extra pipes with -W0'); }; +# ensure compatibility with other PSGI servers +SKIP: { + require_mods(@zmods, qw(Plack::Test HTTP::Request::Common), 3); + use_ok 'HTTP::Request::Common'; + use_ok 'Plack::Test'; + my $app = require $psgi; + test_psgi($app, sub { + my ($cb) = @_; + my $req = GET('http://example.com/psgi-return-gzip'); + my $res = $cb->($req); + my $buf = $res->content; + IO::Uncompress::Gunzip::gunzip(\$buf => \(my $out)); + is($out, "hello world\n"); + }); +} + done_testing(); sub capture { -- cgit v1.2.3-24-ge0c7