Commit Graph
4 Commits
Author SHA1 Message Date
Thomas Camlong 320c51ac89 fix(http): stop destroying superseded agents, which could abort live requests
Follow-up to the agent caching change. When the trust material changes the caches
are cleared, and that path called agent.destroy() on the node https agents.

Node's documentation for agent.destroy() is "Destroy any sockets that are
currently in use by the agent" - so an admin uploading a certificate could have
aborted an HTTPS request that was already in flight, for instance a nextcloud
calendar sync. The agents run without keepAlive (verified: new https.Agent({})
reports keepAlive false on node 24), so destroying bought nothing anyway; each
socket closes on its own once its response completes.

undici's close() is kept, because it waits for enqueued requests to finish and
therefore cannot interrupt one in flight.

Also verified the correctness premise of sharing a single agent across every
integration, which the previous commit asserted but did not test: three origins
served by one agent each got their own pooled connection, four requests over one
connection apiece, with no response misrouted between them.
2026-08-13 15:36:12 +02:00
Thomas Camlong 3ba2800db9 perf(http): reuse the certificate agent instead of building one per request
fetchWithTrustedCertificatesAsync has 125 call sites and none of them pass a
dispatcher, so every HTTP request Homarr makes - every integration poll, every
proxied image - built a brand new EnvHttpProxyAgent. An agent owns its
connection pool and its TLS session cache, so a fresh one per request means a
full TLS handshake every time and no keep-alive reuse at all.

Measured against a local TLS server, 60 sequential requests:

  fresh agent per request   5.11 ms/req   60 TLS handshakes
  one shared agent          1.69 ms/req    2 TLS handshakes

3.0x faster and 30x fewer handshakes on loopback; over a real network the gap
is larger, since that is where handshake round-trips actually cost something.

Agent construction itself is cheap (0.004 ms, 1.7 KiB) because undici builds
the TLS store lazily at connect time - so the cost was never construction, it
was the handshake that a fresh pool forces.

The trust material is still read on every call and the cached agents are keyed
on a hash of it, so adding or removing a certificate - including by dropping a
file into the mounted folder rather than going through the UI - takes effect on
the very next request, exactly as before. Superseded agents are closed so their
idle sockets are released.
2026-08-11 16:09:37 +02:00
Meier Lukas 5a57115ca0 feat(http): add proxy support (#4721) 2025-12-25 11:32:14 +01:00
Meier Lukas 6f0dbae121 refactor(http): move to core package (#4690) 2025-12-19 16:37:21 +01:00