diff options
author | Eric Wong <e@80x24.org> | 2015-09-05 08:56:54 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2015-09-05 08:58:51 +0000 |
commit | daeb042141ce15a6f8b46da9d600ab4b417c93a1 (patch) | |
tree | 777ffb70f9b3af271972529533119f37da6aa030 /lib/PublicInbox | |
parent | 79601e109dc8162b4c62f7c63cfc6518b0f00112 (diff) | |
download | public-inbox-daeb042141ce15a6f8b46da9d600ab4b417c93a1.tar.gz |
In case a URL gets truncated (as is common with long URLs), we can rely on Xapian for partial matches and bring the user to their destination.
Diffstat (limited to 'lib/PublicInbox')
-rw-r--r-- | lib/PublicInbox/ExtMsg.pm | 45 | ||||
-rw-r--r-- | lib/PublicInbox/Search.pm | 9 | ||||
-rw-r--r-- | lib/PublicInbox/WWW.pm | 1 |
3 files changed, 49 insertions, 6 deletions
diff --git a/lib/PublicInbox/ExtMsg.pm b/lib/PublicInbox/ExtMsg.pm index 7cf696d4..243b6bad 100644 --- a/lib/PublicInbox/ExtMsg.pm +++ b/lib/PublicInbox/ExtMsg.pm @@ -23,7 +23,7 @@ sub ext_msg { eval { require PublicInbox::Search }; my $have_xap = $@ ? 0 : 1; - my @nox; + my (@nox, @pfx); foreach my $k (keys %$pi_config) { $k =~ /\Apublicinbox\.([A-Z0-9a-z-]+)\.url\z/ or next; @@ -40,8 +40,9 @@ sub ext_msg { # try to find the URL with Xapian to avoid forking if ($have_xap) { + my $s; my $doc_id = eval { - my $s = PublicInbox::Search->new($git_dir); + $s = PublicInbox::Search->new($git_dir); $s->find_unique_doc_id('mid', $mid); }; if ($@) { @@ -53,6 +54,7 @@ sub ext_msg { # no point in trying the fork fallback if we # know Xapian is up-to-date but missing the # message in the current repo + push @pfx, { srch => $s, url => $url }; next; } } @@ -82,19 +84,50 @@ sub ext_msg { } } + # fall back to partial MID matching + my $n_partial = 0; + my @partial; + if ($have_xap) { + my $cgi = $ctx->{cgi}; + my $url = ref($cgi) eq 'CGI' ? $cgi->url(-base) . '/' + : $cgi->base->as_string; + $url .= $listname; + unshift @pfx, { srch => $ctx->{srch}, url => $url }; + foreach my $pfx (@pfx) { + my $srch = delete $pfx->{srch} or next; + if (my $res = $srch->mid_prefix($mid)) { + $n_partial += scalar(@$res); + $pfx->{res} = $res; + push @partial, $pfx; + } + } + } my $code = 404; my $h = PublicInbox::Hval->new_msgid($mid, 1); my $href = $h->as_href; my $html = $h->as_html; my $title = "Message-ID <$html> not found"; - - # Fall back to external repos if configured my $s = "<html><head><title>$title</title>" . - "</head><body><pre><b>$title</b>"; + "</head><body><pre><b>$title</b>\n"; + if ($n_partial) { + $code = 300; + $s.= "\nPartial matches found:\n\n"; + foreach my $pfx (@partial) { + my $u = $pfx->{url}; + foreach my $m (@{$pfx->{res}}) { + $h = PublicInbox::Hval->new($m); + $href = $h->as_href; + $html = $h->as_html; + $s .= qq{<a\nhref="$u/$href/">$u/$html/</a>\n}; + } + } + } + + # Fall back to external repos if configured if (@EXT_URL) { $code = 300; - $s .= "\n\nPerhaps try an external site:\n\n"; + $s .= "\nPerhaps try an external site:\n\n"; foreach my $u (@EXT_URL) { my $r = sprintf($u, $href); my $t = sprintf($u, $html); diff --git a/lib/PublicInbox/Search.pm b/lib/PublicInbox/Search.pm index 20650554..e7ea96c7 100644 --- a/lib/PublicInbox/Search.pm +++ b/lib/PublicInbox/Search.pm @@ -269,4 +269,13 @@ sub enquire { $self->{enquire} ||= Search::Xapian::Enquire->new($self->{xdb}); } +sub mid_prefix { + my ($self, $mpfx) = @_; + my $query = eval { $self->qp->parse_query("m:$mpfx", FLAG_PARTIAL) }; + return if $@; + my $res = $self->do_enquire($query, { relevance => 1 }); + return unless $res->{total}; + [ map { $_->mid } @{$res->{msgs}} ]; +} + 1; diff --git a/lib/PublicInbox/WWW.pm b/lib/PublicInbox/WWW.pm index 2718854c..8f155063 100644 --- a/lib/PublicInbox/WWW.pm +++ b/lib/PublicInbox/WWW.pm @@ -79,6 +79,7 @@ sub r404 { my ($ctx) = @_; if ($ctx && $ctx->{mid}) { require PublicInbox::ExtMsg; + searcher($ctx); return PublicInbox::ExtMsg::ext_msg($ctx); } r(404, 'Not Found'); |