check / check (push) Successful in 42s
POST /api/v1/reports stays unauthenticated but is bounded. Each client address, as the trusted-proxy logic resolves it, may send REPORTS_PER_MINUTE reports a minute (default 60, counted by go-chi/httprate over a sliding minute); past that it gets 429 with Retry-After. reportbuf refuses a report that would take the report files past DATA_DIR_MAX_BYTES (default 1 GiB), counting the files already in DATA_DIR and unwritten reports at their uncompressed size; the handler answers 507. CORS adds nothing unless CORS_ALLOWED_ORIGINS lists origins. A limit that is not a positive number, or an origin that is not a plain scheme://host[:port], stops the server from starting. Model: opus-5-5
65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
package config_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"sneak.berlin/go/netwatch/internal/config"
|
|
"sneak.berlin/go/netwatch/internal/globals"
|
|
"sneak.berlin/go/netwatch/internal/logger"
|
|
|
|
"go.uber.org/fx"
|
|
)
|
|
|
|
// requireConfigError builds the config as main does and fails the
|
|
// test unless that fails with an error naming setting. It uses
|
|
// fx.New, because fxtest.New fails the test itself on an error.
|
|
func requireConfigError(t *testing.T, setting string) {
|
|
t.Helper()
|
|
|
|
app := fx.New(
|
|
fx.NopLogger,
|
|
fx.Provide(globals.New, logger.New, config.New),
|
|
fx.Invoke(func(*config.Config) {}),
|
|
)
|
|
|
|
err := app.Err()
|
|
if err == nil || !strings.Contains(err.Error(), setting) {
|
|
t.Fatalf("config error = %v, want one naming %s", err, setting)
|
|
}
|
|
}
|
|
|
|
// TestReportsPerMinuteMustBePositive: unchecked, zero would panic
|
|
// when the routes are built, and a negative rate would lift the
|
|
// limit.
|
|
func TestReportsPerMinuteMustBePositive(t *testing.T) {
|
|
t.Setenv("REPORTS_PER_MINUTE", "0")
|
|
|
|
requireConfigError(t, "REPORTS_PER_MINUTE")
|
|
}
|
|
|
|
// TestDataDirMaxBytesMustBeANumber: viper reads a value that is not
|
|
// a number, such as "1GB", as 0, which would refuse every report.
|
|
func TestDataDirMaxBytesMustBeANumber(t *testing.T) {
|
|
t.Setenv("DATA_DIR_MAX_BYTES", "1GB")
|
|
|
|
requireConfigError(t, "DATA_DIR_MAX_BYTES")
|
|
}
|
|
|
|
// TestCORSAllowedOriginsMustBeOrigins: "*" would let every origin in,
|
|
// and an entry that is not a plain origin would match no page.
|
|
func TestCORSAllowedOriginsMustBeOrigins(t *testing.T) {
|
|
for _, entry := range []string{
|
|
"*",
|
|
"https://*.netwatch.example",
|
|
"netwatch.example",
|
|
"https://netwatch.example/",
|
|
} {
|
|
t.Run(entry, func(t *testing.T) {
|
|
t.Setenv("CORS_ALLOWED_ORIGINS", entry)
|
|
|
|
requireConfigError(t, "CORS_ALLOWED_ORIGINS")
|
|
})
|
|
}
|
|
}
|