From: Eric Wong Date: Fri, 28 Mar 2025 10:34:10 +0000 (+0000) Subject: daemon: allow per-listener servername= and serverport= X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=243288259c8a52b14064052c3a08960854aad75d;p=thirdparty%2Fpublic-inbox.git daemon: allow per-listener servername= and serverport= Being able to specify per-listener servername= with the `--listen' CLI arg is helpful for running an Tor .onion NNTP server with the same config file (and thus publicinbox.nntpserver) as a public-facing NNTP endpoint. For HTTP, servername= and serverport= allow overriding the SERVER_NAME and SERVER_PORT PSGI environment variables, respectively. These are useful for generating full URLs for clients which don't send the HTTP `Host:' header. These currently have no effect aside from wasting memory for POP3 and IMAP listeners. serverport= isn't used by NNTP, either. --- diff --git a/Documentation/public-inbox-config.pod b/Documentation/public-inbox-config.pod index faf35d673..0e3569614 100644 --- a/Documentation/public-inbox-config.pod +++ b/Documentation/public-inbox-config.pod @@ -330,7 +330,10 @@ Default: none =item publicinbox.nntpserver Same as C, but for the hostname(s) of the -L instance. +L instance. This affects C headers +in responses. As of public-inbox 2.0, this can be overriden on +the C command-line via +C<--listen nntp://$ADDRESS:$PORT/?servername=example.com> Default: none diff --git a/Documentation/public-inbox-daemon.pod b/Documentation/public-inbox-daemon.pod index 092be667b..7496cfca4 100644 --- a/Documentation/public-inbox-daemon.pod +++ b/Documentation/public-inbox-daemon.pod @@ -51,7 +51,8 @@ all if relying on L or similar, Per-listener options may be specified after C as C pairs delimited by C<,>. See L for documentation on the C, C, C, -C, C, and C options available. +C, C, C, C, and C +options available. Default: server-dependent unless socket activation is used with L or similar (see L). diff --git a/Documentation/public-inbox-netd.pod b/Documentation/public-inbox-netd.pod index 71425e3cb..bbf0eb448 100644 --- a/Documentation/public-inbox-netd.pod +++ b/Documentation/public-inbox-netd.pod @@ -50,6 +50,14 @@ C. HTTP(S) users are encouraged to configure L or L, instead. +As of public-inbox 2.0, C and C may +also be specified on a per listener basis. For HTTP(S), +these ensure full URLs are generated properly for HTTP clients +which omit the HTTP C header. For NNTP(S), C +is printed in the the greeting and used for generating C +headers, overriding the L +directive. + =item --cert /path/to/cert See L. diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm index 17abf01d4..cb13a4cc0 100644 --- a/lib/PublicInbox/Daemon.pm +++ b/lib/PublicInbox/Daemon.pm @@ -149,6 +149,15 @@ sub load_mod ($;$$) { $tlsd->{$f} = $logs{$p} //= open_log_path(my $fh, $p); warn "# $scheme://$addr $f=$p\n"; } + for my $f (qw(servername serverport)) { + my $p = $opt->{$f} or next; + die "multiple $f= options specified\n" if @$p > 1; + if ($p->[0] eq '') { + warn "W: empty $f= ignored\n"; + } else { + $tlsd->{$f} = $p->[0]; + } + } # for per-listener $SIG{__WARN__}: my $err = $tlsd->{err}; $tlsd->{warn_cb} = sub { diff --git a/lib/PublicInbox/HTTPD.pm b/lib/PublicInbox/HTTPD.pm index 38b2e4f9a..55d728cbd 100644 --- a/lib/PublicInbox/HTTPD.pm +++ b/lib/PublicInbox/HTTPD.pm @@ -21,8 +21,8 @@ sub env_for ($$$) { my $n = getsockname($srv) or die "not a socket: $srv $!\n"; my ($host, $port) = PublicInbox::Daemon::host_with_port($n); { - SERVER_NAME => $host, - SERVER_PORT => $port, + SERVER_NAME => $self->{servername} // $host, + SERVER_PORT => ($self->{serverport} // $port) + 0, SCRIPT_NAME => '', 'psgi.version' => [ 1, 1 ], 'psgi.errors' => $self->{err}, diff --git a/lib/PublicInbox/NNTPD.pm b/lib/PublicInbox/NNTPD.pm index 4401a29b9..7e0459beb 100644 --- a/lib/PublicInbox/NNTPD.pm +++ b/lib/PublicInbox/NNTPD.pm @@ -18,6 +18,7 @@ sub new { out => \*STDOUT, # pi_cfg => $pi_cfg, # ssl_ctx_opt => { SSL_cert_file => ..., SSL_key_file => ... } + # servername => str # idler => PublicInbox::InboxIdle }, $class; } @@ -25,16 +26,11 @@ sub new { sub refresh_groups { my ($self, $sig) = @_; my $pi_cfg = PublicInbox::Config->new; - my $name = $pi_cfg->{'publicinbox.nntpserver'}; - if (!defined($name) or $name eq '') { - $name = hostname; - } elsif (ref($name) eq 'ARRAY') { - $name = $name->[0]; - } - if ($name ne ($self->{servername} // '')) { - $self->{servername} = $name; - $self->{greet} = \"201 $name ready - post via email\r\n"; - } + $self->{servername} //= $pi_cfg->{'publicinbox.nntpserver'} // ''; + ref($self->{servername}) eq 'ARRAY' and + $self->{servername} = $self->{servername}->[0]; + $self->{servername} = hostname if $self->{servername} eq ''; + $self->{greet} = \"201 $self->{servername} ready - post via email\r\n"; my $groups = $pi_cfg->{-by_newsgroup}; # filled during each_inbox my $cache = eval { $pi_cfg->ALL->misc->nntpd_cache_load } // {}; $pi_cfg->each_inbox(sub { diff --git a/t/httpd.t b/t/httpd.t index 39382b85f..36b076ade 100644 --- a/t/httpd.t +++ b/t/httpd.t @@ -5,6 +5,7 @@ use strict; use v5.10.1; use PublicInbox::TestCommon; use PublicInbox::Eml; +use PublicInbox::IO; use Socket qw(IPPROTO_TCP SOL_SOCKET); require_mods '-httpd'; require_git_http_backend; @@ -18,7 +19,9 @@ my $inboxdir = "$tmpdir/i.git"; my $group = 'test-httpd'; my $addr = $group . '@example.com'; my $sock = tcp_server(); +my $hostname = 'bogus-test.example.com'; my $td; +my $msgid = 'httpd-test@example.com'; { create_inbox 'test', tmpdir => $inboxdir, sub { my ($im, $ibx) = @_; @@ -26,7 +29,7 @@ my $td; From: Me To: You Cc: $addr -Message-Id: +Message-Id: <$msgid> Subject: hihi Date: Thu, 01 Jan 1970 06:06:06 +0000 @@ -40,9 +43,10 @@ EOF local $ENV{HOME} = $home; my $cmd = [ '-init', $group, $inboxdir, 'http://example.com/', $addr ]; ok(run_script($cmd), 'init ran properly'); - $cmd = [ '-httpd', '-W0', "--stdout=$out", "--stderr=$err" ]; - $td = start_script($cmd, undef, { 3 => $sock }); my $http_pfx = 'http://'.tcp_host_port($sock); + $cmd = [ '-httpd', '-W0', "--stdout=$out", "--stderr=$err", + "-l$http_pfx?servername=$hostname&serverport=80" ]; + $td = start_script($cmd, undef, { 3 => $sock }); { my $bad = tcp_connect($sock); print $bad "GETT / HTTP/1.0\r\n\r\n" or die; @@ -57,6 +61,12 @@ EOF is($conn->read($buf, 1), 0, "EOF"); } + $conn = tcp_connect($sock); + print $conn "GET /$group/$msgid HTTP/1.0\r\n\r\n" or xbail $!; + my $buf = PublicInbox::IO::read_all($conn); + like $buf, qr!\nLocation:\x20http://\Q$hostname\E/$group/$msgid/\r\n!s, + 'redirect used SERVER_{NAME,PORT} from CLI overrides'; + is(xsys(qw(git clone -q --mirror), "$http_pfx/$group", "$tmpdir/clone.git"), 0, 'smart clone successful'); @@ -81,7 +91,7 @@ EOM close $fh or xbail "close $!"; $td->kill('HUP') or BAIL_OUT "failed to kill -httpd: $!"; tick; # wait for HUP to take effect - my $buf = do { + $buf = do { my $c2 = tcp_connect($sock); $c2->write("GET /test-2/qp\@example.com/raw HTTP/1.0\r\n\r\n") or xbail "c2 write: $!"; diff --git a/t/nntpd.t b/t/nntpd.t index 1b2a9fa9b..220003ffb 100644 --- a/t/nntpd.t +++ b/t/nntpd.t @@ -5,10 +5,10 @@ use strict; use v5.10.1; use PublicInbox::TestCommon; require_mods(qw(DBD::SQLite Net::NNTP)); use PublicInbox::Eml; use Socket qw(IPPROTO_TCP TCP_NODELAY); -use Sys::Hostname; use POSIX qw(_exit); use PublicInbox::SHA; use PublicInbox::DS; +my $hostname = 'bogus-test.example.com'; # t/nntpd-v2.t wraps this for v2 my $version = $ENV{PI_TEST_VERSION} || 1; @@ -84,7 +84,8 @@ EOF close $cfgfh or BAIL_OUT; { - my $cmd = [ '-nntpd', '-W0', "--stdout=$out", "--stderr=$err" ]; + my $cmd = [ '-nntpd', '-W0', "--stdout=$out", "--stderr=$err", + "-lnntp://$host_port?servername=$hostname" ]; $td = start_script($cmd, undef, { 3 => $sock }); my $n = Net::NNTP->new($host_port); my $list = $n->list; @@ -95,7 +96,7 @@ close $cfgfh or BAIL_OUT; # TODO: Net::NNTP::listgroup does not support range at the moment my $s = tcp_connect($sock); sysread($s, my $buf, 4096); - is($buf, "201 " . hostname . " ready - post via email\r\n", + is($buf, "201 " . $hostname . " ready - post via email\r\n", 'got greeting'); syswrite($s, "LISTGROUP $group 1-1\r\n"); $buf = read_til_dot($s); @@ -123,13 +124,13 @@ close $cfgfh or BAIL_OUT; 'from' => "El\xc3\xa9anor ", 'to' => "El\xc3\xa9anor ", 'cc' => $addr, - 'xref' => hostname . " $group:1", + 'xref' => $hostname . " $group:1", 'references' => '', ); $s = tcp_connect($sock); sysread($s, $buf, 4096); - is($buf, "201 " . hostname . " ready - post via email\r\n", + is($buf, "201 " . $hostname . " ready - post via email\r\n", 'got greeting'); ok(syswrite($s, " \r\n"), 'wrote spaces'); @@ -149,7 +150,7 @@ close $cfgfh or BAIL_OUT; $s = tcp_connect($sock); sysread($s, $buf, 4096); - is($buf, "201 " . hostname . " ready - post via email\r\n", + is($buf, "201 " . $hostname . " ready - post via email\r\n", 'got greeting'); syswrite($s, "CAPABILITIES\r\n"); @@ -199,7 +200,7 @@ close $cfgfh or BAIL_OUT; '', $len, '1', - 'Xref: '. hostname . ' test-nntpd:1'] }, + 'Xref: '. $hostname . ' test-nntpd:1'] }, "XOVER range works"); is_deeply($n->xover('1'), { @@ -210,7 +211,7 @@ close $cfgfh or BAIL_OUT; '', $len, '1', - 'Xref: '. hostname . ' test-nntpd:1'] }, + 'Xref: '. $hostname . ' test-nntpd:1'] }, "XOVER by article works"); is_deeply($n->head(1), $n->head(''), 'HEAD OK'); @@ -233,7 +234,7 @@ close $cfgfh or BAIL_OUT; "El\xc3\xa9anor \t" . "Thu, 01 Jan 1970 06:06:06 +0000\t" . "$mid\t\t$len\t1" . - "\tXref: " . hostname . " test-nntpd:0", + "\tXref: " . $hostname . " test-nntpd:0", 'OVER by Message-ID works'); is($r[2], '.', 'correctly terminated response'); }