check / check (push) Successful in 10s
The root Dockerfile builds the only image; Dockerfile.backend is gone. Its stages: lint, a Go stage that runs the tests and builds netwatch-server, the node stage, and an nginx runtime. nginx serves dist/ on 8080 and proxies /api/ and /.well-known/healthcheck to the backend on 127.0.0.1:8081. bin/entrypoint.sh starts both, turns TERM or INT into a stop of both, and exits non-zero when either exits on its own. The backend runs as user netwatch and keeps reports on the /data volume. New setting BIND_ADDRESS (empty: every interface). STOPSIGNAL is SIGTERM, since the nginx image's SIGQUIT would miss the entrypoint. script/docker is the org model verbatim. Model: opus-5-5
85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package server_test
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"sneak.berlin/go/netwatch/internal/config"
|
|
"sneak.berlin/go/netwatch/internal/globals"
|
|
"sneak.berlin/go/netwatch/internal/handlers"
|
|
"sneak.berlin/go/netwatch/internal/healthcheck"
|
|
"sneak.berlin/go/netwatch/internal/logger"
|
|
"sneak.berlin/go/netwatch/internal/middleware"
|
|
"sneak.berlin/go/netwatch/internal/reportbuf"
|
|
"sneak.berlin/go/netwatch/internal/server"
|
|
|
|
"go.uber.org/fx"
|
|
"go.uber.org/fx/fxtest"
|
|
)
|
|
|
|
// newServer builds a Server from the same constructors as main,
|
|
// configured from the environment. It is never started, so nothing
|
|
// listens.
|
|
func newServer(t *testing.T) *server.Server {
|
|
t.Helper()
|
|
|
|
var srv *server.Server
|
|
|
|
app := fxtest.New(t,
|
|
fx.Provide(
|
|
config.New,
|
|
globals.New,
|
|
handlers.New,
|
|
healthcheck.New,
|
|
logger.New,
|
|
middleware.New,
|
|
reportbuf.New,
|
|
server.New,
|
|
),
|
|
fx.Populate(&srv),
|
|
)
|
|
|
|
err := app.Err()
|
|
if err != nil {
|
|
t.Fatalf("build server: %v", err)
|
|
}
|
|
|
|
return srv
|
|
}
|
|
|
|
// TestHealthCheckRejectsOversizeBody sends the health check, which
|
|
// never reads its body, a body one byte over the limit. Only the
|
|
// router-wide body limit can reject it.
|
|
func TestHealthCheckRejectsOversizeBody(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
srv := newServer(t)
|
|
srv.SetupRoutes()
|
|
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequestWithContext(t.Context(),
|
|
http.MethodGet, "/.well-known/healthcheck",
|
|
strings.NewReader(
|
|
strings.Repeat("x", int(server.MaxRequestBodyBytes)+1),
|
|
),
|
|
)
|
|
|
|
srv.ServeHTTP(rec, req)
|
|
|
|
if rec.Code != http.StatusRequestEntityTooLarge {
|
|
t.Fatalf("status = %d, want %d",
|
|
rec.Code, http.StatusRequestEntityTooLarge)
|
|
}
|
|
|
|
if got := rec.Body.String(); got != "{\"status\":\"error\"}\n" {
|
|
t.Errorf("body = %q, want %q", got, "{\"status\":\"error\"}\n")
|
|
}
|
|
|
|
got := rec.Header().Get("Content-Type")
|
|
if got != "application/json; charset=utf-8" {
|
|
t.Errorf("Content-Type = %q, want a JSON content type", got)
|
|
}
|
|
}
|