X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FWwwStatic.pm;h=1c1a3d38d6e7c5fd9a8c479b5dc013809b66405b;hb=HEAD;hp=547b75bba01c369d7caa75a07ac3ed1fcac9d28b;hpb=fcfa0d639da338c470f07942da71f78fa65354a1;p=public-inbox.git diff --git a/lib/PublicInbox/WwwStatic.pm b/lib/PublicInbox/WwwStatic.pm index 547b75bb..1c1a3d38 100644 --- a/lib/PublicInbox/WwwStatic.pm +++ b/lib/PublicInbox/WwwStatic.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2019 all contributors +# Copyright (C) 2016-2021 all contributors # License: AGPL-3.0+ # This package can either be a PSGI response body for a static file @@ -9,14 +9,15 @@ # functionality of nginx. package PublicInbox::WwwStatic; use strict; +use v5.10.1; use parent qw(Exporter); -use bytes (); use Fcntl qw(SEEK_SET O_RDONLY O_NONBLOCK); use POSIX qw(strftime); use HTTP::Date qw(time2str); use HTTP::Status qw(status_message); use Errno qw(EACCES ENOTDIR ENOENT); use URI::Escape qw(uri_escape_utf8); +use PublicInbox::GzipFilter qw(gzf_maybe); use PublicInbox::Hval qw(ascii_html); use Plack::MIME; our @EXPORT_OK = qw(@NO_CACHE r path_info_raw); @@ -117,7 +118,9 @@ sub try_gzip_static ($$$$) { return unless -f $gz && (stat(_))[9] == $mtime; my $res = response($env, $h, $gz, $type); return if ($res->[0] > 300 || $res->[0] < 200); - push @{$res->[1]}, qw(Cache-Control no-transform Content-Encoding gzip); + push @{$res->[1]}, qw(Cache-Control no-transform + Content-Encoding gzip + Vary Accept-Encoding); $res; } @@ -215,7 +218,7 @@ my %path_re_cache; sub path_info_raw ($) { my ($env) = @_; my $sn = $env->{SCRIPT_NAME}; - my $re = $path_re_cache{$sn} ||= do { + my $re = $path_re_cache{$sn} //= do { $sn = '/'.$sn unless index($sn, '/') == 0; $sn =~ s!/\z!!; qr!\A(?:https?://[^/]+)?\Q$sn\E(/[^\?\#]+)!; @@ -272,12 +275,11 @@ sub dir_response ($$$) { my $path_info = $env->{PATH_INFO}; push @entries, '..' if $path_info ne '/'; for my $base (@entries) { + my @st = stat($fs_path . $base) or next; # unlikely my $href = ascii_html(uri_escape_utf8($base)); my $name = ascii_html($base); - my @st = stat($fs_path . $base) or next; # unlikely - my ($gzipped, $uncompressed, $hsize); - my $entry = ''; my $mtime = $st[9]; + my ($entry, $hsize); if (-d _) { $href .= '/'; $name .= '/'; @@ -293,12 +295,12 @@ sub dir_response ($$$) { next; } # 54 = 80 - (SP length(strftime(%Y-%m-%d %k:%M)) SP human_size) - $hsize = sprintf('% 8s', $hsize); my $pad = 54 - length($name); $pad = 1 if $pad <= 0; - $entry .= qq($name) . (' ' x $pad); - $mtime = strftime('%Y-%m-%d %k:%M', gmtime($mtime)); - $entry .= $mtime . $hsize; + $entry = qq(\n$name) . + (' ' x $pad) . + strftime('%Y-%m-%d %k:%M', gmtime($mtime)) . + sprintf('% 8s', $hsize); } # filter out '.gz' files as long as the mtime matches the @@ -306,14 +308,16 @@ sub dir_response ($$$) { delete(@other{keys %want_gz}); @entries = ((map { ${$dirs{$_}} } sort keys %dirs), (map { ${$other{$_}} } sort keys %other)); - my $path_info_html = ascii_html($path_info); - my $body = "Index of $path_info_html" . - ${$self->{style}} . - "
Index of $path_info_html

\n";
-	$body .= join("\n", @entries) . "

\n"; - [ 200, [ qw(Content-Type text/html - Content-Length), bytes::length($body) ], [ $body ] ] + my @h = qw(Content-Type text/html); + my $gzf = gzf_maybe(\@h, $env); + print { $gzf->zfh } 'Index of ', $path_info_html, + '', ${$self->{style}}, '
Index of ',
+		$path_info_html, '

', @entries,
+		'

'; + my $out = $gzf->zflush; + push @h, 'Content-Length', length($out); + [ 200, \@h, [ $out ] ] } sub call { # PSGI app endpoint