AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Inspect HTTP/2 cancellation before relaxing abuse defenses

Go clients can trigger HTTP/2 defenses through response handling. Inspect control frames, body consumption and cancellation while keeping resource limits.

Citiți articolul în română

An HTTP/2 abuse error can describe the traffic a client produced even when its application had legitimate intent. Before relaxing a server's protection, examine how the client consumes responses and cancels streams. Correct application behavior includes resource limits, so the remedy must preserve deliberate cancellation as well as eliminate unnecessary protocol work.

Looking back from November 2026, Cloudflare's account of 31 October 2025 is a useful diagnostic example. Its engineers attributed ENHANCE_YOUR_CALM closures to PING-flood protection. Their reproduction showed resets followed by PINGs when closing unconsumed response bodies, even empty ones. Reading before closing removed those frames in their example. That is Cloudflare's reported investigation and result; this article reports no AL+ reproduction or client change.

The connection tells a different story from the request count

A dashboard that counts successful business requests may miss work generated by control frames. Several streams can share one HTTP/2 connection, so the connection can accumulate behavior that is difficult to see in per-request summaries. A client making useful requests can still create avoidable protocol overhead between them. Investigate both levels before assuming the protection is misconfigured.

Cloudflare's account distinguishes RST_STREAM, PING and GOAWAY, and identifies PING protection rather than Rapid Reset as the cause in that case. Those distinctions prevent a familiar error label from becoming a diagnosis. A closure tells you where communication stopped. It does not, by itself, identify which client operation generated the offending sequence.

For an actual incident, correlate the request lifecycle with connection-level evidence. Record when the application receives headers, reads the body, closes it and cancels the context. Compare those events with the transport's frame sequence. This is a proposed investigation, not a claim that logs or traffic captures were collected here. The useful output is a causal account of one observed failure.

Keep the comparison narrow enough to understand. A small client that retains the relevant response behavior can help isolate a cause, but it should still use the affected transport and connection reuse pattern. A reproduction that changes HTTP version or stops reusing connections may remove the symptom while also removing the condition under investigation.

Closing and consuming answer different questions

Application authors often regard closing a response as completing their responsibility for it. The case illustrates why transport behavior deserves a closer look. Consumption establishes what the application has read; closing releases the application's use of the body. How those operations affect the stream depends on the transport and state. Do not infer the full wire sequence from a cleanup call's name.

In a proposed check, compare a small bounded response that is read to completion with the same response abandoned after headers. Keep the request and transport conditions comparable. The purpose would be to determine whether the body's lifecycle explains the extra frames. A change in behavior would still require interpretation against the actual implementation, rather than automatic extrapolation to every Go version.

An empty payload can also be a useful boundary case. Absence of business data does not necessarily mean the application has exercised the body-reading path. Include that distinction when choosing a minimal reproduction. A realistic assessment should also retain the nonempty responses the product actually handles, since fixing an empty-response example alone does not establish general correctness.

Cancellation remains part of a healthy client

The strongest counterargument is that clients must be able to abandon work. A caller may have timed out, a user may have left the page, or a response may exceed an allowed size. Continuing indefinitely to consume unwanted data would defeat the application's resource policy. A blanket instruction to drain every untrusted response without bounds is therefore an unsuitable universal fix.

Define limits for time and bytes before selecting a consumption policy. An expected small response from a controlled service presents a different decision from an open-ended stream supplied by an untrusted peer. Reading to completion may be sensible in the first case. In the second, intentional cancellation can be the correct outcome even if it produces control frames.

Preserve evidence of that intention. A useful incident record distinguishes successful complete reads, rejected oversized responses and caller cancellations. Otherwise legitimate protective behavior can be mistaken for a leak or treated as a bug merely because a reset appears. The acceptance condition is proportionate behavior under each case, rather than the disappearance of every cancellation frame.

Keep retry behavior in view as well. Repeating failed calls without understanding their cause can increase the same connection pressure that triggered the closure. Before changing retry rules, identify whether the operation is safe to repeat and whether a retry simply reproduces the response-handling pattern. A transport symptom cannot settle the business operation's retry contract.

Choose evidence that can answer the incident

The Go flight-recorder article of 26 September 2025 describes Go 1.25's bounded recent execution tracing capability. It can provide runtime context around an event. That is a different evidence source from HTTP/2 frame logs or a packet capture. A runtime trace alone does not prove which frames crossed a network connection.

Select the least intrusive evidence capable of resolving the uncertainty, and account for sensitive information in traces or transport logs. Compare evidence timestamps and retention windows before assuming separate records describe the same occurrence. A short trace without the triggering interval may be valid data while remaining insufficient for this particular diagnosis.

The argument has limits: Cloudflare's specific cause does not explain every ENHANCE_YOUR_CALM response, and a service may encounter genuine abuse or another implementation's limits. Protecting a server and correcting a client are compatible responsibilities. Escalate an unexplained closure with evidence about the actual frame sequence before requesting a change to defenses.

For software maintenance, ask for the failing lifecycle, the transport evidence and the proposed bounded response policy. The repair should remove unnecessary work while retaining size limits and deliberate cancellation. Verification belongs to that application's client and server combination; the published investigation supplies a hypothesis to examine.