The HTTP server ran ListenAndServe in a goroutine, so a failed bind
was only logged and neoircd kept running without its HTTP API.
The start hook now binds the listen address and returns the bind
error, so neoircd exits 1 with an error naming the address. If serving
the bound listener later ends with anything other than a normal
shutdown, the server stops the app through fx.Shutdowner with exit
code 1; the handler tests now pass it that Shutdowner.
Tests check that a taken port fails startup, that a serve failure
stops the app with exit code 1, and that a normal stop does not. The
server tests no longer run in parallel: building the app writes the
global viper instance.
Model: opus-5-5
setupSPA took the file name from request.URL.Path[1:], which panics
when the path is empty, as it is for an absolute-form request line
with no path ("GET http://host HTTP/1.1"). It now trims a leading "/"
instead; an empty name fails to read, so the request gets the index
page, as "/" already does.
The new test in internal/server sends such a request and expects 200
and the index page. export_test.go gives it a Server whose router has
only the web client route.
Model: opus-5-5