=item publicinbox.nntpserver
Same as C<publicinbox.imapserver>, but for the hostname(s) of the
-L<public-inbox-nntpd(1)> instance.
+L<public-inbox-nntpd(1)> instance. This affects C<Xref:> headers
+in responses. As of public-inbox 2.0, this can be overriden on
+the C<public-inbox-netd(1)> command-line via
+C<--listen nntp://$ADDRESS:$PORT/?servername=example.com>
Default: none
Per-listener options may be specified after C<?> as C<KEY=VALUE>
pairs delimited by C<,>. See L<public-inbox-netd(1)> for
documentation on the C<cert=>, C<key=>, C<env.NAME=VALUE>,
-C<out=>, C<err=>, and C<psgi=> options available.
+C<out=>, C<err=>, C<psgi=>, C<servername=>, and C<serverport=>
+options available.
Default: server-dependent unless socket activation is used with
L<systemd(1)> or similar (see L<systemd.socket(5)>).
L<Plack::Middleware::AccessLog> or
L<Plack::Middleware::AccessLog::Timed>, instead.
+As of public-inbox 2.0, C<servername=> and C<serverport=> 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<Host:> header. For NNTP(S), C<servername=>
+is printed in the the greeting and used for generating C<Xref:>
+headers, overriding the L<public-inbox-config(5)/publicinbox.nntpserver>
+directive.
+
=item --cert /path/to/cert
See L<public-inbox-daemon(1)>.
$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 {
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},
out => \*STDOUT,
# pi_cfg => $pi_cfg,
# ssl_ctx_opt => { SSL_cert_file => ..., SSL_key_file => ... }
+ # servername => str
# idler => PublicInbox::InboxIdle
}, $class;
}
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 {
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;
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) = @_;
From: Me <me\@example.com>
To: You <you\@example.com>
Cc: $addr
-Message-Id: <nntp\@example.com>
+Message-Id: <$msgid>
Subject: hihi
Date: Thu, 01 Jan 1970 06:06:06 +0000
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;
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');
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: $!";
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;
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;
# 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);
'from' => "El\xc3\xa9anor <me\@example.com>",
'to' => "El\xc3\xa9anor <you\@example.com>",
'cc' => $addr,
- 'xref' => hostname . " $group:1",
+ 'xref' => $hostname . " $group:1",
'references' => '<reftabsqueezed>',
);
$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');
$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");
'<reftabsqueezed>',
$len,
'1',
- 'Xref: '. hostname . ' test-nntpd:1'] },
+ 'Xref: '. $hostname . ' test-nntpd:1'] },
"XOVER range works");
is_deeply($n->xover('1'), {
'<reftabsqueezed>',
$len,
'1',
- 'Xref: '. hostname . ' test-nntpd:1'] },
+ 'Xref: '. $hostname . ' test-nntpd:1'] },
"XOVER by article works");
is_deeply($n->head(1), $n->head('<nntp@example.com>'), 'HEAD OK');
"El\xc3\xa9anor <me\@example.com>\t" .
"Thu, 01 Jan 1970 06:06:06 +0000\t" .
"$mid\t<reftabsqueezed>\t$len\t1" .
- "\tXref: " . hostname . " test-nntpd:0",
+ "\tXref: " . $hostname . " test-nntpd:0",
'OVER by Message-ID works');
is($r[2], '.', 'correctly terminated response');
}