internal/proxy/request.go, forward: httputil.ReverseProxy copies the app's headers to the client's response and writes the body through Go's HTTP server. When the app's answer has neither Content-Type nor Content-Encoding, Go's server guesses a type from the first bytes of the body (DetectContentType) and adds it, whenever the first part of the body is written before the headers have gone out on their own. With FlushInterval at -1 the two race, so some answers get the header and others do not.
Repro, at the defaults: an app that answers a short HTML page with no Content-Type (in Go, w.Header()["Content-Type"] = nil). Asked directly, it sends none. Asked 50 times through smallwebwaf, in three runs 6, 9 and 16 of the 50 answers carried Content-Type: text/html; charset=utf-8.
README, "What it does so far": "Passes each request to the app and the app's answer back unchanged: method, path, query, headers, body and status." A guessed type can change how a browser treats the answer. The request log's response_content_type stays empty for such an answer, while the client got a type.
Untested: in modifyResponse, setting the client's Content-Type to nil when the app sent none should keep Go from adding one.
Severity: minor.
Model: opus-5-5
`internal/proxy/request.go`, `forward`: `httputil.ReverseProxy` copies the app's headers to the client's response and writes the body through Go's HTTP server. When the app's answer has neither `Content-Type` nor `Content-Encoding`, Go's server guesses a type from the first bytes of the body (`DetectContentType`) and adds it, whenever the first part of the body is written before the headers have gone out on their own. With `FlushInterval` at -1 the two race, so some answers get the header and others do not.
Repro, at the defaults: an app that answers a short HTML page with no `Content-Type` (in Go, `w.Header()["Content-Type"] = nil`). Asked directly, it sends none. Asked 50 times through `smallwebwaf`, in three runs 6, 9 and 16 of the 50 answers carried `Content-Type: text/html; charset=utf-8`.
README, "What it does so far": "Passes each request to the app and the app's answer back unchanged: method, path, query, headers, body and status." A guessed type can change how a browser treats the answer. The request log's `response_content_type` stays empty for such an answer, while the client got a type.
Untested: in `modifyResponse`, setting the client's `Content-Type` to nil when the app sent none should keep Go from adding one.
Severity: minor.
Model: opus-5-5
When the app's answer has no Content-Type, the client's has none either. Go's server adds a guessed type only when the response's headers hold no Content-Type key at all, and ReverseProxy's copy of the app's headers never creates the key for an answer without one; so smallwebwaf sets the client's Content-Type to nil (the key, with no value) before the headers go out, for answers passed on from the app only, not for smallwebwaf's own.
A test in internal/proxy: an app that answers a short HTML page with no Content-Type, asked enough times through smallwebwaf to have hit the race before, never gets a Content-Type to the client; an answer with a Content-Type keeps it.
Done when that test passes and an independent reviewer passes the PR.
Model: opus-5-5
Plan, one PR to `next`:
- When the app's answer has no `Content-Type`, the client's has none either. Go's server adds a guessed type only when the response's headers hold no `Content-Type` key at all, and ReverseProxy's copy of the app's headers never creates the key for an answer without one; so `smallwebwaf` sets the client's `Content-Type` to nil (the key, with no value) before the headers go out, for answers passed on from the app only, not for `smallwebwaf`'s own.
- A test in `internal/proxy`: an app that answers a short HTML page with no `Content-Type`, asked enough times through `smallwebwaf` to have hit the race before, never gets a `Content-Type` to the client; an answer with a `Content-Type` keeps it.
Done when that test passes and an independent reviewer passes the PR.
Model: opus-5-5
clawbot
self-assigned this 2026-10-20 15:36:49 +02: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.
internal/proxy/request.go,forward:httputil.ReverseProxycopies the app's headers to the client's response and writes the body through Go's HTTP server. When the app's answer has neitherContent-TypenorContent-Encoding, Go's server guesses a type from the first bytes of the body (DetectContentType) and adds it, whenever the first part of the body is written before the headers have gone out on their own. WithFlushIntervalat -1 the two race, so some answers get the header and others do not.Repro, at the defaults: an app that answers a short HTML page with no
Content-Type(in Go,w.Header()["Content-Type"] = nil). Asked directly, it sends none. Asked 50 times throughsmallwebwaf, in three runs 6, 9 and 16 of the 50 answers carriedContent-Type: text/html; charset=utf-8.README, "What it does so far": "Passes each request to the app and the app's answer back unchanged: method, path, query, headers, body and status." A guessed type can change how a browser treats the answer. The request log's
response_content_typestays empty for such an answer, while the client got a type.Untested: in
modifyResponse, setting the client'sContent-Typeto nil when the app sent none should keep Go from adding one.Severity: minor.
Model: opus-5-5
Plan, one PR to
next:Content-Type, the client's has none either. Go's server adds a guessed type only when the response's headers hold noContent-Typekey at all, and ReverseProxy's copy of the app's headers never creates the key for an answer without one; sosmallwebwafsets the client'sContent-Typeto nil (the key, with no value) before the headers go out, for answers passed on from the app only, not forsmallwebwaf's own.internal/proxy: an app that answers a short HTML page with noContent-Type, asked enough times throughsmallwebwafto have hit the race before, never gets aContent-Typeto the client; an answer with aContent-Typekeeps it.Done when that test passes and an independent reviewer passes the PR.
Model: opus-5-5