Skip to content

Client: handle RST_STREAM with NO_ERROR set for the reason #2872

@abonander

Description

@abonander

Version

hyper = "0.14.18"
h2 = "0.3.13"

Platform

> uname -a
Linux <REDACTED> 5.17.5-76051705-generic #202204271406~1651504840~22.04~63e51bd SMP PREEMPT Mon May 2 15: x86_64 x86_64 x86_64 GNU/Linux

Description
I've found that Google Cloud Storage's API can respond with HTTP/2 RST_STREAM frame with NO_ERROR set for the reason, which appears to mean "stop sending the request body and read my response" according to https://datatracker.ietf.org/doc/html/rfc7540#section-8.1

A server can send a complete response prior to the client sending an entire
request if the response does not depend on any portion of the request
that has not been sent and received. When this is true, a server MAY
request that the client abort transmission of a request without error
by sending a RST_STREAM with an error code of NO_ERROR after sending
a complete response (i.e., a frame with the END_STREAM flag).
Clients MUST NOT discard responses as a result of receiving such a
RST_STREAM, though clients can always discard responses at their
discretion for other reasons.

I believe this is happening in response to a PutObject request when the bucket is being rate limited for writes. The server is trying to tell the client to stop sending the request body because it won't be processed, and instead it should immediately read the response to discover the 429 Too Many Requests error code.

However, Hyper's client implementation appears to just return the RST_STREAM message as an error and discards the response instead of handling it, which gives a hilariously confusing error message of:

error reading a body from connection: stream error received: not a result of an error

To be compliant with the spec, the implementation should stop sending the body and immediately read the response and return it.

For context, I'm using the Gcloud Storage API via https://crates.io/crates/aws-sdk-s3 (because the Gcloud Rust SDK doesn't support streaming bodies, but thankfully Gcloud Storage exposes an S3-compatible API), which uses Hyper internally. aws-sdk-s3 appears to be returning the error from Hyper verbatim, however.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-http2Area: HTTP/2 specific.C-bugCategory: bug. Something is wrong. This is bad!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions