]> Sergey Matveev's repositories - public-inbox.git/commitdiff
implement external Message-ID finder
authorEric Wong <e@80x24.org>
Wed, 2 Sep 2015 02:37:23 +0000 (02:37 +0000)
committerEric Wong <e@80x24.org>
Wed, 2 Sep 2015 06:51:27 +0000 (06:51 +0000)
Currently, this looks at other public-inbox configurations
served in the same process.  In the future, it will generate
links to other Message-ID lookup endpoints.

lib/PublicInbox/ExtMsg.pm [new file with mode: 0644]
lib/PublicInbox/View.pm
lib/PublicInbox/WWW.pm
public-inbox.cgi

diff --git a/lib/PublicInbox/ExtMsg.pm b/lib/PublicInbox/ExtMsg.pm
new file mode 100644 (file)
index 0000000..1c0887c
--- /dev/null
@@ -0,0 +1,92 @@
+# Copyright (C) 2015 all contributors <meta@public-inbox.org>
+# License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
+package PublicInbox::ExtMsg;
+use strict;
+use warnings;
+use URI::Escape qw(uri_escape_utf8);
+use PublicInbox::Hval;
+use PublicInbox::MID qw/mid_compress mid2path/;
+
+sub ext_msg {
+       my ($ctx) = @_;
+       my $pi_config = $ctx->{pi_config};
+       my $listname = $ctx->{listname};
+       my $mid = $ctx->{mid};
+       my $cmid = mid_compress($mid);
+
+       eval { require PublicInbox::Search };
+       my $have_xap = $@ ? 0 : 1;
+       my @nox;
+
+       foreach my $k (keys %$pi_config) {
+               $k =~ /\Apublicinbox\.([A-Z0-9a-z-]+)\.url\z/ or next;
+               my $list = $1;
+               next if $list eq $listname;
+
+               my $git_dir = $pi_config->{"publicinbox.$list.mainrepo"};
+               defined $git_dir or next;
+
+               my $url = $pi_config->{"publicinbox.$list.url"};
+               defined $url or next;
+
+               $url =~ s!/+\z!!;
+
+               # try to find the URL with Xapian to avoid forking
+               if ($have_xap) {
+                       my $doc_id = eval {
+                               my $s = PublicInbox::Search->new($git_dir);
+                               $s->find_unique_doc_id('mid', $cmid);
+                       };
+                       if ($@) {
+                               # xapian not configured for this repo
+                       } else {
+                               # maybe we found it!
+                               return r302($url, $cmid) if (defined $doc_id);
+
+                               # no point in trying the fork fallback if we
+                               # know Xapian is up-to-date but missing the
+                               # message in the current repo
+                               next;
+                       }
+               }
+
+               # queue up for forking after we've tried Xapian on all of them
+               push @nox, { git_dir => $git_dir, url => $url };
+       }
+
+       # Xapian not installed or configured for some repos
+       my $path = "HEAD:" . mid2path($cmid);
+
+       foreach my $n (@nox) {
+               my @cmd = ('git', "--git-dir=$n->{git_dir}", 'cat-file',
+                          '-t', $path);
+               my $pid = open my $fh, '-|';
+               defined $pid or die "fork failed: $!\n";
+
+               if ($pid == 0) {
+                       open STDERR, '>', '/dev/null'; # ignore errors
+                       exec @cmd or die "exec failed: $!\n";
+               } else {
+                       my $type = eval { local $/; <$fh> };
+                       close $fh;
+                       if ($? == 0 && $type eq "blob\n") {
+                               return r302($n->{url}, $cmid);
+                       }
+               }
+       }
+
+       # Fall back to external repos
+
+       [404, ['Content-Type'=>'text/plain'], ['Not found']];
+}
+
+# Redirect to another public-inbox which is mapped by $pi_config
+sub r302 {
+       my ($url, $mid) = @_;
+       $url .= '/' . uri_escape_utf8($mid) . '/';
+       [ 302,
+         [ 'Location' => $url, 'Content-Type' => 'text/plain' ],
+         [ "Redirecting to\n$url\n" ] ]
+}
+
+1;
index 1528a874ada4f5c1256700de5e71e501cd000fda..e18895f1b3ae64b6765377c4586dd1634ac13111 100644 (file)
@@ -164,7 +164,7 @@ sub emit_thread_html {
        my $res = $srch->get_thread($mid);
        my $msgs = load_results($res);
        my $nr = scalar @$msgs;
-       return missing_thread($cb) if $nr == 0;
+       return missing_thread($cb, $ctx) if $nr == 0;
        my $flat = $ctx->{flat};
        my $orig_cb = $cb;
        my $seen = {};
@@ -189,7 +189,7 @@ sub emit_thread_html {
 
        # there could be a race due to a message being deleted in git
        # but still being in the Xapian index:
-       return missing_thread($cb) if ($orig_cb eq $cb);
+       return missing_thread($cb, $ctx) if ($orig_cb eq $cb);
 
        my $final_anchor = $state->{anchor_idx};
        my $next = "<a\nid=\"s$final_anchor\">";
@@ -637,12 +637,10 @@ sub thread_results {
 }
 
 sub missing_thread {
-       my ($cb) = @_;
-       my $title = 'Thread does not exist';
-       $cb->([404, ['Content-Type' => 'text/html']])->write(<<EOF);
-<html><head><title>$title</title></head><body><pre>$title
-<a href="../../">Return to index</a></pre></body></html>
-EOF
+       my ($cb, $ctx) = @_;
+       require PublicInbox::ExtMsg;
+
+       $cb->(PublicInbox::ExtMsg::ext_msg($ctx))
 }
 
 sub _msg_date {
index 9ae7f7be40296ce11f68f9c3416cffb68ab901a8..16fd16aaeb9b26621e42bc5343017440155bbcc3 100644 (file)
@@ -88,7 +88,14 @@ sub preload {
 
 # private functions below
 
-sub r404 { r(404, 'Not Found') }
+sub r404 {
+       my ($ctx) = @_;
+       if ($ctx && $ctx->{mid}) {
+               require PublicInbox::ExtMsg;
+               return PublicInbox::ExtMsg::ext_msg($ctx);
+       }
+       r(404, 'Not Found');
+}
 
 # simple response for errors
 sub r { [ $_[0], ['Content-Type' => 'text/plain'], [ join(' ', @_, "\n") ] ] }
@@ -151,7 +158,7 @@ sub mid2blob {
 # /$LISTNAME/$MESSAGE_ID/raw                    -> raw mbox
 sub get_mid_txt {
        my ($ctx) = @_;
-       my $x = mid2blob($ctx) or return r404();
+       my $x = mid2blob($ctx) or return r404($ctx);
        require PublicInbox::Mbox;
        PublicInbox::Mbox::emit1($x);
 }
@@ -159,7 +166,7 @@ sub get_mid_txt {
 # /$LISTNAME/$MESSAGE_ID/                   -> HTML content (short quotes)
 sub get_mid_html {
        my ($ctx) = @_;
-       my $x = mid2blob($ctx) or return r404();
+       my $x = mid2blob($ctx) or return r404($ctx);
 
        require PublicInbox::View;
        my $foot = footer($ctx);
@@ -173,7 +180,7 @@ sub get_mid_html {
 # /$LISTNAME/$MESSAGE_ID/f/                   -> HTML content (fullquotes)
 sub get_full_html {
        my ($ctx) = @_;
-       my $x = mid2blob($ctx) or return r404();
+       my $x = mid2blob($ctx) or return r404($ctx);
 
        require PublicInbox::View;
        my $foot = footer($ctx);
index 75d510c092b284a685f7158566dadf4029e354d6..1fcc04fa195bcb18a318080fbad6ced743c72d71 100755 (executable)
@@ -18,6 +18,7 @@ BEGIN {
        %HTTP_CODES = (
                200 => 'OK',
                301 => 'Moved Permanently',
+               302 => 'Found',
                404 => 'Not Found',
                405 => 'Method Not Allowed',
                501 => 'Not Implemented',