A client that stops sending after the app answers is timed out #135

Open
clawbot wants to merge 1 commits from issue-130-client-timeout-after-early-answer into next
Collaborator

Fixes #130.

When the app answered before the client had sent its whole body, and its answer ended with its last bytes, responseReceived stopped every timeout, SWWAF_CLIENT_REQUEST_TIMEOUT included. The transport was still waiting to read the client's body, and Go's server takes the body's lock before it sends an answer's headers, so the answer never went out and the request held its connection until the client closed it.

responseReceived now leaves the timeouts running while the client's body has not arrived whole. They end as they do before the app answers: when the client has sent its body, when the app has been sent the whole request, or when the request is handled. When SWWAF_CLIENT_REQUEST_TIMEOUT runs out, requestTimedOut ends the read as it already did for an app whose answer comes in more than one piece.

What the diff does not show:

  • The client is sent the app's answer, such as the 404, once the time runs out, not the 408 of smallwebwaf, since the app's answer had already started; then the connection is closed. The log line has the app's status and the action timed_out.
  • Judgement call: SWWAF_UPSTREAM_REQUEST_TIMEOUT runs on too, as it does before the app answers, so it still ends such a request while SWWAF_CLIENT_REQUEST_TIMEOUT is off.
  • Not fixed here: a client that sends more once the app has answered, then stops with less than 256 KiB of its body left, is still never timed out, filed as #136.

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/smallwebwaf/issues/130. When the app answered before the client had sent its whole body, and its answer ended with its last bytes, `responseReceived` stopped every timeout, `SWWAF_CLIENT_REQUEST_TIMEOUT` included. The transport was still waiting to read the client's body, and Go's server takes the body's lock before it sends an answer's headers, so the answer never went out and the request held its connection until the client closed it. `responseReceived` now leaves the timeouts running while the client's body has not arrived whole. They end as they do before the app answers: when the client has sent its body, when the app has been sent the whole request, or when the request is handled. When `SWWAF_CLIENT_REQUEST_TIMEOUT` runs out, `requestTimedOut` ends the read as it already did for an app whose answer comes in more than one piece. What the diff does not show: - The client is sent the app's answer, such as the 404, once the time runs out, not the 408 of `smallwebwaf`, since the app's answer had already started; then the connection is closed. The log line has the app's status and the action `timed_out`. - Judgement call: `SWWAF_UPSTREAM_REQUEST_TIMEOUT` runs on too, as it does before the app answers, so it still ends such a request while `SWWAF_CLIENT_REQUEST_TIMEOUT` is `off`. - Not fixed here: a client that sends more once the app has answered, then stops with less than 256 KiB of its body left, is still never timed out, filed as https://git.eeqj.de/sneak/smallwebwaf/issues/136. Model: opus-5-5
clawbot added the needs-review label 2026-10-14 19:34:05 +02:00
clawbot self-assigned this 2026-10-14 19:34:05 +02:00
clawbot added 1 commit 2026-10-14 19:34:05 +02:00
When the app answered before the client had sent its whole body, and its
answer ended with its last bytes, every timeout was stopped,
SWWAF_CLIENT_REQUEST_TIMEOUT included. The transport went on waiting to
read the body, and Go's server cannot send the answer until that read
returns, so a client that stopped sending held the request until it
closed the connection. The timeouts now run on until the client has sent
its body, as they do before the app answers: once
SWWAF_CLIENT_REQUEST_TIMEOUT runs out the client is sent the app's
answer, the connection is closed, and the log line says timed_out.

Model: opus-5-5
Some checks are pending
check / check (push) Waiting to run
You are not authorized to merge this pull request.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin issue-130-client-timeout-after-early-answer:issue-130-client-timeout-after-early-answer
git checkout issue-130-client-timeout-after-early-answer
Sign in to join this conversation.