);
# XXX: cgit filters may care about more variables...
+sub cgit_parse_hdr { # {parse_hdr} for Qspawn
+ my ($r, $bref) = @_;
+ my $res = parse_cgi_headers($r, $bref) or return; # incomplete
+ $res;
+}
+
sub call {
my ($self, $env) = @_;
my $path_info = $env->{PATH_INFO};
my $rdr = input_prepare($env) or return r(500);
my $qsp = PublicInbox::Qspawn->new($self->{cmd}, $cgi_env, $rdr);
my $limiter = $self->{pi_config}->limiter('-cgit');
- $qsp->psgi_return($env, $limiter, sub {
- my ($r, $bref) = @_;
- my $res = parse_cgi_headers($r, $bref) or return; # incomplete
- $res;
- });
+ $qsp->psgi_return($env, $limiter, \&cgit_parse_hdr);
}
1;
($code, $len);
}
+sub git_parse_hdr { # {parse_hdr} for Qspawn
+ my ($r, $bref, $dumb_args) = @_;
+ my $res = parse_cgi_headers($r, $bref) or return; # incomplete
+ $res->[0] == 403 ? serve_dumb(@$dumb_args) : $res;
+}
+
# returns undef if 403 so it falls back to dumb HTTP
sub serve_smart {
my ($env, $git, $path) = @_;
$env{PATH_TRANSLATED} = "$git->{git_dir}/$path";
my $rdr = input_prepare($env) or return r(500);
my $qsp = PublicInbox::Qspawn->new([qw(git http-backend)], \%env, $rdr);
- $qsp->psgi_return($env, $limiter, sub { # parse_hdr
- my ($r, $bref) = @_;
- my $res = parse_cgi_headers($r, $bref) or return; # incomplete
- $res->[0] == 403 ? serve_dumb($env, $git, $path) : $res;
- });
+ $qsp->psgi_return($env, $limiter, \&git_parse_hdr, [$env, $git, $path]);
}
sub input_prepare {
my $ret;
my $total_rd = 0;
my $hdr_buf = $self->{hdr_buf};
+ my ($ph_cb, $ph_arg) = @{$self->{parse_hdr}};
do {
my $r = sysread($self->{rpipe}, $$hdr_buf, 4096,
length($$hdr_buf));
if (defined($r)) {
$total_rd += $r;
- $ret = $self->{parse_hdr}->($total_rd, $hdr_buf);
+ $ret = $ph_cb->($total_rd, $hdr_buf, $ph_arg);
} else {
# caller should notify us when it's ready:
return if $! == EAGAIN;
# psgix.io. 3-element arrays means the body is available
# immediately (or streamed via ->getline (pull-based)).
sub psgi_return {
- my ($self, $env, $limiter, $parse_hdr) = @_;
+ my ($self, $env, $limiter, $parse_hdr, $hdr_arg) = @_;
$self->{psgi_env} = $env;
$self->{hdr_buf} = \(my $hdr_buf = '');
- $self->{parse_hdr} = $parse_hdr;
+ $self->{parse_hdr} = [ $parse_hdr, $hdr_arg ];
$limiter ||= $def_limiter ||= PublicInbox::Qspawn::Limiter->new(32);
# the caller already captured the PSGI write callback from
$wcb ? $wcb->($res) : $res;
}
+sub stream_blob_parse_hdr { # {parse_hdr} for Qspawn
+ my ($r, $bref, $ctx) = @_;
+ my ($res, $logref) = delete @$ctx{qw(-res -logref)};
+ my ($git, $oid, $type, $size, $di) = @$res;
+ my @cl = ('Content-Length', $size);
+ if (!defined $r) { # error
+ html_page($ctx, 500, $logref);
+ } elsif (index($$bref, "\0") >= 0) {
+ [200, [qw(Content-Type application/octet-stream), @cl] ];
+ } else {
+ my $n = bytes::length($$bref);
+ if ($n >= $BIN_DETECT || $n == $size) {
+ return [200, [ 'Content-Type',
+ 'text/plain; charset=UTF-8', @cl ] ];
+ }
+ if ($r == 0) {
+ warn "premature EOF on $oid $$logref\n";
+ return html_page($ctx, 500, $logref);
+ }
+ undef; # bref keeps growing
+ }
+}
+
sub stream_large_blob ($$$$) {
my ($ctx, $res, $logref, $fn) = @_;
+ $ctx->{-logref} = $logref;
+ $ctx->{-res} = $res;
my ($git, $oid, $type, $size, $di) = @$res;
my $cmd = ['git', "--git-dir=$git->{git_dir}", 'cat-file', $type, $oid];
my $qsp = PublicInbox::Qspawn->new($cmd);
- my @cl = ('Content-Length', $size);
my $env = $ctx->{env};
- $env->{'public-inbox.tmpgit'} = $git; # for {-tmp}/File::Temp::Dir
$env->{'qspawn.wcb'} = delete $ctx->{-wcb};
- $qsp->psgi_return($env, undef, sub {
- my ($r, $bref) = @_;
- if (!defined $r) { # error
- html_page($ctx, 500, $logref);
- } elsif (index($$bref, "\0") >= 0) {
- my $ct = 'application/octet-stream';
- [200, ['Content-Type', $ct, @cl ] ];
- } else {
- my $n = bytes::length($$bref);
- if ($n >= $BIN_DETECT || $n == $size) {
- my $ct = 'text/plain; charset=UTF-8';
- return [200, ['Content-Type', $ct, @cl] ];
- }
- if ($r == 0) {
- warn "premature EOF on $oid $$logref\n";
- return html_page($ctx, 500, $logref);
- }
- undef; # bref keeps growing
- }
- });
+ $qsp->psgi_return($env, undef, \&stream_blob_parse_hdr, $ctx);
}
sub show_other_result ($$) {