Commit a365d5c
fix: a fast upstream failure hung the client instead of answering 502
handleMessages installs an abort so a client that gives up mid-SSE frees the
upstream. It was keyed on clientReq's "close" — which Node emits when the
request BODY has been consumed, i.e. on every request, immediately — so it
aborted while the client was still sitting there, and the forwardRequest catch
opens with `if (aborted) return`. Nothing was written back.
Measured in reverse mode on the real /v1/messages path, against an upstream that
refuses instantly, which is what a dead local hop does:
before body at once -> HANG (6s client timeout) body delayed -> HANG
after body at once -> 502 in 9ms body delayed -> 502 in 52ms
Keyed on clientRes's close instead: it fires when the response finishes OR the
connection is destroyed, so pairing it with writableEnded separates "we
answered" from "the client hung up". Same change in handlePassthrough, which
carried the identical line.
This was found by measuring an exposure I had already dismissed as too risky to
touch. The previous commit recorded it as a latent defect blocking a different
fix; it is not latent, it is on the most ordinary upstream failure there is.
WHAT THE TESTS DO AND DO NOT GUARD, because the difference matters:
the 502 case dies when the listener is reverted to clientReq — mutation-checked
the no-leak case does NOT die when the listener is deleted outright
Two attempts at the second: client takes a frame then leaves (the pipe tears the
upstream down by itself), and an upstream that accepts and never answers so no
pipe exists (still freed). Both passed with the listener removed. So the listener
may be doing nothing that socket teardown does not already do. It stays — "I
could not demonstrate it matters" is not "it does not matter" — and the case is
labelled as pinning the PROPERTY, not guarding the listener, so nobody reads it
as coverage it is not.
ALSO: the relayed probe added in 70ff998 dialled the real api.anthropic.com,
because that test never set CACHE_FIX_PROXY_UPSTREAM and the default is the live
host. That is the trap integrated.conf line 20 already warns about, and it took
CI red on node 22 while bafabae with identical proxy code was green. It now runs
against a local 418, on its own instance — pointing config.upstream at loopback
for the whole case makes the CONNECT half read the tunnel target as the upstream
and stop blind-tunnelling it, which failed the fail-open assertion for an
unrelated reason.
Ref cnighswonger#304
Co-Authored-By: Claude <noreply@anthropic.com>1 parent cf06dc6 commit a365d5c
3 files changed
Lines changed: 138 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
151 | 151 | | |
152 | 152 | | |
153 | 153 | | |
154 | | - | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
155 | 170 | | |
156 | 171 | | |
157 | 172 | | |
| |||
481 | 496 | | |
482 | 497 | | |
483 | 498 | | |
484 | | - | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
485 | 504 | | |
486 | 505 | | |
487 | 506 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
256 | 256 | | |
257 | 257 | | |
258 | 258 | | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
259 | 268 | | |
260 | 269 | | |
261 | 270 | | |
| |||
311 | 320 | | |
312 | 321 | | |
313 | 322 | | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
314 | 331 | | |
315 | 332 | | |
316 | 333 | | |
| |||
319 | 336 | | |
320 | 337 | | |
321 | 338 | | |
322 | | - | |
323 | | - | |
324 | | - | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
325 | 343 | | |
326 | 344 | | |
327 | 345 | | |
328 | 346 | | |
329 | | - | |
| 347 | + | |
330 | 348 | | |
331 | 349 | | |
332 | 350 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
939 | 939 | | |
940 | 940 | | |
941 | 941 | | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
0 commit comments