Skip to content

[✨ Triage] dotnet/runtime#126858 by savitha-qs - HttpClient: PUT/POST uploads stall and time out through HTTPS CONNE ... #195

@MihuBot

Description

@MihuBot

Triage for dotnet/runtime#126858.
Repo filter: All networking issues.
MihuBot version: 43c005.
Ping MihaZupan for any issues.

This is a test triage report generated by AI, aimed at helping the triage team quickly identify past issues/PRs that may be related.
Take any conclusions with a large grain of salt.

Tool logs
dotnet/runtime#126858: HttpClient: PUT/POST uploads stall and time out through HTTPS CONNECT proxy tunnel by savitha-qs
Extracted 5 search queries: HttpClient PUT/POST uploads stall through HTTPS CONNECT proxy tunnel SocketsHttpHandler, HttpClient waiting for Expect: 100-continue when uploading via CONNECT proxy, HTTP/2 negotiation over CONNECT tunnel causing upload stalls with .NET HttpClient, Chunked transfer/content-length upload stalls through HTTPS forward proxy using SocketsHttpHandler, NO_PROXY leading-dot vs wildcard behavior causing proxy bypass issues in .NET
Found 25 candidate issues

Here are the potentially-relevant issues from the search with short summaries and the takeaways that are most likely useful for triaging the new report (uploads stall through an HTTPS CONNECT proxy tunnel). I focused on issues touching: proxy/NO_PROXY handling, CONNECT-tunnel interactions, request-body streaming (Expect: 100-continue / Content-Length / chunked), and HTTP/2/TLS handshake/flow-control behaviors — those are the areas your report suggested investigating.

  • Issue #61840 (Nov 2011) - HttpClient: An asterisk for wildcards in NO_PROXY is not handled properly

    • Summary: Reports that NO_PROXY wildcard syntax (e.g. .domain) is not handled as some users expect; the .NET implementation follows curl conventions (leading-dot works, leading- does not). Discussion led to documentation clarifications rather than changing behavior.
    • Relevance: Your workaround uses NO_PROXY with a leading dot; this issue documents why wildcard forms behave differently and confirms documentation / semantics are distinct in .NET. Useful for follow-up about the workaround and making sure the NO_PROXY behavior is understood.
  • Issue #75199 (Sep 2022) - NO_PROXY: consider matching curl behavior

    • Summary: Follow-up discussion about possibly trimming leading dots / otherwise aligning NO_PROXY semantics to curl for better interop; triage moved to Future. Workarounds and doc suggestions discussed.
    • Relevance: Confirms there is an outstanding enhancement discussion — relevant if the team needs to document/better-guidance the workaround you used.
  • Issue #58249 (Aug 2021) - WebProxy method IsBypassed(uri) returns false although uri is in bypass list

    • Summary: Multiple IWebProxy implementations behave differently (Environment vs Windows proxy), and GetProxy / IsBypassed semantics are inconsistent; suggestion to document expected checking sequence (IsBypassed -> GetProxy).
    • Relevance: Explains subtle differences in proxy-bypass logic across platforms/implementations that complicate reproducing/working around CONNECT-tunnel issues (your report noted leading-dot vs wildcard behavior).
  • Issue #62258 (Dec 2021) - SocketsHttpHandler does not enforce request Content-Length correctness

    • Summary: SocketsHttpHandler historically didn’t detect mismatches between Content-Length header and actual bytes sent; discussion recommended failing / tearing down the connection when lengths mismatch. Moved to Future.
    • Relevance: If request Content-Length is wrong (e.g., Azure SDK or custom HttpContent), server might see truncated body and close/times out; the handler not enforcing the length could produce stalls/timeouts. Worth checking bytes-sent vs Content-Length in a packet capture.
  • Issue #25047 (Feb 2018) - SocketsHttpHandler: Consider exposing Expect:100-continue timeout

    • Summary: The Expect:100-continue wait timeout is hardcoded (1s) and there was an API proposal to make it configurable; discussion compared libcurl defaults.
    • Relevance: Your report lists Expect: 100-continue handling as a suspect. If the client is waiting for 100-continue (or its timer) when tunneled through the proxy, mismatched behavior or delays could manifest as a stall. Packet capture will show whether Expect is being used. The codebase has historically considered this a notable area.
  • Issue #36717 (May 2020) - Faulty request HttpContent might cause a hang in expect 100 Continue scenario

    • Summary: If Expect:100-continue is used and sending the request body fails synchronously (e.g., faulty custom HttpContent), the Expect timer/response path could deadlock and swallow original exception. Proposed fixes: better coordination, tear down the connection on send failure.
    • Relevance: Another Expect-related hang pattern: if client code fails to write body (or Write/Read on body blocks), you can see the client stuck waiting for status. For your repro, verify the content write path is actually progressing (packet capture or instrumenting the HttpContent).
  • Issue #30057 (Jun 2019) - HTTP/2 POST w/ Expect: 100-continue never completing

    • Summary: HTTP/2 + Expect:100-continue had a bug where window updates weren’t sent in some paths, causing deadlocks for POSTs with Expect. Root cause traced to credit/window management; fix/workarounds discussed.
    • Relevance: If the tunneled connection negotiates HTTP/2 to the origin (ALPN over the tunnel) and Expect is involved, this exact class of interaction (Expect + HTTP/2 window/credit logic) is a known source of stalls. Packet capture + TLS ALPN inspection inside tunnel (if possible) or client-side logs should show whether HTTP/2 was negotiated.
  • Issue #30315 / #30318 (Jul 2019) - HTTP/2: Post ExpectAndContinue hangs / large streaming with server flow control

    • Summary: Multiple reports about HTTP/2 + Expect or large streaming encountering hung or failed sends because of credit/flow-control or timeout interactions; many fixes and test changes followed.
    • Relevance: Reinforces that HTTP/2 flow-control/credit interactions can deadlock uploads under certain code-paths (especially with Expect semantics). Given your observation that GETs (download) work but PUT stalls, HTTP/2 send-side flow-control is a strong suspect if HTTP/2 is in use through the tunnel.
  • Issue #43086 (Oct 2020) - HTTP/2 has poor throughput with content larger than initial receive window size

    • Summary: SocketsHttpHandler used relatively small per-stream windows and small thresholds for window updates; that caused frequent small window updates and poor throughput. Work included making stream/connection window behavior configurable and improving default heuristics.
    • Relevance: If HTTP/2 is negotiated through the tunnel, small stream windows and aggressive small window updates can cause the client to send only small amounts then wait — matching your symptom where only ~17 KB went through then a long stall. This is a performance/flow-control vector rather than a bug in proxies.
  • PR #80066 (Dec 2022) - Fix HTTP/2 extended connect hang

    • Summary: A code fix addressing an HTTP/2 “extended CONNECT” hang was implemented (change to exception handling and flow). Merged.
    • Relevance: Shows recent fixes in HTTP/2 CONNECT/extended-connect handling. If your scenario involves extended CONNECT or HTTP/2-specific CONNECT interactions, verify whether the runtime version you run contains this fix (your environment is .NET 8.0.25 — check whether the specific fix and subsequent related patches are included).
  • Issue #106507 (Aug 2024) - HTTP2 connection hangs and causes TaskCanceledException in HttpConnectionPool

    • Summary: Users saw HTTP/2 connection creation hang waiting on TLS handshake / settings frames after an endpoint restart; investigation pointed at SslStream/TLS resume interactions and potential stuck handshake loops. Team requested packet captures and suggested disabling TLS resume as a diagnostic (DOTNET_SYSTEM_NET_SECURITY_DISABLETLSRESUME). Several triage suggestions (keepalive, connect-timeouts) were proposed.
    • Relevance: Your scenario involves CONNECT TLS tunnels. This issue shows that TLS handshake behavior (including TLS session resumption and SslStream internals) can create hangs that look like stalled uploads. Packet capture + trying DOTNET_SYSTEM_NET_SECURITY_DISABLETLSRESUME (or toggling TLS 1.3/1.2) is a recommended diagnostic step per that discussion.
  • Issue #43520 (Oct 2020) - HttpWebRequest timeout broken with proxy/ssl, repro attached

    • Summary: Reported cases where tunneling SSL through a proxy caused timeouts not to be honored (timeo ut semantics around TLS + proxy + response streaming are tricky). Discussion emphasized complexities of applying timeouts/read-write timeouts to the HTTPS-over-proxy sync paths. Triaged to wait for more customer feedback.
    • Relevance: Confirms the CONNECT+TLS+proxy code paths are tricky and can yield surprising timeout/hang behavior; reinforces recommendation to capture network traces and focus on the handshake + read/write behavior over the tunnel.
  • Issue #15542 / #15546 / #15546 family (2015–2016) - HttpClient hangs when sending chunked encoded request / related chunked hang tests

    • Summary: Older reports of hangs when sending chunked requests, especially on certain platforms / handler implementations; many fixes over time focused on async vs sync flush/Write usage and correct async flows.
    • Relevance: If the upload uses chunked transfer and something in the pipeline is doing sync vs async flushes or a handler misbehaves over the tunnel, that can manifest as a send stall. Verify how the upload content is sent (Content-Length vs chunked).
  • Issue #26462 (Jun 2018) - SocketsHttpHandler fails to authenticate to proxy when doing HTTPS tunneling to server

    • Summary: Edge cases with auth schemes (Negotiate/NTLM) and CONNECT tunnels produced 407s; fixes were applied.
    • Relevance: Not directly your case (proxy has no auth), but reminds that CONNECT handling is a subtle area where different auth / proxy responses can change behavior. Proxy logs in your case showed CONNECT succeeded, so auth issues likely not the cause.
  • Issue #62473 (Dec 2021) - HttpClient can’t connect to Kestrel/other web-servers in HTTP/2 only mode (ALPN missing)

    • Summary: Machine-specific Schannel configuration caused client not to include ALPN in TLS ClientHello, so HTTP/2 negotiation failed; resolved by fixing the local TLS provider.
    • Relevance: If HTTP/2 negotiation inside the tunnel is involved, ALPN negotiation problems could change the protocol used and lead to unexpected behavior. For a CONNECT tunnel you should confirm whether ALPN negotiation inside the tunnel is happening and what protocol results.

