From afa3b8fa09324360efafcff6953e35818ec446ac Mon Sep 17 00:00:00 2001 From: lcian <17258265+lcian@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:40:42 +0200 Subject: [PATCH] ref(rust-client): Use typed resumable queries --- Cargo.lock | 1 + clients/rust/Cargo.toml | 2 +- clients/rust/src/client.rs | 14 -------------- clients/rust/src/resumable.rs | 35 +++++++++++++++++++++++++++-------- 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7b5ec614..ebd6b806 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3966,6 +3966,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", "tokio-native-tls", diff --git a/clients/rust/Cargo.toml b/clients/rust/Cargo.toml index b848a6d1..da2c3125 100644 --- a/clients/rust/Cargo.toml +++ b/clients/rust/Cargo.toml @@ -20,7 +20,7 @@ jsonwebtoken = { workspace = true } multer = { workspace = true } objectstore-types = { workspace = true } # Pinned below workspace version for MSRV compatibility -reqwest = { version = "0.13.1", default-features = false, features = ["charset", "http2", "system-proxy", "json", "stream", "multipart"] } +reqwest = { version = "0.13.1", default-features = false, features = ["charset", "http2", "system-proxy", "json", "stream", "multipart", "query"] } sentry-core = { version = ">=0.41", default-features = false, features = ["client"] } serde = { workspace = true } thiserror = { workspace = true } diff --git a/clients/rust/src/client.rs b/clients/rust/src/client.rs index d24389ee..6d9a1c0a 100644 --- a/clients/rust/src/client.rs +++ b/clients/rust/src/client.rs @@ -583,20 +583,6 @@ impl Session { self.prepare_builder(builder) } - #[cfg(feature = "resumable-upload-api")] - pub(crate) fn resumable_request( - &self, - method: reqwest::Method, - object_key: &str, - query_pair: (&str, &str), - ) -> crate::Result { - let mut url = self.object_url(object_key); - url.query_pairs_mut() - .append_pair(query_pair.0, query_pair.1); - let builder = self.client.reqwest.request(method, url); - self.prepare_builder(builder) - } - pub(crate) fn batch_request(&self) -> crate::Result { let url = self.batch_url(); let builder = self.client.reqwest.post(url); diff --git a/clients/rust/src/resumable.rs b/clients/rust/src/resumable.rs index 37edd2df..a0f2c8ac 100644 --- a/clients/rust/src/resumable.rs +++ b/clients/rust/src/resumable.rs @@ -18,11 +18,28 @@ use objectstore_types::resumable::{ UploadOffset, }; use reqwest::{Method, Response, StatusCode}; +use serde::Serialize; pub use objectstore_types::resumable::{SessionToken, UploadProgress}; use crate::{Compression, Error, ExpirationPolicy, ObjectKey, Session}; +#[derive(Serialize)] +#[serde(rename_all = "snake_case")] +enum UploadType { + Resumable, +} + +#[derive(Serialize)] +struct UploadTypeQuery { + upload_type: UploadType, +} + +#[derive(Serialize)] +struct SessionQuery<'a> { + session: &'a SessionToken, +} + /// A handle bound to one resumable upload session. /// /// See the [crate-level documentation](crate#resumable-upload-api) for more information and @@ -113,9 +130,12 @@ impl ResumableUpload { } fn request(&self, method: Method) -> crate::Result { - let token = self.token.to_base64url(); - self.session - .resumable_request(method, &self.key, ("session", &token)) + Ok(self + .session + .request(method, &self.key)? + .query(&SessionQuery { + session: &self.token, + })) } } @@ -195,11 +215,10 @@ impl CreateResumableUploadBuilder { }; let request = self .session - .resumable_request( - method, - self.key.as_deref().unwrap_or_default(), - ("upload_type", "resumable"), - )? + .request(method, self.key.as_deref().unwrap_or_default())? + .query(&UploadTypeQuery { + upload_type: UploadType::Resumable, + }) .headers(self.metadata.to_headers("")?) .header(HEADER_UPLOAD_LENGTH, self.total_length.to_string()); let response = request.send().await?;