durch / rust-s3

Rust library for interfacing with S3 API compatible services
MIT License
498 stars 195 forks source link

"PROTOCOL_ERROR" when using GCS as S3 backend, tokio-rustls-tls #377

Open bcspragu opened 5 months ago

bcspragu commented 5 months ago

Describe the bug

When using rust-s3 with the tokio-rustls-tls backend, I reliably get this error when connecting to GCS:

Reqwest(reqwest::Error { kind: Request, url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("storage.googleapis.com")), port: None, path: "/<bucket>/rust-test", query: None, fragment: None }, source: hyper::Error(Http2, Error { kind: Reset(StreamId(1), PROTOCOL_ERROR, Remote) }) })

To Reproduce

Have a Cargo.toml file with:

rust-s3 = { version = "0.33.0", default-features = false, features = ["tokio-rustls-tls"] }

Example snippet:

Rust example code
#[tokio::main]
async fn main() {
    let bucket_name = "<bucket>";
    let google_access_key_id = "<access key>";
    let google_access_key_secret = "<secret key>";

    let bucket = s3::bucket::Bucket::new(
        bucket_name,
        s3::region::Region::Custom {
            region: "auto".to_owned(),
            endpoint: "https://storage.googleapis.com".to_owned(),
        },
        s3::creds::Credentials::new(
            Some(google_access_key_id),
            Some(google_access_key_secret),
            None,
            None,
            None,
        )
        .unwrap(),
    )
    .unwrap()
    .with_path_style();

    bucket
        .put_object("rust-test", "some data".as_bytes())
        .await
        .unwrap();
}

Expected behavior

I expect a file to be created on GCS at /rust-test containing "some data", which happens correctly with rust-s3's default features, but not with tokio-rustls-tls.

Environment

Additional context

I initially noticed this downstream in Stalwart, and was able to temporarily hack around this by recompiling with tokio-native-tls instead.

Googling around, it seems like Google servers do something with http2 that causes problems for rustls, but I didn't see anything conclusive. The issue is probably upstream of rust-s3, but figured I'd work my way up the chain of deps to better understand it.