Takeaways and recommended next diagnostic steps (based on the above related issues)

  • Capture network traces (tcpdump/wireshark) on the client side while reproducing through the proxy (as suggested in your thread and echoed in several linked issues). The capture should show:
    • whether the client sends Expect: 100-continue and whether the origin responds (or whether the client waits)
    • whether TLS inside the CONNECT tunnel negotiates HTTP/1.1 or HTTP/2 (ALPN) — this strongly affects behavior (HTTP/2 flow-control/credits can explain small-send-then-wait symptoms)
    • whether the client actually sends the request body bytes over the tunnel after CONNECT (and their pacing)
  • Enable verbose System.Net/HttpHandler diagnostics on the client (System.Net.Http logging) and correlate with the packet capture timestamps. This helps determine whether the stall is in SocketsHttpHandler, SslStream handshaking, or blocked at the TCP layer.
  • Try reproducing with a minimal HttpClient PUT (no Azure SDK) and with minimal options: explicitly set VersionPolicy and Version (force HTTP/1.1 vs allow HTTP/2) and try forcing/disabling Expect:100-continue and using Content-Length vs chunked. This will help isolate whether the problem is HTTP/2 flow-control, Expect, or chunked/body plumbing in SocketsHttpHandler.
  • Try toggling TLS resume and TLS versions as hot diagnostics (DOTNET_SYSTEM_NET_SECURITY_DISABLETLSRESUME; or force TLS 1.2) as suggested in #106507 if you suspect the handshake is part of the stall.
  • Inspect the request’s Content-Length and the bytes actually sent (packet capture) to rule out Content-Length mismatches (see #62258).
  • Confirm your runtime includes recent HTTP/2 CONNECT/flow-control fixes (e.g., PR #80066 and subsequent changes) — you’re on .NET 8.0.25; check whether any relevant regression fixes are in that servicing baseline.

If you want, I can:

  • produce a short minimal repro outline (HttpClient PUT through a proxy CONNECT) you can run on the same runner to isolate SocketsHttpHandler behavior; or
  • propose the exact tcpdump/Wireshark filters and System.Net tracing switches to capture the most useful artifacts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions