script/fmt now runs golines -m 77 after gofmt, repeating golines until it changes nothing, since one pass can leave a line the next splits. script/fmt-check fails when either would change a file. script/bootstrap installs golines v0.13.0 with go install, pinned to its commit, and checks the installed version with go version -m. The tree is reformatted. The longer lines this makes are fixed by hand: nolint directives moved onto their own line above the statement, one string split, and 20 functions over funlen's 80 lines shortened or split, RunWAF and limitPercentages among them. Model: opus-5-5
This commit is contained in:
1 parent
f9bec5146b
commit
a8b24a843b
117 files changed
+9441
-2670
No files matched your search
+219
-76
@@ -358,11 +358,13 @@ func startServerLogging(
|
||||
}
|
||||
maps.Copy(settings, env)
|
||||
|
||||
cfg, err := config.RProxyFromEnvironment(func(name string) (string, bool) {
|
||||
value, ok := settings[name]
|
||||
cfg, err := config.RProxyFromEnvironment(
|
||||
func(name string) (string, bool) {
|
||||
value, ok := settings[name]
|
||||
|
||||
return value, ok
|
||||
})
|
||||
return value, ok
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("settings %v: %v", settings, err)
|
||||
}
|
||||
@@ -370,10 +372,18 @@ func startServerLogging(
|
||||
server := rproxy.New(rproxy.Params{
|
||||
Config: cfg,
|
||||
RequestLog: requestLog,
|
||||
ProcessLog: requestlog.NewProcessLogger(processLog, "test", slog.LevelInfo),
|
||||
ProcessLog: requestlog.NewProcessLogger(
|
||||
processLog,
|
||||
"test",
|
||||
slog.LevelInfo,
|
||||
),
|
||||
})
|
||||
|
||||
listener, err := (&net.ListenConfig{}).Listen(t.Context(), "tcp", localhost+":0")
|
||||
listener, err := (&net.ListenConfig{}).Listen(
|
||||
t.Context(),
|
||||
"tcp",
|
||||
localhost+":0",
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("listen: %v", err)
|
||||
}
|
||||
@@ -403,7 +413,10 @@ type answered struct {
|
||||
func visit(t *testing.T, req *http.Request) answered {
|
||||
t.Helper()
|
||||
|
||||
transport := &http.Transport{DisableKeepAlives: true, DisableCompression: true}
|
||||
transport := &http.Transport{
|
||||
DisableKeepAlives: true,
|
||||
DisableCompression: true,
|
||||
}
|
||||
defer transport.CloseIdleConnections()
|
||||
|
||||
res, err := transport.RoundTrip(req)
|
||||
@@ -429,8 +442,12 @@ func newRequest(
|
||||
) *http.Request {
|
||||
t.Helper()
|
||||
|
||||
req, err := http.NewRequestWithContext(t.Context(), method, "http://"+addr+target,
|
||||
body)
|
||||
req, err := http.NewRequestWithContext(
|
||||
t.Context(),
|
||||
method,
|
||||
"http://"+addr+target,
|
||||
body,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("new request: %v", err)
|
||||
}
|
||||
@@ -450,7 +467,11 @@ func wantGreeting(t *testing.T, got answered) {
|
||||
t.Helper()
|
||||
|
||||
if got.status != http.StatusOK || got.body != greeting {
|
||||
t.Errorf("answered %d %q, want the app's greeting", got.status, got.body)
|
||||
t.Errorf(
|
||||
"answered %d %q, want the app's greeting",
|
||||
got.status,
|
||||
got.body,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -547,7 +568,12 @@ func TestPassesAnAllowedRequestToTheAppAndItsAnswerBack(t *testing.T) {
|
||||
requestIDHeader: asked.header.Get(requestIDHeader),
|
||||
} {
|
||||
if received.Header.Get(name) != want {
|
||||
t.Errorf("the app saw %s %q, want %q", name, received.Header.Get(name), want)
|
||||
t.Errorf(
|
||||
"the app saw %s %q, want %q",
|
||||
name,
|
||||
received.Header.Get(name),
|
||||
want,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -660,7 +686,12 @@ func TestAnAnswerWithoutAContentTypeGetsNone(t *testing.T) {
|
||||
})
|
||||
_, _, server := startServer(t, standIn.URL, app.URL, nil)
|
||||
|
||||
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", http.NoBody)
|
||||
req := httptest.NewRequestWithContext(
|
||||
t.Context(),
|
||||
http.MethodGet,
|
||||
"/",
|
||||
http.NoBody,
|
||||
)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
server.Handler.ServeHTTP(w, req)
|
||||
@@ -670,8 +701,11 @@ func TestAnAnswerWithoutAContentTypeGetsNone(t *testing.T) {
|
||||
// stops it: the key with no value.
|
||||
values, there := w.Header()["Content-Type"]
|
||||
if !there || len(values) != 0 {
|
||||
t.Errorf("the answer's Content-Type is %q, there: %v, want the key with no value",
|
||||
values, there)
|
||||
t.Errorf(
|
||||
"the answer's Content-Type is %q, there: %v, want the key with no value",
|
||||
values,
|
||||
there,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,8 +740,12 @@ func TestRemovesTheVisitorsLookupHeadersWhenWAFGivesNone(t *testing.T) {
|
||||
wantGreeting(t, visit(t, req))
|
||||
|
||||
header := <-seen
|
||||
if len(header.Values(asnHeader)) != 0 || len(header.Values(countryHeader)) != 0 {
|
||||
t.Errorf("the app saw the visitor's lookup headers: %v", header)
|
||||
if len(header.Values(asnHeader)) != 0 ||
|
||||
len(header.Values(countryHeader)) != 0 {
|
||||
t.Errorf(
|
||||
"the app saw the visitor's lookup headers: %v",
|
||||
header,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -740,7 +778,8 @@ func TestDenyGivesTheVisitorWAFsAnswer(t *testing.T) {
|
||||
}
|
||||
|
||||
line := out.requestLine(t)
|
||||
if line["disposition"] != dispositionDeny || line["default_disposition"] != nil {
|
||||
if line["disposition"] != dispositionDeny ||
|
||||
line["default_disposition"] != nil {
|
||||
t.Errorf("line %v, want waf's deny", line)
|
||||
}
|
||||
}
|
||||
@@ -754,7 +793,11 @@ func TestADeniedHeadKeepsWAFsContentLength(t *testing.T) {
|
||||
|
||||
got := visit(t, newRequest(t, http.MethodHead, addr, "/", http.NoBody))
|
||||
if got.status != http.StatusForbidden ||
|
||||
got.header.Get(contentLengthHeader) != strconv.Itoa(len(deniedBody)) {
|
||||
got.header.Get(
|
||||
contentLengthHeader,
|
||||
) != strconv.Itoa(
|
||||
len(deniedBody),
|
||||
) {
|
||||
t.Errorf("answered %+v, want waf's 403 and its length", got)
|
||||
}
|
||||
}
|
||||
@@ -778,7 +821,14 @@ func TestAnAnswerRProxyHoldsWholeIsSentBeforeItsLogLine(t *testing.T) {
|
||||
log := heldLog{release: make(chan struct{})}
|
||||
standIn := startWAF(t, deny)
|
||||
app := startApp(t, greet)
|
||||
addr, _ := startServerLogging(t, standIn.URL, app.URL, nil, log, io.Discard)
|
||||
addr, _ := startServerLogging(
|
||||
t,
|
||||
standIn.URL,
|
||||
app.URL,
|
||||
nil,
|
||||
log,
|
||||
io.Discard,
|
||||
)
|
||||
|
||||
t.Cleanup(func() { close(log.release) })
|
||||
|
||||
@@ -795,9 +845,16 @@ func TestAnAnswerRProxyHoldsWholeIsSentBeforeItsLogLine(t *testing.T) {
|
||||
}()
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil || res.StatusCode != tc.status || string(body) != tc.body {
|
||||
t.Errorf("answered %d %q (%v), want %d %q", res.StatusCode, body, err,
|
||||
tc.status, tc.body)
|
||||
if err != nil || res.StatusCode != tc.status ||
|
||||
string(body) != tc.body {
|
||||
t.Errorf(
|
||||
"answered %d %q (%v), want %d %q",
|
||||
res.StatusCode,
|
||||
body,
|
||||
err,
|
||||
tc.status,
|
||||
tc.body,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -843,8 +900,11 @@ func TestCloseClosesTheConnectionWithoutAnAnswer(t *testing.T) {
|
||||
|
||||
text, err := io.ReadAll(conn)
|
||||
if err != nil || len(text) != 0 {
|
||||
t.Errorf("read %q (%v), want the connection closed without an answer",
|
||||
text, err)
|
||||
t.Errorf(
|
||||
"read %q (%v), want the connection closed without an answer",
|
||||
text,
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
report := standIn.report(t)
|
||||
@@ -858,7 +918,9 @@ func TestCloseClosesTheConnectionWithoutAnAnswer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestALineForARequestClosedWithoutAnAnswerHasNoNegativeTime(t *testing.T) {
|
||||
func TestALineForARequestClosedWithoutAnAnswerHasNoNegativeTime(
|
||||
t *testing.T,
|
||||
) {
|
||||
t.Parallel()
|
||||
|
||||
backend := startWAFAnsweringReports(t,
|
||||
@@ -881,7 +943,10 @@ func TestALineForARequestClosedWithoutAnAnswerHasNoNegativeTime(t *testing.T) {
|
||||
|
||||
duration, ok := line["duration_response_ms"].(float64)
|
||||
if !ok || duration < 0 {
|
||||
t.Errorf("line %v, want a duration_response_ms that is not negative", line)
|
||||
t.Errorf(
|
||||
"line %v, want a duration_response_ms that is not negative",
|
||||
line,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -900,12 +965,16 @@ func answeringWith(answer http.HandlerFunc) func(t *testing.T) string {
|
||||
func noAnswers() map[string]func(t *testing.T) string {
|
||||
return map[string]func(t *testing.T) string{
|
||||
"no connection": func(*testing.T) string { return nowhere },
|
||||
"no answer at all": answeringWith(func(http.ResponseWriter, *http.Request) {
|
||||
panic(http.ErrAbortHandler)
|
||||
}),
|
||||
"a slow start": answeringWith(func(_ http.ResponseWriter, r *http.Request) {
|
||||
<-r.Context().Done()
|
||||
}),
|
||||
"no answer at all": answeringWith(
|
||||
func(http.ResponseWriter, *http.Request) {
|
||||
panic(http.ErrAbortHandler)
|
||||
},
|
||||
),
|
||||
"a slow start": answeringWith(
|
||||
func(_ http.ResponseWriter, r *http.Request) {
|
||||
<-r.Context().Done()
|
||||
},
|
||||
),
|
||||
"headers followed by a stalled body": answeringWith(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set(dispositionHeader, dispositionDeny)
|
||||
@@ -947,21 +1016,29 @@ func TestAnAnswerOtherThanAllowGoesToTheVisitorAsWAFGaveIt(t *testing.T) {
|
||||
t.Run(tc.name+" with the default "+setting, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
standIn := startWAF(t, func(w http.ResponseWriter, _ *http.Request) {
|
||||
if tc.disposition != "" {
|
||||
w.Header().Set(dispositionHeader, tc.disposition)
|
||||
}
|
||||
standIn := startWAF(
|
||||
t,
|
||||
func(w http.ResponseWriter, _ *http.Request) {
|
||||
if tc.disposition != "" {
|
||||
w.Header().Set(dispositionHeader, tc.disposition)
|
||||
}
|
||||
|
||||
w.Header().Set(fromWAFHeader, addedHeaderValue)
|
||||
w.WriteHeader(tc.status)
|
||||
_, _ = io.WriteString(w, tc.body)
|
||||
})
|
||||
w.Header().Set(fromWAFHeader, addedHeaderValue)
|
||||
w.WriteHeader(tc.status)
|
||||
_, _ = io.WriteString(w, tc.body)
|
||||
},
|
||||
)
|
||||
app := startApp(t, func(http.ResponseWriter, *http.Request) {
|
||||
t.Error("the app was asked")
|
||||
})
|
||||
addr, out := startRProxy(t, standIn.URL, app.URL, map[string]string{
|
||||
defaultDisposition: setting,
|
||||
})
|
||||
addr, out := startRProxy(
|
||||
t,
|
||||
standIn.URL,
|
||||
app.URL,
|
||||
map[string]string{
|
||||
defaultDisposition: setting,
|
||||
},
|
||||
)
|
||||
|
||||
got := get(t, addr, "/")
|
||||
if got.status != tc.status || got.body != tc.body ||
|
||||
@@ -974,8 +1051,13 @@ func TestAnAnswerOtherThanAllowGoesToTheVisitorAsWAFGaveIt(t *testing.T) {
|
||||
}
|
||||
|
||||
line := out.requestLine(t)
|
||||
if line["status"] != float64(tc.status) || line["default_disposition"] != nil {
|
||||
t.Errorf("line %v, want status %d and no default", line, tc.status)
|
||||
if line["status"] != float64(tc.status) ||
|
||||
line["default_disposition"] != nil {
|
||||
t.Errorf(
|
||||
"line %v, want status %d and no default",
|
||||
line,
|
||||
tc.status,
|
||||
)
|
||||
}
|
||||
|
||||
if out.has("waf gave no answer") {
|
||||
@@ -1036,7 +1118,8 @@ func TestAnAnswerOf1MiBGoesToTheVisitor(t *testing.T) {
|
||||
})
|
||||
|
||||
got := get(t, addr, "/")
|
||||
if got.status != http.StatusInternalServerError || len(got.body) != size {
|
||||
if got.status != http.StatusInternalServerError ||
|
||||
len(got.body) != size {
|
||||
t.Errorf("answered %d with %d bytes, want waf's 500 with %d",
|
||||
got.status, len(got.body), size)
|
||||
}
|
||||
@@ -1048,7 +1131,11 @@ func TestAnAnswerOf1MiBGoesToTheVisitor(t *testing.T) {
|
||||
func startWAFWriting(t *testing.T, text string) string {
|
||||
t.Helper()
|
||||
|
||||
listener, err := (&net.ListenConfig{}).Listen(t.Context(), "tcp", localhost+":0")
|
||||
listener, err := (&net.ListenConfig{}).Listen(
|
||||
t.Context(),
|
||||
"tcp",
|
||||
localhost+":0",
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("listen: %v", err)
|
||||
}
|
||||
@@ -1126,10 +1213,15 @@ func TestAnAnswerThatCannotBePassedOnIsAnswered502(t *testing.T) {
|
||||
app := startApp(t, func(http.ResponseWriter, *http.Request) {
|
||||
t.Error("the app was asked")
|
||||
})
|
||||
addr, out := startRProxy(t, backend(t), app.URL, map[string]string{
|
||||
timeoutSetting: "60000",
|
||||
defaultDisposition: setting,
|
||||
})
|
||||
addr, out := startRProxy(
|
||||
t,
|
||||
backend(t),
|
||||
app.URL,
|
||||
map[string]string{
|
||||
timeoutSetting: "60000",
|
||||
defaultDisposition: setting,
|
||||
},
|
||||
)
|
||||
|
||||
if got := get(t, addr, "/"); got.status != http.StatusBadGateway {
|
||||
t.Errorf("answered %+v, want 502", got)
|
||||
@@ -1138,7 +1230,10 @@ func TestAnAnswerThatCannotBePassedOnIsAnswered502(t *testing.T) {
|
||||
line := out.requestLine(t)
|
||||
if line["status"] != float64(http.StatusBadGateway) ||
|
||||
line["disposition"] != nil || line["default_disposition"] != nil {
|
||||
t.Errorf("line %v, want status 502 and no disposition", line)
|
||||
t.Errorf(
|
||||
"line %v, want status 502 and no disposition",
|
||||
line,
|
||||
)
|
||||
}
|
||||
|
||||
out.waitFor(t, "waf's answer is dropped")
|
||||
@@ -1171,9 +1266,14 @@ func TestWithoutAnAnswerTheDefaultDispositionDecides(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := startApp(t, greet)
|
||||
addr, out := startRProxy(t, backend(t), app.URL, map[string]string{
|
||||
timeoutSetting: "200",
|
||||
})
|
||||
addr, out := startRProxy(
|
||||
t,
|
||||
backend(t),
|
||||
app.URL,
|
||||
map[string]string{
|
||||
timeoutSetting: "200",
|
||||
},
|
||||
)
|
||||
|
||||
wantGreeting(t, get(t, addr, "/"))
|
||||
|
||||
@@ -1190,10 +1290,15 @@ func TestWithoutAnAnswerTheDefaultDispositionDecides(t *testing.T) {
|
||||
app := startApp(t, func(http.ResponseWriter, *http.Request) {
|
||||
t.Error("the app was asked")
|
||||
})
|
||||
addr, out := startRProxy(t, backend(t), app.URL, map[string]string{
|
||||
timeoutSetting: "200",
|
||||
defaultDisposition: dispositionDeny,
|
||||
})
|
||||
addr, out := startRProxy(
|
||||
t,
|
||||
backend(t),
|
||||
app.URL,
|
||||
map[string]string{
|
||||
timeoutSetting: "200",
|
||||
defaultDisposition: dispositionDeny,
|
||||
},
|
||||
)
|
||||
|
||||
got := get(t, addr, "/")
|
||||
if got.status != http.StatusServiceUnavailable {
|
||||
@@ -1216,16 +1321,24 @@ func TestAVisitorThatGoesAwayWhileWAFIsAskedGetsNoDefault(t *testing.T) {
|
||||
t.Run("with the default "+disposition, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
standIn := startWAF(t, func(_ http.ResponseWriter, r *http.Request) {
|
||||
<-r.Context().Done()
|
||||
})
|
||||
standIn := startWAF(
|
||||
t,
|
||||
func(_ http.ResponseWriter, r *http.Request) {
|
||||
<-r.Context().Done()
|
||||
},
|
||||
)
|
||||
app := startApp(t, func(http.ResponseWriter, *http.Request) {
|
||||
t.Error("the app was asked")
|
||||
})
|
||||
addr, out := startRProxy(t, standIn.URL, app.URL, map[string]string{
|
||||
timeoutSetting: "60000",
|
||||
defaultDisposition: disposition,
|
||||
})
|
||||
addr, out := startRProxy(
|
||||
t,
|
||||
standIn.URL,
|
||||
app.URL,
|
||||
map[string]string{
|
||||
timeoutSetting: "60000",
|
||||
defaultDisposition: disposition,
|
||||
},
|
||||
)
|
||||
|
||||
conn := dial(t, addr)
|
||||
send(t, conn, "GET / HTTP/1.1\r\nHost: site.example\r\n\r\n")
|
||||
@@ -1443,12 +1556,21 @@ func TestReportGivesWhatHappened(t *testing.T) {
|
||||
report.ResponseBytes != int64(len(greeting)) ||
|
||||
report.DurationTotalMS <= 0 || report.DurationUpstreamTotalMS <= 0 ||
|
||||
report.DurationUpstreamTotalMS > report.DurationTotalMS {
|
||||
t.Errorf("report %+v, of %d bytes up and %d back", report, len(body), len(greeting))
|
||||
t.Errorf(
|
||||
"report %+v, of %d bytes up and %d back",
|
||||
report,
|
||||
len(body),
|
||||
len(greeting),
|
||||
)
|
||||
}
|
||||
|
||||
line := out.requestLine(t)
|
||||
if line["request_id"] != report.RequestID {
|
||||
t.Errorf("line %v, report %+v, want the same request id", line, report)
|
||||
t.Errorf(
|
||||
"line %v, report %+v, want the same request id",
|
||||
line,
|
||||
report,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1477,9 +1599,14 @@ func TestWaitForReportsWaitsForAReportBeingSent(t *testing.T) {
|
||||
t.Cleanup(backend.Close)
|
||||
|
||||
app := startApp(t, greet)
|
||||
addr, _, server := startServer(t, backend.URL, app.URL, map[string]string{
|
||||
timeoutSetting: "5000",
|
||||
})
|
||||
addr, _, server := startServer(
|
||||
t,
|
||||
backend.URL,
|
||||
app.URL,
|
||||
map[string]string{
|
||||
timeoutSetting: "5000",
|
||||
},
|
||||
)
|
||||
|
||||
wantGreeting(t, get(t, addr, "/"))
|
||||
|
||||
@@ -1535,7 +1662,11 @@ func TestReportOfAWebSocketCountsWhatItCarried(t *testing.T) {
|
||||
_ = res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusSwitchingProtocols {
|
||||
t.Fatalf("status %d, want %d", res.StatusCode, http.StatusSwitchingProtocols)
|
||||
t.Fatalf(
|
||||
"status %d, want %d",
|
||||
res.StatusCode,
|
||||
http.StatusSwitchingProtocols,
|
||||
)
|
||||
}
|
||||
|
||||
// Past both time limits, the connection still carries what is sent.
|
||||
@@ -1559,7 +1690,9 @@ func TestReportOfAWebSocketCountsWhatItCarried(t *testing.T) {
|
||||
t.Errorf("report %+v, of %d bytes each way", report, len(message))
|
||||
}
|
||||
|
||||
if line := out.requestLine(t); line["status"] != float64(res.StatusCode) {
|
||||
if line := out.requestLine(t); line["status"] != float64(
|
||||
res.StatusCode,
|
||||
) {
|
||||
t.Errorf("line %v, want status 101", line)
|
||||
}
|
||||
}
|
||||
@@ -1714,7 +1847,8 @@ func TestEachRequestGetsAFreshID(t *testing.T) {
|
||||
ids = append(ids, standIn.question(t).header.Get(requestIDHeader))
|
||||
}
|
||||
|
||||
if slices.Contains(ids, fromTraefik) || ids[0] == "" || ids[0] == ids[1] {
|
||||
if slices.Contains(ids, fromTraefik) || ids[0] == "" ||
|
||||
ids[0] == ids[1] {
|
||||
t.Errorf("ids %v, want two fresh ones", ids)
|
||||
}
|
||||
}
|
||||
@@ -1732,7 +1866,13 @@ func TestLogLineGivesTheRequestAsSent(t *testing.T) {
|
||||
app := startApp(t, greet)
|
||||
addr, out := startRProxy(t, standIn.URL, app.URL, nil)
|
||||
|
||||
req := newRequest(t, http.MethodPost, addr, path+"?"+query, strings.NewReader(body))
|
||||
req := newRequest(
|
||||
t,
|
||||
http.MethodPost,
|
||||
addr,
|
||||
path+"?"+query,
|
||||
strings.NewReader(body),
|
||||
)
|
||||
req.Host = site
|
||||
wantGreeting(t, visit(t, req))
|
||||
|
||||
@@ -1758,7 +1898,10 @@ func TestLogLineGivesTheRequestAsSent(t *testing.T) {
|
||||
}
|
||||
|
||||
if line["default_disposition"] != nil {
|
||||
t.Errorf("default_disposition is %v, want it left out", line["default_disposition"])
|
||||
t.Errorf(
|
||||
"default_disposition is %v, want it left out",
|
||||
line["default_disposition"],
|
||||
)
|
||||
}
|
||||
|
||||
for _, name := range []string{"duration_request_ms", "duration_response_ms"} {
|
||||
|
||||
Reference in new issue
Block a user