diff options
author | Eric Wong <e@80x24.org> | 2016-03-07 08:10:54 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2016-04-05 18:58:27 +0000 |
commit | 4e49ab58f0ea6b32e9610a990c5bfe21900dc73b (patch) | |
tree | 8572c4ffa2c7c4a9047611c5330190297029c41e /lib | |
parent | 541b8a4e14c471d4746bfda597691155dae0f960 (diff) | |
download | public-inbox-4e49ab58f0ea6b32e9610a990c5bfe21900dc73b.tar.gz |
We broke this fallback when we became more callback driven and a test will come in the next commit. However, our dumb cloning is still subject to scheduling monopolization when serving gigantic packs. Scheduling will be fixed at a later time. Fixes: b44af5d8f2fb ("git-http-backend: start refactoring to use callback")
Diffstat (limited to 'lib')
-rw-r--r-- | lib/PublicInbox/GitHTTPBackend.pm | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/lib/PublicInbox/GitHTTPBackend.pm b/lib/PublicInbox/GitHTTPBackend.pm index 50bb4331..989dac7f 100644 --- a/lib/PublicInbox/GitHTTPBackend.pm +++ b/lib/PublicInbox/GitHTTPBackend.pm @@ -34,8 +34,15 @@ sub serve { if ($service =~ /\Agit-\w+-pack\z/ || $path =~ /\Agit-\w+-pack\z/) { my $ok = serve_smart($cgi, $git, $path); return $ok if $ok; + # fall through to dumb HTTP... } + serve_dumb($cgi, $git, $path); +} + +sub serve_dumb { + my ($cgi, $git, $path) = @_; + # serve dumb HTTP... my $type; if ($path =~ /\A(?:$BIN)\z/o) { $type = 'application/octet-stream'; @@ -123,7 +130,6 @@ sub prepare_range { ($code, $len); } -# returns undef if 403 so it falls back to dumb HTTP sub serve_smart { my ($cgi, $git, $path) = @_; my $env = $cgi->{env}; @@ -158,7 +164,8 @@ sub serve_smart { my $git_dir = $git->{git_dir}; $env{GIT_HTTP_EXPORT_ALL} = '1'; $env{PATH_TRANSLATED} = "$git_dir/$path"; - my %rdr = ( 0 => fileno($in), 1 => fileno($wpipe) ); + my %rdr = ( 0 => fileno($in), 1 => fileno($wpipe), + 2 => $git->err_begin ); my $pid = spawn([qw(git http-backend)], \%env, \%rdr); unless (defined $pid) { $err->print("error spawning: $!\n"); @@ -202,7 +209,8 @@ sub serve_smart { if ($fh) { # stream body from git-http-backend to HTTP client $fh->write($buf); $buf = ''; - } elsif ($buf =~ s/\A(.*?)\r\n\r\n//s) { # parse headers + } elsif (defined $res && $buf =~ s/\A(.*?)\r\n\r\n//s) { + # parse headers my $h = $1; my $code = 200; my @h; @@ -214,11 +222,23 @@ sub serve_smart { push @h, $k, $v; } } - # write response header: - $fh = $res->([ $code, \@h ]); - $res = undef; - $fh->write($buf); - $buf = ''; + # incredibly convoluted, ugh... + if ($code == 403) { + my $d = serve_dumb($cgi, $git, $path); + if (ref($d) eq 'ARRAY') { # 404 + $res->($d); + } else { + $d->($res); + } + $res = undef; + $end->(); + } else { + # write response header: + $fh = $res->([ $code, \@h ]); + $res = undef; + $fh->write($buf); + $buf = ''; + } } # else { keep reading ... } }; if (my $async = $env->{'pi-httpd.async'}) { |