Commit Graph
5 Commits
Author SHA1 Message Date
clawbot a70b173a48 healthcheck: answer 503 when the last round of DNS checks reached no root server (closes #302)
check / check (push) Canceled after 0s
The health check answered ok while every DNS lookup failed, as on a
network that intercepts DNS queries. A lookup whose root servers give no
usable reply now fails with ErrNoRootServerAnswered. At the end of each
round of DNS checks the watcher records whether every lookup failed with
it or with ErrIntercepted; the health check then gives status error, and
/.well-known/healthcheck and /health answer 503. Until the first round
finishes it stays ok.

The health check now depends on the watcher, so fx builds the watcher
first: its first round starts before the HTTP server listens, and the
server tests' fx graph includes it. NewWithRootServers lets tests start
a resolver's walks at real servers that are not root servers.

Model: opus-5-5
2026-10-18 13:30:45 +00:00
clawbot 2ae6110414 server: a port that cannot be bound stops startup (closes #266)
check / check (push) Canceled after 0s
The start hook now binds the listen port itself and serves on it in a
goroutine. A bind failure, such as a port already in use or a
privileged port without root, is returned to fx, which stops startup
and exits 1 with an error like "starting http server: listen tcp
:8080: bind: address already in use". Before, the bind happened inside
the goroutine and its error was only logged while the watcher kept
running without the dashboard, API or health check.

The http.Server is now built before that goroutine starts, so Shutdown
no longer reads a field another goroutine may still be writing.

TestPortInUseStopsStartup holds a port and checks that starting the
server on it fails with an error naming it.

Model: opus-5-5
2026-10-13 18:00:00 +02:00
clawbot c0ea9b96f2 server: report HTTP handler panics to Sentry (closes #107)
check / check (push) Successful in 1m35s
DNSWATCHER_SENTRY_DSN was read but never used. This ports the Sentry
integration from gohttpserver with sentry-go v0.49.0. The server's start
hook calls sentry.Init when the DSN is set; a DSN Sentry cannot parse
fails the hook, so startup stops with the parse error. sentryhttp, with
Repanic, reports handler panics and passes them on to chi's Recoverer.
Shutdown sends queued reports once the HTTP server has stopped. The
client uses the older transport (DisableTelemetryBuffer): with the
default one, Flush can return before sending a report made just before
it. Client reports are off, so only panics are sent. The DSN is checked
at server start, not in config, so the config test is unchanged.
sentry-go raises several golang.org/x modules and moves go-spew and
go-difflib to untagged commits.

Model: opus-5-5
2026-10-01 23:09:39 +02:00
clawbot 19f282c8b3 server: assert timeouts on the served http.Server, not just the constructor (closes #120)
check / check (push) Successful in 6s
The timeout tests called newHTTPServer directly, so a Run that built
its http.Server inline would drop every timeout with the suite still
green. TestRunWiresSocketTimeouts wires a Server as cmd/dnswatcher
does, minus the watcher and resolver so no live DNS is touched, drives
Run with an unbindable port so it stores its http.Server and returns
without listening, and checks that server carries all four timeouts
and both required relationships. The addr/handler test, which could
not fail, is dropped.

The ReadTimeout note now says what net/http does: a request whose
headers arrive after ReadTimeout but within ReadHeaderTimeout gets a
read deadline that has already passed, so reading its body fails at
once.

Model: opus-4-8 (implementation); opus-5-5 (rework)
2026-09-28 22:01:36 +02:00
clawbot fc43f893a5 server: set all four http.Server socket timeouts (#118)
check / check (push) Successful in 3m50s
The http.Server was built with only ReadHeaderTimeout set; the other three
timeouts were zero, which in net/http means no limit, so a peer could hold a
connection open past the header phase, responses had no write deadline, and
keep-alive connections were never reaped. ReadTimeout 15s, WriteTimeout 75s,
and IdleTimeout 120s now join ReadHeaderTimeout 10s as named constants.
WriteTimeout must stay above the 60s chimw.Timeout handler budget, because
net/http arms the write deadline once request headers are read; a test fails
the build if either number moves alone. The server literal moved into
newHTTPServer so the configuration can be asserted without binding a socket
(closes #99)

Model: opus-5
2026-09-09 15:17:43 +02:00