caddy/modules/caddyhttp
SillyZir df44d6c383
encode: flush headers immediately for server-sent events responses (#7905)
* encode: flush headers immediately for server-sent events responses

The encode middleware withholds the response header until the first body
write so it can sniff content-type and apply the minimum_length threshold.
For a text/event-stream response the upstream typically writes headers and
flushes to establish the event stream before any event body is available,
so the client never received the headers and the stream stalled; the same
buffering also delayed individual events.

When WriteHeader sees a text/event-stream content type, initialize encoding
and write the header through immediately. Forcing the header out also marks
the response as started, so subsequent event writes bypass the minimum_length
buffering and stream to the client as they arrive.

Fixes #6293

* encode: add WriteHeader benchmark covering SSE fast path

* encode: replace mime.ParseMediaType with bound-checked SSE check

WriteHeader runs an SSE Content-Type check on every call once headers
haven't been written yet. mime.ParseMediaType parses the full media
type, including parameters, even when nothing matches, which shows up
on the hot header-write path.

Replace it with a bound-checked manual prefix/boundary check (isSSE),
skipping parameter parsing for the common non-SSE case.

* encode: reject content types with junk after text/event-stream

isSSE accepted any suffix after a space, so a value like
"text/event-stream nonsense" was treated as an SSE response. After the
media type, skip optional whitespace and require either the end of the
value or a parameter separator. The check remains allocation-free, so
the hot-path motivation for the manual matcher is preserved.

---------

Co-authored-by: SillyZir <269283839+SillyZir@users.noreply.github.com>
Co-authored-by: Kévin Dunglas <kevin@les-tilleuls.coop>
2026-08-01 00:27:28 +10:00
..
caddyauth caddyhttp: use canonical header key casing to avoid re-canonicalization (#7911) 2026-07-30 20:40:35 +10:00
encode encode: flush headers immediately for server-sent events responses (#7905) 2026-08-01 00:27:28 +10:00
fileserver
headers
intercept intercept: fix misleading handle_response error for extra matcher args (#7871) 2026-07-12 09:16:34 +10:00
logging
map
proxyprotocol
push
requestbody
reverseproxy reverseproxy: fix broken reservoir sampling in random_choose policy (#7873) 2026-07-12 09:25:31 +10:00
rewrite rewrite: preserve non-canonical path encoding after uri replace (#7907) 2026-07-26 08:49:44 +10:00
standard
templates
tracing
app.go
autohttps.go
autohttps_test.go
caddyhttp.go
caddyhttp_test.go
celmatcher.go build(deps): bump cel-go from v0.28.1 to v0.29.2 (#7872) 2026-07-12 09:17:08 +10:00
celmatcher_test.go caddyhttp: add URL pattern request matcher (#7787) 2026-06-22 10:25:43 -06:00
errors.go
http2listener.go
httpredirectlistener.go
invoke.go
ip_matchers.go
ip_range.go
logging.go
marshalers.go
matchers.go caddyhttp: use canonical header key casing to avoid re-canonicalization (#7911) 2026-07-30 20:40:35 +10:00
matchers_test.go caddyhttp: fix path_regexp (MatchPathRE) Windows backslash bypass (#7858) 2026-07-11 08:37:44 +10:00
metrics.go
metrics_test.go
replacer.go
replacer_test.go
responsematchers.go
responsematchers_test.go
responsewriter.go
responsewriter_test.go
routes.go
server.go Set the QUIC InitialPacketSize to 1200 bytes (#7886) 2026-07-26 08:48:25 +10:00
server_test.go
staticerror.go
staticresp.go chore: fix sabotage spelling in nolint comments (#7892) 2026-07-18 08:14:38 +00:00
staticresp_test.go
subroute.go
urlpatternmatcher.go caddyhttp: add URL pattern request matcher (#7787) 2026-06-22 10:25:43 -06:00
urlpatternmatcher_test.go caddyhttp: add URL pattern request matcher (#7787) 2026-06-22 10:25:43 -06:00
vars.go
vars_test.go