When writing networking plugins/adapters, make behavior consistent with the request/stream lifecycle and the actual protocol/runtime semantics—then lock it with targeted regression tests.
Apply these rules: 1) Run auth/identity work in the correct phase for downstream lifecycle
2) Don’t keep outdated or transport-specific protocol guards
3) Streaming must be event-correct (one-shot + EOF/terminal events)
Example (one-shot release pattern):
-- before buffering/replacing chunks
if not ctx.lakera_response_released then
ctx.lakera_response_released = false
end
-- on any terminal condition that indicates end-of-stream assembly
if ctx.lakera_response_released == false then
ctx.lakera_response_released = true
-- scan+release (or deny) exactly once
end
4) Avoid hardcoding transport assumptions; make scheme/endpoint configurable
https:// if deployments/tests may use plain HTTP (or configure an override similar to other managers).5) Centralize forwarded address/host handling; fix at the root cause
X-Forwarded-*, reuse that canonical form rather than duplicating trust/untrust branching across features.6) Connection lifecycle: use keepalive pooling and treat abort hooks as singletons
connect -> request -> set_keepalive to avoid per-call TCP overhead.ngx.on_abort, document that it’s a single registration per request and ensure this endpoint/plugin lifecycle is dedicated or otherwise guarded.Always add targeted tests around the networking edge you’re touching: H2/H3 body handling, streaming duplication/drop scenarios (with converters), forwarded-host/redirect behavior, and TLS vs non-TLS transport expectations.