public-inbox.cgi | 21 +++++++++++++++++++++ t/cgi.t | 8 ++++++++ diff --git a/public-inbox.cgi b/public-inbox.cgi index 1765cf4549bc51b334ee5061e2176df0a3038040..17eb5b7beb4e0626c7bf6e135f5587cbce0d48a5 100755 --- a/public-inbox.cgi +++ b/public-inbox.cgi @@ -46,6 +46,12 @@ # private functions below sub main { + # some servers (Ruby webrick) include scheme://host[:port] here, + # which confuses CGI.pm when generating self_url. + # RFC 3875 does not mention REQUEST_URI at all, + # so nuke it since CGI.pm functions without it. + delete $ENV{REQUEST_URI}; + my $cgi = CGI->new; my %ctx; if ($cgi->request_method !~ /\AGET|HEAD\z/) { @@ -77,6 +83,8 @@ invalid_list_mid(\%ctx, $1, $2) || get_full_html(\%ctx, $cgi); } elsif ($path_info =~ m!$LISTNAME_RE/f/(\S+)\z!o) { redirect_mid_html($cgi, $1, $2); + } elsif ($path_info =~ m!$LISTNAME_RE\z!o) { + invalid_list(\%ctx, $1) || redirect_list_index(\%ctx, $cgi); } else { r404(); } @@ -180,6 +188,19 @@ require PublicInbox::View; require Email::MIME; [ "200 OK", {'Content-Type' => 'text/html'}, PublicInbox::View->as_html(Email::MIME->new($$x))]; +} + +sub redirect_list_index { + my ($ctx, $cgi) = @_; + do_redirect($cgi->self_url . "/"); +} + +sub do_redirect { + my ($url) = @_; + [ '301 Moved Permanently', + { Location => $url, 'Content-Type' => 'text/plain' }, + "Redirecting to $url\n" + ] } # only used for CGI and static file generation modes diff --git a/t/cgi.t b/t/cgi.t index ae7cc730e7203ea1c1c5991233d52a7dff7597ea..c8755541211ffd3757480ba8b519a851a17e0831 100644 --- a/t/cgi.t +++ b/t/cgi.t @@ -181,6 +181,14 @@ like($res->{body}, qr/slashy%2Fasdf%40example\.com/, "slashy URL generated correctly"); } +# redirect list-name-only URLs +{ + local $ENV{HOME} = $home; + my $res = cgi_run("/test"); + like($res->{head}, qr/Status: 301 Moved/, "redirected status"); + like($res->{head}, qr!/test/!, "redirected with slash"); +} + done_testing(); sub run_with_env {