X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FNewsWWW.pm;h=d7dd637ff8b681e37f0a483148cd860c08bd477c;hb=af0b0fb7a454470a32c452119d0392e0dedb3fe1;hp=8626cf96eaba44acee92a10a2aa3d84fcb7ab788;hpb=6e6f7999361925e4c944f308df4bc32a1842cd69;p=public-inbox.git diff --git a/lib/PublicInbox/NewsWWW.pm b/lib/PublicInbox/NewsWWW.pm index 8626cf96..d7dd637f 100644 --- a/lib/PublicInbox/NewsWWW.pm +++ b/lib/PublicInbox/NewsWWW.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2019 all contributors +# Copyright (C) 2016-2021 all contributors # License: AGPL-3.0+ # # Plack app redirector for mapping /$NEWSGROUP requests to @@ -10,11 +10,11 @@ use strict; use warnings; use PublicInbox::Config; use PublicInbox::MID qw(mid_escape); +use PublicInbox::Hval qw(prurl); sub new { - my ($class, $pi_config) = @_; - $pi_config ||= PublicInbox::Config->new; - bless { pi_config => $pi_config }, $class; + my ($class, $pi_cfg) = @_; + bless { pi_cfg => $pi_cfg // PublicInbox::Config->new }, $class; } sub redirect ($$) { @@ -24,16 +24,19 @@ sub redirect ($$) { [ "Redirecting to $url\n" ] ] } -sub try_inbox ($$) { - my ($ibx, $mid) = @_; +sub try_inbox { + my ($ibx, $arg) = @_; + return if scalar(@$arg) > 1; + # do not pass $env since HTTP_HOST may differ my $url = $ibx->base_url or return; + my ($mid) = @$arg; eval { $ibx->mm->num_for($mid) } or return; # 302 since the same message may show up on # multiple inboxes and inboxes can be added/reordered - redirect(302, $url .= mid_escape($mid) . '/'); + $arg->[1] = redirect(302, $url .= mid_escape($mid) . '/'); } sub call { @@ -43,11 +46,11 @@ sub call { # /inbox.foo.bar/123456 my (undef, @parts) = split(m!/!, $env->{PATH_INFO}); my ($ng, $article) = @parts; - my $pi_config = $self->{pi_config}; - if (my $ibx = $pi_config->lookup_newsgroup($ng)) { - my $url = PublicInbox::Hval::prurl($env, $ibx->{url}); + my $pi_cfg = $self->{pi_cfg}; + if (my $ibx = $pi_cfg->lookup_newsgroup($ng)) { + my $url = prurl($env, $ibx->{url}); my $code = 301; - if (defined $article && $article =~ /\A\d+\z/) { + if (defined $article && $article =~ /\A[0-9]+\z/) { my $mid = eval { $ibx->mm->mid_for($article) }; if (defined $mid) { # article IDs are not stable across clones, @@ -59,7 +62,6 @@ sub call { return redirect($code, $url); } - my $res; my @try = (join('/', @parts)); # trailing slash is in the rest of our WWW, so maybe some users @@ -68,14 +70,30 @@ sub call { pop @parts; push @try, join('/', @parts); } - - foreach my $mid (@try) { - $pi_config->each_inbox(sub { - $res ||= try_inbox($_[0], $mid); - }); - last if defined $res; + my $ALL = $pi_cfg->ALL; + if (my $over = $ALL ? $ALL->over : undef) { + my $by_eidx_key = $pi_cfg->{-by_eidx_key}; + for my $mid (@try) { + my ($id, $prev); + while (my $x = $over->next_by_mid($mid, \$id, \$prev)) { + my $xr3 = $over->get_xref3($x->{num}); + for (@$xr3) { + s/:[0-9]+:$x->{blob}\z// or next; + my $ibx = $by_eidx_key->{$_} // next; + my $url = $ibx->base_url or next; + $url .= mid_escape($mid) . '/'; + return redirect(302, $url); + } + } + } + } else { # slow path, scan every inbox + for my $mid (@try) { + my $arg = [ $mid ]; # [1] => result + $pi_cfg->each_inbox(\&try_inbox, $arg); + return $arg->[1] if $arg->[1]; + } } - $res || [ 404, [qw(Content-Type text/plain)], ["404 Not Found\n"] ]; + [ 404, [qw(Content-Type text/plain)], ["404 Not Found\n"] ]; } 1;