Format Go with gofmt, then golines -m 77 (closes #215)
check / check (push) Waiting to run

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:
sneak committed 2026-11-11 15:14:58 +00:00
1 parent 63e58e326b
commit 7f8a59de04
118 files changed
+9447 -2670

No files matched your search

+256 -80
View File
@@ -34,13 +34,15 @@ func announcedLength(size int) string {
func TestServerHasTheFixedLimits(t *testing.T) {
t.Parallel()
cfg, err := config.RProxyFromEnvironment(func(name string) (string, bool) {
if name == "SWRP_WAF_BACKEND" {
return nowhere, true
}
cfg, err := config.RProxyFromEnvironment(
func(name string) (string, bool) {
if name == "SWRP_WAF_BACKEND" {
return nowhere, true
}
return "", false
})
return "", false
},
)
if err != nil {
t.Fatalf("settings: %v", err)
}
@@ -48,14 +50,23 @@ func TestServerHasTheFixedLimits(t *testing.T) {
server := rproxy.New(rproxy.Params{
Config: cfg,
RequestLog: io.Discard,
ProcessLog: requestlog.NewProcessLogger(io.Discard, "test", slog.LevelInfo),
ProcessLog: requestlog.NewProcessLogger(
io.Discard,
"test",
slog.LevelInfo,
),
})
if server.Addr != ":8080" || server.MaxHeaderBytes != 28<<10 ||
server.IdleTimeout != 2*time.Minute || server.ReadHeaderTimeout != time.Minute {
t.Errorf("server listens on %q with header limit %d, idle time %s and "+
"header timeout %s", server.Addr, server.MaxHeaderBytes,
server.IdleTimeout, server.ReadHeaderTimeout)
t.Errorf(
"server listens on %q with header limit %d, idle time %s and "+
"header timeout %s",
server.Addr,
server.MaxHeaderBytes,
server.IdleTimeout,
server.ReadHeaderTimeout,
)
}
}
@@ -76,9 +87,14 @@ func TestABodyAnnouncedOverItsLimitIsRefusedOnceWAFAllowsIt(t *testing.T) {
app := startApp(t, func(http.ResponseWriter, *http.Request) {
t.Error("the app was asked")
})
addr, _ := startRProxy(t, standIn.URL, app.URL, map[string]string{
maxRequestSize: tc.limit,
})
addr, _ := startRProxy(
t,
standIn.URL,
app.URL,
map[string]string{
maxRequestSize: tc.limit,
},
)
got := visit(t, newRequest(t, http.MethodPost, addr, "/",
bytes.NewReader(make([]byte, tc.size))))
@@ -87,7 +103,11 @@ func TestABodyAnnouncedOverItsLimitIsRefusedOnceWAFAllowsIt(t *testing.T) {
}
if asked := standIn.question(t); len(asked.body) != tc.asked {
t.Errorf("the question carries %d bytes, want %d", len(asked.body), tc.asked)
t.Errorf(
"the question carries %d bytes, want %d",
len(asked.body),
tc.asked,
)
}
report := standIn.report(t)
@@ -138,13 +158,21 @@ func TestABodyNotAnnouncedOverItsLimitIsRefused(t *testing.T) {
asked.Store(true)
greet(w, r)
})
addr, _ := startRProxy(t, standIn.URL, app.URL, map[string]string{
maxRequestSize: tc.limit,
})
addr, _ := startRProxy(
t,
standIn.URL,
app.URL,
map[string]string{
maxRequestSize: tc.limit,
},
)
conn := dial(t, addr)
send(t, conn, post+"Transfer-Encoding: chunked\r\n\r\n"+
strconv.FormatInt(int64(tc.size), 16)+"\r\n"+strings.Repeat("x", tc.size)+
strconv.FormatInt(
int64(tc.size),
16,
)+"\r\n"+strings.Repeat("x", tc.size)+
"\r\n0\r\n\r\n")
if status := readStatus(t, conn); status != http.StatusRequestEntityTooLarge {
@@ -203,17 +231,26 @@ func TestAResponseOverItsLimit(t *testing.T) {
text, err := io.ReadAll(conn)
if err != nil || bytes.Contains(text, []byte(large)) {
t.Errorf("read %d bytes (%v), want the answer cut off", len(text), err)
t.Errorf(
"read %d bytes (%v), want the answer cut off",
len(text),
err,
)
}
report := standIn.report(t)
if report.Status != http.StatusOK || report.ResponseBytes > 1<<10 {
t.Errorf("report %+v, want status 200 and at most 1K of the answer", report)
t.Errorf(
"report %+v, want status 200 and at most 1K of the answer",
report,
)
}
})
}
func TestAHeadWhoseAnswerAnnouncesMoreThanTheResponseLimitIsPassedOn(t *testing.T) {
func TestAHeadWhoseAnswerAnnouncesMoreThanTheResponseLimitIsPassedOn(
t *testing.T,
) {
t.Parallel()
const announced = "2048"
@@ -227,8 +264,13 @@ func TestAHeadWhoseAnswerAnnouncesMoreThanTheResponseLimitIsPassedOn(t *testing.
})
got := visit(t, newRequest(t, http.MethodHead, addr, "/", http.NoBody))
if got.status != http.StatusOK || got.header.Get(contentLengthHeader) != announced {
t.Errorf("answered %+v, want the app's 200 announcing %s bytes", got, announced)
if got.status != http.StatusOK ||
got.header.Get(contentLengthHeader) != announced {
t.Errorf(
"answered %+v, want the app's 200 announcing %s bytes",
got,
announced,
)
}
}
@@ -243,14 +285,22 @@ func TestASettingOfOffSetsNoLimit(t *testing.T) {
standIn := startWAF(t, allow)
app := startApp(t, greet)
addr, _ := startRProxy(t, standIn.URL, app.URL, map[string]string{
setting: "off",
})
addr, _ := startRProxy(
t,
standIn.URL,
app.URL,
map[string]string{
setting: "off",
},
)
// A body and an answer that a limit of zero would cut off, as it would the
// next answer, which rproxy gives itself.
wantGreeting(t, visit(t, newRequest(t, http.MethodPost, addr, "/",
strings.NewReader("a body"))))
wantGreeting(
t,
visit(t, newRequest(t, http.MethodPost, addr, "/",
strings.NewReader("a body"))),
)
if got := get(t, addr, waf.HealthPath); got.status != http.StatusOK {
t.Errorf("answered %+v, want rproxy's own 200", got)
@@ -273,9 +323,14 @@ func TestAVisitorTooSlowToSendTheFirstPartIsAnswered408(t *testing.T) {
standIn := startWAF(t, allow)
app := startApp(t, greet)
addr, out := startRProxy(t, standIn.URL, app.URL, map[string]string{
maxRequestTime: "500",
})
addr, out := startRProxy(
t,
standIn.URL,
app.URL,
map[string]string{
maxRequestTime: "500",
},
)
conn := dial(t, addr)
send(t, conn, post+tc.rest)
@@ -319,7 +374,9 @@ func TestAVisitorThatGoesAwayBeforeTheFirstPartIsNotAsked(t *testing.T) {
}
}
func TestABodyThatCannotBeReadClosesTheConnectionWithoutAnAnswer(t *testing.T) {
func TestABodyThatCannotBeReadClosesTheConnectionWithoutAnAnswer(
t *testing.T,
) {
t.Parallel()
for _, tc := range []struct {
@@ -356,8 +413,11 @@ func TestABodyThatCannotBeReadClosesTheConnectionWithoutAnAnswer(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,
)
}
line := out.requestLine(t)
@@ -402,7 +462,8 @@ func (w *deadlineRecorder) FlushError() error {
func (w *deadlineRecorder) SetReadDeadline(deadline time.Time) error {
w.readDeadline = deadline
if w.stalled != nil && !deadline.IsZero() && !deadline.After(time.Now()) {
if w.stalled != nil && !deadline.IsZero() &&
!deadline.After(time.Now()) {
_ = w.stalled.CloseWithError(os.ErrDeadlineExceeded)
}
@@ -439,12 +500,22 @@ func TestABodyLeftUnreadIsReadOnlyUntilTheRequestTimeLimit(t *testing.T) {
t.Cleanup(func() { _ = stop.Close() })
req := httptest.NewRequestWithContext(t.Context(), http.MethodPost, "/",
io.MultiReader(bytes.NewReader(make([]byte, questionBodyMaxBytes+1)), stalled))
req := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/",
io.MultiReader(
bytes.NewReader(make([]byte, questionBodyMaxBytes+1)),
stalled,
),
)
req.ContentLength = announced
req.Header.Set(contentLengthHeader, strconv.Itoa(announced))
w := &deadlineRecorder{ResponseRecorder: httptest.NewRecorder(), stalled: stop}
w := &deadlineRecorder{
ResponseRecorder: httptest.NewRecorder(),
stalled: stop,
}
before := time.Now()
@@ -456,12 +527,17 @@ func TestABodyLeftUnreadIsReadOnlyUntilTheRequestTimeLimit(t *testing.T) {
if w.readDeadline.Before(before.Add(limit)) ||
w.readDeadline.After(time.Now().Add(limit)) {
t.Errorf("the reading of the body ends at %s, want %s from the request",
w.readDeadline, limit)
t.Errorf(
"the reading of the body ends at %s, want %s from the request",
w.readDeadline,
limit,
)
}
}
func TestABodyLeftUnreadIsReadNoMoreOnceTheTimeToSendTheAnswerRunsOut(t *testing.T) {
func TestABodyLeftUnreadIsReadNoMoreOnceTheTimeToSendTheAnswerRunsOut(
t *testing.T,
) {
t.Parallel()
standIn := startWAF(t, allow)
@@ -473,8 +549,15 @@ func TestABodyLeftUnreadIsReadNoMoreOnceTheTimeToSendTheAnswerRunsOut(t *testing
t.Cleanup(func() { _ = stop.Close() })
req := httptest.NewRequestWithContext(t.Context(), http.MethodPost, "/",
io.MultiReader(bytes.NewReader(make([]byte, questionBodyMaxBytes+1)), stalled))
req := httptest.NewRequestWithContext(
t.Context(),
http.MethodPost,
"/",
io.MultiReader(
bytes.NewReader(make([]byte, questionBodyMaxBytes+1)),
stalled,
),
)
req.ContentLength = 2 * questionBodyMaxBytes
req.Header.Set(contentLengthHeader, strconv.Itoa(2*questionBodyMaxBytes))
@@ -496,7 +579,10 @@ func TestABodyLeftUnreadIsReadNoMoreOnceTheTimeToSendTheAnswerRunsOut(t *testing
}
if w.readDeadline.Before(before) || w.readDeadline.After(time.Now()) {
t.Errorf("the reading of the body ends at %s, want now", w.readDeadline)
t.Errorf(
"the reading of the body ends at %s, want now",
w.readDeadline,
)
}
}
@@ -517,12 +603,24 @@ func TestAnAnswerRProxyGivesItselfHasTheResponseTimeToBeSent(t *testing.T) {
standIn := startWAF(t, deny)
app := startApp(t, greet)
_, _, server := startServer(t, standIn.URL, app.URL, map[string]string{
maxResponseTime: strconv.FormatInt(limit.Milliseconds(), 10),
})
_, _, server := startServer(
t,
standIn.URL,
app.URL,
map[string]string{
maxResponseTime: strconv.FormatInt(
limit.Milliseconds(),
10,
),
},
)
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, tc.target,
http.NoBody)
req := httptest.NewRequestWithContext(
t.Context(),
http.MethodGet,
tc.target,
http.NoBody,
)
w := &deadlineRecorder{ResponseRecorder: httptest.NewRecorder()}
before := time.Now()
@@ -535,14 +633,19 @@ func TestAnAnswerRProxyGivesItselfHasTheResponseTimeToBeSent(t *testing.T) {
if w.writeDeadline.Before(before.Add(limit)) ||
w.writeDeadline.After(time.Now().Add(limit)) {
t.Errorf("the time limit on sending ends at %s, want %s from the answer",
w.writeDeadline, limit)
t.Errorf(
"the time limit on sending ends at %s, want %s from the answer",
w.writeDeadline,
limit,
)
}
})
}
}
func TestAnAnswerRProxyGivesItselfHasTenSecondsToBeSentAtLeast(t *testing.T) {
func TestAnAnswerRProxyGivesItselfHasTenSecondsToBeSentAtLeast(
t *testing.T,
) {
t.Parallel()
const least = 10 * time.Second
@@ -553,7 +656,12 @@ func TestAnAnswerRProxyGivesItselfHasTenSecondsToBeSentAtLeast(t *testing.T) {
maxResponseTime: "300",
})
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", http.NoBody)
req := httptest.NewRequestWithContext(
t.Context(),
http.MethodGet,
"/",
http.NoBody,
)
w := &deadlineRecorder{ResponseRecorder: httptest.NewRecorder()}
before := time.Now()
@@ -561,8 +669,11 @@ func TestAnAnswerRProxyGivesItselfHasTenSecondsToBeSentAtLeast(t *testing.T) {
server.Handler.ServeHTTP(w, req)
if w.writeDeadline.Before(before.Add(least)) {
t.Errorf("the time limit on sending ends at %s, want %s from the answer at least",
w.writeDeadline, least)
t.Errorf(
"the time limit on sending ends at %s, want %s from the answer at least",
w.writeDeadline,
least,
)
}
}
@@ -583,7 +694,9 @@ func TestAVisitorTooSlowToSendTheRestIsAnswered408(t *testing.T) {
t.Errorf("status %d, want 408", status)
}
if asked := standIn.question(t); len(asked.body) != questionBodyMaxBytes {
if asked := standIn.question(t); len(
asked.body,
) != questionBodyMaxBytes {
t.Errorf("the question carries %d bytes", len(asked.body))
}
@@ -597,7 +710,11 @@ func TestAVisitorTooSlowToSendTheRestIsAnswered408(t *testing.T) {
func startAppThatTakesNothing(t *testing.T) 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)
}
@@ -686,7 +803,9 @@ func TestAnAppTooSlowToAnswerIsAnswered504(t *testing.T) {
}
}
func TestAVisitorGetsAnAnswerWhenTheAppAnswersAsTheTimeRunsOut(t *testing.T) {
func TestAVisitorGetsAnAnswerWhenTheAppAnswersAsTheTimeRunsOut(
t *testing.T,
) {
t.Parallel()
// Four visitors at a time, each with an app and rproxy of its own, send more
@@ -785,8 +904,13 @@ func TestAnAppTooSlowToFinishItsAnswerIsCutOff(t *testing.T) {
if res.StatusCode != http.StatusOK || string(body) != start ||
!errors.Is(err, io.ErrUnexpectedEOF) {
t.Errorf("answered %d %q (%v), want the app's 200 %q, then the connection closed",
res.StatusCode, body, err, start)
t.Errorf(
"answered %d %q (%v), want the app's 200 %q, then the connection closed",
res.StatusCode,
body,
err,
start,
)
}
if report := standIn.report(t); report.Status != http.StatusOK {
@@ -827,13 +951,17 @@ func TestAVisitorTooSlowToTakeTheAnswerIsCutOff(t *testing.T) {
line := out.requestLine(t)
responseBytes, _ := line["response_bytes"].(float64)
if line["status"] != float64(http.StatusOK) || responseBytes >= bodySize {
if line["status"] != float64(http.StatusOK) ||
responseBytes >= bodySize {
t.Errorf("line %v, want status 200 and the answer cut off", line)
}
report := standIn.report(t)
if report.Status != http.StatusOK || report.ResponseBytes >= bodySize {
t.Errorf("report %+v, want status 200 and the answer cut off", report)
t.Errorf(
"report %+v, want status 200 and the answer cut off",
report,
)
}
}
@@ -853,7 +981,9 @@ func TestAnAppThatCannotBeReachedIsAnswered502WithAReport(t *testing.T) {
}
}
func TestAVisitorThatStopsSendingAfterTheAppHasAnsweredGetsTheAnswer(t *testing.T) {
func TestAVisitorThatStopsSendingAfterTheAppHasAnsweredGetsTheAnswer(
t *testing.T,
) {
t.Parallel()
standIn := startWAF(t, allow)
@@ -937,7 +1067,9 @@ func TestAVisitorThatStopsALittleShortGetsTheAppsAnswerAtOnce(t *testing.T) {
wantGreeting(t, readAnswer(t, conn))
}
func TestAVisitorThatStopsALittleShortIsReadUntilTheRequestTimeLimit(t *testing.T) {
func TestAVisitorThatStopsALittleShortIsReadUntilTheRequestTimeLimit(
t *testing.T,
) {
t.Parallel()
const limit = 2 * time.Second
@@ -961,7 +1093,11 @@ func TestAVisitorThatStopsALittleShortIsReadUntilTheRequestTimeLimit(t *testing.
}
if closed := time.Since(start); closed < limit {
t.Errorf("the connection closed after %s, want %s at least", closed, limit)
t.Errorf(
"the connection closed after %s, want %s at least",
closed,
limit,
)
}
}
@@ -992,7 +1128,8 @@ func TestAVisitorThatStopsALittleShortHasTheConnectionClosedWhenTheAnswerIsCutOf
rc := http.NewResponseController(w)
_ = rc.EnableFullDuplex()
w.Header().Set(contentLengthHeader, strconv.Itoa(len(greeting)))
w.Header().
Set(contentLengthHeader, strconv.Itoa(len(greeting)))
for _, part := range tc.atOnce {
_, _ = io.WriteString(w, part)
@@ -1010,10 +1147,18 @@ func TestAVisitorThatStopsALittleShortHasTheConnectionClosedWhenTheAnswerIsCutOf
})
// The request time limit is far longer than dial's deadline.
addr, _ := startRProxy(t, standIn.URL, app.URL, map[string]string{
maxRequestTime: "120000",
maxResponseTime: strconv.FormatInt(limit.Milliseconds(), 10),
})
addr, _ := startRProxy(
t,
standIn.URL,
app.URL,
map[string]string{
maxRequestTime: "120000",
maxResponseTime: strconv.FormatInt(
limit.Milliseconds(),
10,
),
},
)
conn := dial(t, addr)
sendAllButALittle(t, conn)
@@ -1030,7 +1175,12 @@ func TestAVisitorThatStopsALittleShortHasTheConnectionClosedWhenTheAnswerIsCutOf
want := strings.Join(tc.atOnce, "")
if string(body) != want || !errors.Is(err, io.ErrUnexpectedEOF) {
t.Errorf("read %q (%v), want %q and the connection closed", body, err, want)
t.Errorf(
"read %q (%v), want %q and the connection closed",
body,
err,
want,
)
}
})
}
@@ -1068,7 +1218,11 @@ func TestAVisitorThatStopsSendingWhileTheAppWorksGetsNoAnswer(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,
)
}
if line := out.requestLine(t); line["status"] != 0.0 {
@@ -1076,7 +1230,9 @@ func TestAVisitorThatStopsSendingWhileTheAppWorksGetsNoAnswer(t *testing.T) {
}
}
func TestTheRequestTimeLimitDoesNotCutAnAnswerOnceTheAppHasTheRequest(t *testing.T) {
func TestTheRequestTimeLimitDoesNotCutAnAnswerOnceTheAppHasTheRequest(
t *testing.T,
) {
t.Parallel()
const answer = "the end of a long answer"
@@ -1094,13 +1250,28 @@ func TestTheRequestTimeLimitDoesNotCutAnAnswerOnceTheAppHasTheRequest(t *testing
maxRequestTime: "2000",
})
got := visit(t, newRequest(t, http.MethodPost, addr, "/", strings.NewReader("a body")))
got := visit(
t,
newRequest(
t,
http.MethodPost,
addr,
"/",
strings.NewReader("a body"),
),
)
if got.status != http.StatusOK || got.body != answer {
t.Errorf("answered %d %q, want the app's whole answer", got.status, got.body)
t.Errorf(
"answered %d %q, want the app's whole answer",
got.status,
got.body,
)
}
}
func TestAVisitorThatStopsALittleShortGetsAnAnswerRProxyGivesAtOnce(t *testing.T) {
func TestAVisitorThatStopsALittleShortGetsAnAnswerRProxyGivesAtOnce(
t *testing.T,
) {
t.Parallel()
for _, tc := range []struct {
@@ -1121,10 +1292,15 @@ func TestAVisitorThatStopsALittleShortGetsAnAnswerRProxyGivesAtOnce(t *testing.T
app := startApp(t, greet)
// The request time limit is longer than the 10 seconds an answer rproxy
// gives itself has to be sent, and than dial's deadline.
addr, _ := startRProxy(t, standIn.URL, app.URL, map[string]string{
maxRequestTime: "15000",
maxResponseTime: "300",
})
addr, _ := startRProxy(
t,
standIn.URL,
app.URL,
map[string]string{
maxRequestTime: "15000",
maxResponseTime: "300",
},
)
// The body stops 100 bytes short, less than Go's server reads of a body
// left unread before it answers.