Plack-Middleware-Zstandard
view release on metacpan or search on metacpan
lib/Plack/Middleware/Zstandard.pm view on Meta::CPAN
use warnings;
use 5.020;
use experimental qw( postderef signatures );
package Plack::Middleware::Zstandard 0.02 {
# ABSTRACT: Compress response body with Zstandard
use parent qw( Plack::Middleware );
use Plack::Util ();
use Plack::Util::Accessor qw( level _constructor_args vary );
use Ref::Util qw( is_plain_arrayref );
use Compress::Stream::Zstd::Compressor ();
sub prepare_app ($self) {
if(defined $self->level) {
$self->_constructor_args([$self->level]);
} else {
$self->_constructor_args([]);
}
}
sub call ($self, $env) {
my $res = $self->app->($env);
$self->response_cb($res, sub ($res) {
return undef if $env->{HTTP_CONTENT_RANGE};
my $h = Plack::Util::headers($res->[1]);
return undef if Plack::Util::status_with_no_entity_body($res->[0]);
return undef if $h->exists('Cache-Control') && $h->get('Cache-Control') =~ /\bno-transform\b/;
if($self->vary // 1) {
my @vary = split /\s*,\s*/, ($h->get('Vary') || '');
push @vary, 'Accept-Encoding';
$h->set('Vary' => join(",", @vary));
}
# Do not clobber already existing encoding
return if $h->exists('Content-Encoding') && $h->get('Content-Encoding') ne 'identity';
return undef unless ($env->{HTTP_ACCEPT_ENCODING} // '') =~ /\bzstd\b/;
$h->set('Content-Encoding' => 'zstd');
$h->remove('Content-Length');
my $compressor = Compress::Stream::Zstd::Compressor->new($self->_constructor_args->@*);
if($res->[2] && is_plain_arrayref $res->[2]) {
$res->[2] = [grep length, map { $compressor->compress($_) } grep defined, $res->[2]->@*];
my $end = $compressor->end;
push $res->[2]->@*, $end if length $end;
return undef;
} else {
return sub ($chunk) {
if(defined $chunk) {
return $compressor->compress($chunk);
} elsif(defined $compressor) {
my $end = $compressor->end;
undef $compressor;
return $end;
} else {
return undef;
}
};
}
});
}
}
( run in 1.081 second using v1.01-cache-2.11-cpan-39bf76dae61 )