watcher: an IPv6 address is written in brackets before its port (closes #270)
check / check (push) Canceled after 0s

Port and certificate keys were joined as address:port, so an IPv6
address ran into its port: 2a01:4f8:2200:fd11::1:80 is also an address
on its own. Keys are now joined with net.JoinHostPort and split with
net.SplitHostPort, giving [2a01:4f8:2200:fd11::1]:80 in the state file,
/api/v1/status, the dashboard and Port Change notifications; an IPv4
address is unchanged. A certificate key still splits at its last colon,
since a hostname has none. Tests that built IPv6 keys by hand now use
the bracketed form, and a test checks that an IPv6 address's
certificate entry is removed when its port 443 closes.

Model: opus-5-5
This commit was merged in pull request #282.
This commit is contained in:
2026-10-13 22:27:34 +02:00
parent 6b580a5a0f
commit aaccabad50
6 changed files with 115 additions and 20 deletions
+7 -4
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log/slog"
"net"
"os"
"slices"
"strings"
@@ -824,7 +825,8 @@ func TestPortStateChange(t *testing.T) {
hs, _ := deps.state.GetHostnameState(testHost)
assertNotified(
t, deps, "Port Change: "+addresses(hs)[0]+":443", "warning",
t, deps, "Port Change: "+net.JoinHostPort(addresses(hs)[0], "443"),
"warning",
)
}
@@ -1031,11 +1033,12 @@ func TestDNSRunsBeforePortAndTLSChecks(t *testing.T) {
// Port and TLS checks must use the addresses this check found.
for _, ip := range addresses(snap.Hostnames[testHost]) {
if _, ok := snap.Ports[ip+":80"]; !ok {
t.Error("port check used stale DNS: missing " + ip + ":80")
portKey := net.JoinHostPort(ip, "80")
if _, ok := snap.Ports[portKey]; !ok {
t.Error("port check used stale DNS: missing " + portKey)
}
certKey := ip + ":443:" + testHost
certKey := net.JoinHostPort(ip, "443") + ":" + testHost
if _, ok := snap.Certificates[certKey]; !ok {
t.Error("TLS check used stale DNS: missing " + certKey)
}