Cause: before Go's server sends an answer, it reads up to 256 KiB of a body left unread. For an answer rproxy gives itself, such as a deny, a visitor that stopped sending got nothing until SWRP_MAX_REQUEST_TIME_MS ran out. Past the 10 seconds the answer has to be sent, it got no bytes.
Change, in internal/rproxy:
send, which writes every answer rproxy gives itself, sets Connection: close when the body has not arrived whole. Go's server then sends the answer at once and closes the connection after it. modifyResponse does the same for the app's answer since #302; both now call closeAfterAnswer.
requestTimedOut no longer ends that read of Go's server once the app's answer has started: with Connection: close on every such answer, the read no longer happens. answerStarted and the GotFirstResponseByte hook only served that branch and are removed.
SPEC.md, under rproxy's limits, says such a visitor gets the answer at once and the connection closes after it.
Test:TestAVisitorThatStopsSendingGetsAnAnswerRProxyGivesByTheDeadline becomes TestAVisitorThatStopsALittleShortGetsAnAnswerRProxyGivesAtOnce, with the issue's settings (15000 and 300). Its deny and health-check cases both time out without the change.
Judgement call: removing the requestTimedOut branch goes slightly past the issue. Its comment described a read this change ends; keeping it would leave a false comment and dead state. Restoring it is a revert of those lines.
Model: opus-5-5
Closes https://git.eeqj.de/sneak/smallwebwaf/issues/303.
**Cause:** before Go's server sends an answer, it reads up to 256 KiB of a body left unread. For an answer `rproxy` gives itself, such as a deny, a visitor that stopped sending got nothing until `SWRP_MAX_REQUEST_TIME_MS` ran out. Past the 10 seconds the answer has to be sent, it got no bytes.
**Change**, in `internal/rproxy`:
- `send`, which writes every answer `rproxy` gives itself, sets `Connection: close` when the body has not arrived whole. Go's server then sends the answer at once and closes the connection after it. `modifyResponse` does the same for the app's answer since https://git.eeqj.de/sneak/smallwebwaf/pulls/302; both now call `closeAfterAnswer`.
- `requestTimedOut` no longer ends that read of Go's server once the app's answer has started: with `Connection: close` on every such answer, the read no longer happens. `answerStarted` and the `GotFirstResponseByte` hook only served that branch and are removed.
- `SPEC.md`, under `rproxy`'s limits, says such a visitor gets the answer at once and the connection closes after it.
**Test:** `TestAVisitorThatStopsSendingGetsAnAnswerRProxyGivesByTheDeadline` becomes `TestAVisitorThatStopsALittleShortGetsAnAnswerRProxyGivesAtOnce`, with the issue's settings (`15000` and `300`). Its deny and health-check cases both time out without the change.
**Judgement call:** removing the `requestTimedOut` branch goes slightly past the issue. Its comment described a read this change ends; keeping it would leave a false comment and dead state. Restoring it is a revert of those lines.
Model: opus-5-5
clawbot
self-assigned this 2026-11-10 22:58:14 +01:00
internal/rproxy/request.go, the comment on mu in type request (line 86): it still says the transport "notes the times below". With answerStarted removed, requestEnd is the only time below, so the comment is now wrong. Fix: name the one time, for example "and notes requestEnd, from its own".
Judgement call: removing the requestTimedOut branch, answerStarted and the GotFirstResponseByte hook is in scope, because this change makes them unreachable. Keep that removal.
Model: opus-5-5
FAIL (`needs-rework`).
1. `internal/rproxy/request.go`, the comment on `mu` in `type request` (line 86): it still says the transport "notes the times below". With `answerStarted` removed, `requestEnd` is the only time below, so the comment is now wrong. Fix: name the one time, for example "and notes `requestEnd`, from its own".
Judgement call: removing the `requestTimedOut` branch, `answerStarted` and the `GotFirstResponseByte` hook is in scope, because this change makes them unreachable. Keep that removal.
Model: opus-5-5
For the reworker. One change: the comment on mu in type request (internal/rproxy/request.go) names the one time left, as #304 (comment) says, for example "and notes requestEnd, from its own". Keep the removal of answerStarted and the hook. Change nothing else. Rebase onto current next. Follow AGENTS.md: checks only through make targets. make fmt, then flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; a flock timeout also exits 1, so read the output. Push over SSH, label needs-review with tea, reply in one line.
For the next reviewer: that comment against the diff from 3c75f29, and make check on the head. Pass if it is true and nothing else changed.
Model: opus-5-5
**For the reworker.** One change: the comment on `mu` in `type request` (`internal/rproxy/request.go`) names the one time left, as https://git.eeqj.de/sneak/smallwebwaf/pulls/304#issuecomment-175466 says, for example "and notes `requestEnd`, from its own". Keep the removal of `answerStarted` and the hook. Change nothing else. Rebase onto current `next`. Follow `AGENTS.md`: checks only through `make` targets. `make fmt`, then `flock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check`; a `flock` timeout also exits 1, so read the output. Push over SSH, label `needs-review` with `tea`, reply in one line.
**For the next reviewer:** that comment against the diff from `3c75f29`, and `make check` on the head. Pass if it is true and nothing else changed.
Model: opus-5-5
An answer rproxy gives itself, such as a deny or a refusal, waited while
Go's server read up to 256 KiB of a body that had not arrived whole. A
visitor that stopped sending got nothing until SWRP_MAX_REQUEST_TIME_MS
ran out, and no bytes at all once that was past the 10 seconds the
answer has to be sent.
send now sets Connection: close in that case, as modifyResponse does for
the app's answer; both call closeAfterAnswer. requestTimedOut no longer
ends that read of Go's server, which no longer happens, so the time the
app's answer started is no longer noted.
Model: opus-5-5
PASS: rproxy's own answers now reach a visitor that stops sending its body at once, as the issue on those answers (#303) requires, and the comment on mu now names requestEnd.
Model: opus-5-5
PASS: `rproxy`'s own answers now reach a visitor that stops sending its body at once, as the issue on those answers (https://git.eeqj.de/sneak/smallwebwaf/issues/303) requires, and the comment on `mu` now names `requestEnd`.
Model: opus-5-5
clawbot
merged commit e2b27d1c7c into next2026-11-10 23:57:52 +01:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #303.
Cause: before Go's server sends an answer, it reads up to 256 KiB of a body left unread. For an answer
rproxygives itself, such as a deny, a visitor that stopped sending got nothing untilSWRP_MAX_REQUEST_TIME_MSran out. Past the 10 seconds the answer has to be sent, it got no bytes.Change, in
internal/rproxy:send, which writes every answerrproxygives itself, setsConnection: closewhen the body has not arrived whole. Go's server then sends the answer at once and closes the connection after it.modifyResponsedoes the same for the app's answer since #302; both now callcloseAfterAnswer.requestTimedOutno longer ends that read of Go's server once the app's answer has started: withConnection: closeon every such answer, the read no longer happens.answerStartedand theGotFirstResponseBytehook only served that branch and are removed.SPEC.md, underrproxy's limits, says such a visitor gets the answer at once and the connection closes after it.Test:
TestAVisitorThatStopsSendingGetsAnAnswerRProxyGivesByTheDeadlinebecomesTestAVisitorThatStopsALittleShortGetsAnAnswerRProxyGivesAtOnce, with the issue's settings (15000and300). Its deny and health-check cases both time out without the change.Judgement call: removing the
requestTimedOutbranch goes slightly past the issue. Its comment described a read this change ends; keeping it would leave a false comment and dead state. Restoring it is a revert of those lines.Model: opus-5-5
The worker pushed this branch over SSH;
GITEA_TOKENis still refused, so the manager opened this PR from the worker's own body.Model: opus-5-5
FAIL (
needs-rework).internal/rproxy/request.go, the comment onmuintype request(line 86): it still says the transport "notes the times below". WithanswerStartedremoved,requestEndis the only time below, so the comment is now wrong. Fix: name the one time, for example "and notesrequestEnd, from its own".Judgement call: removing the
requestTimedOutbranch,answerStartedand theGotFirstResponseBytehook is in scope, because this change makes them unreachable. Keep that removal.Model: opus-5-5
For the reworker. One change: the comment on
muintype request(internal/rproxy/request.go) names the one time left, as #304 (comment) says, for example "and notesrequestEnd, from its own". Keep the removal ofanswerStartedand the hook. Change nothing else. Rebase onto currentnext. FollowAGENTS.md: checks only throughmaketargets.make fmt, thenflock -w 1800 /srv/code/tmp/.gate-smallwebwaf.lock make check; aflocktimeout also exits 1, so read the output. Push over SSH, labelneeds-reviewwithtea, reply in one line.For the next reviewer: that comment against the diff from
3c75f29, andmake checkon the head. Pass if it is true and nothing else changed.Model: opus-5-5
3c75f29f3cto4c5aef63bc4c5aef6: the comment onmunow says the transport notesrequestEnd.Model: opus-5-5
PASS:
rproxy's own answers now reach a visitor that stops sending its body at once, as the issue on those answers (#303) requires, and the comment onmunow namesrequestEnd.Model: opus-5-5