]> Sergey Matveev's repositories - public-inbox.git/blob - t/httpd-corner.psgi
www_coderepo: an alternative to cgit
[public-inbox.git] / t / httpd-corner.psgi
1 # Copyright (C) all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3 # corner case tests for the generic PSGI server
4 # Usage: plackup [OPTIONS] /path/to/this/file
5 use v5.12;
6 use warnings;
7 use Plack::Builder;
8 require Digest::SHA;
9 my $pi_config = $ENV{PI_CONFIG} // 'unset'; # capture ASAP
10 my $app = sub {
11         my ($env) = @_;
12         my $path = $env->{PATH_INFO};
13         my $in = $env->{'psgi.input'};
14         my $actual = -s $in;
15         my $code = 500;
16         my $h = [ 'Content-Type' => 'text/plain' ];
17         my $body = [];
18         if ($path eq '/sha1') {
19                 my $sha1 = Digest::SHA->new('SHA-1');
20                 my $buf;
21                 while (1) {
22                         my $r = $in->read($buf, 4096);
23                         die "read err: $!" unless defined $r;
24                         last if $r == 0;
25                         $sha1->add($buf);
26                 }
27                 $code = 200;
28                 push @$body, $sha1->hexdigest;
29         } elsif (my $fifo = $env->{HTTP_X_CHECK_FIFO}) {
30                 if ($path eq '/slow-header') {
31                         return sub {
32                                 open my $f, '<', $fifo or
33                                                 die "open $fifo: $!\n";
34                                 local $/ = "\n";
35                                 my @r = <$f>;
36                                 $_[0]->([200, $h, \@r ]);
37                         };
38                 } elsif ($path eq '/slow-body') {
39                         return sub {
40                                 my $fh = $_[0]->([200, $h]);
41                                 open my $f, '<', $fifo or
42                                                 die "open $fifo: $!\n";
43                                 local $/ = "\n";
44                                 while (defined(my $l = <$f>)) {
45                                         $fh->write($l);
46                                 }
47                                 $fh->close;
48                         };
49                 }
50         } elsif ($path eq '/host-port') {
51                 $code = 200;
52                 push @$body, "$env->{REMOTE_ADDR} $env->{REMOTE_PORT}";
53         } elsif ($path eq '/callback') {
54                 return sub {
55                         my ($res) = @_;
56                         my $buf = "hello world\n";
57                         push @$h, 'Content-Length', length($buf);
58                         my $fh = $res->([200, $h]);
59                         $fh->write($buf);
60                         $fh->close;
61                 }
62         } elsif ($path eq '/empty') {
63                 $code = 200;
64         } elsif ($path eq '/getline-die') {
65                 $code = 200;
66                 $body = Plack::Util::inline_object(
67                         getline => sub { die 'GETLINE FAIL' },
68                         close => sub { die 'CLOSE FAIL' },
69                 );
70         } elsif ($path eq '/close-die') {
71                 $code = 200;
72                 $body = Plack::Util::inline_object(
73                         getline => sub { undef },
74                         close => sub { die 'CLOSE FAIL' },
75                 );
76         } elsif ($path eq '/async-big') {
77                 require PublicInbox::Qspawn;
78                 open my $null, '>', '/dev/null' or die;
79                 my $rdr = { 2 => fileno($null) };
80                 my $cmd = [qw(dd if=/dev/zero count=30 bs=1024k)];
81                 my $qsp = PublicInbox::Qspawn->new($cmd, undef, $rdr);
82                 return $qsp->psgi_return($env, undef, sub {
83                         my ($r, $bref) = @_;
84                         # make $rd_hdr retry sysread + $parse_hdr in Qspawn:
85                         return until length($$bref) > 8000;
86                         close $null;
87                         [ 200, [ qw(Content-Type application/octet-stream) ]];
88                 });
89         } elsif ($path eq '/psgi-return-gzip') {
90                 require PublicInbox::Qspawn;
91                 require PublicInbox::GzipFilter;
92                 my $cmd = [qw(echo hello world)];
93                 my $qsp = PublicInbox::Qspawn->new($cmd);
94                 $env->{'qspawn.filter'} = PublicInbox::GzipFilter->new;
95                 return $qsp->psgi_return($env, undef, sub {
96                         [ 200, [ qw(Content-Type application/octet-stream)]]
97                 });
98         } elsif ($path eq '/psgi-return-compressible') {
99                 require PublicInbox::Qspawn;
100                 my $cmd = [qw(echo goodbye world)];
101                 my $qsp = PublicInbox::Qspawn->new($cmd);
102                 return $qsp->psgi_return($env, undef, sub {
103                         [200, [qw(Content-Type text/plain)]]
104                 });
105         } elsif ($path eq '/psgi-return-enoent') {
106                 require PublicInbox::Qspawn;
107                 my $cmd = [ 'this-better-not-exist-in-PATH'.rand ];
108                 my $qsp = PublicInbox::Qspawn->new($cmd);
109                 return $qsp->psgi_return($env, undef, sub {
110                         [ 200, [ qw(Content-Type application/octet-stream)]]
111                 });
112         } elsif ($path eq '/pid') {
113                 $code = 200;
114                 push @$body, "$$\n";
115         } elsif ($path eq '/url_scheme') {
116                 $code = 200;
117                 push @$body, $env->{'psgi.url_scheme'}
118         } elsif ($path eq '/PI_CONFIG') {
119                 $code = 200;
120                 push @$body, $pi_config; # show value at ->refresh_groups
121         }
122         [ $code, $h, $body ]
123 };
124
125 builder {
126         enable 'ContentLength';
127         enable 'Head';
128         $app;
129 }