This is an automated email from the ASF dual-hosted git repository.
Xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 23216a129 fix(services/s3): encode version id for stat and read (#7886)
23216a129 is described below
commit 23216a129123204ff71d70b50daa214f14941854
Author: QuakeWang <[email protected]>
AuthorDate: Wed Jul 8 17:44:53 2026 +0800
fix(services/s3): encode version id for stat and read (#7886)
Signed-off-by: QuakeWang <[email protected]>
---
core/services/s3/src/backend.rs | 55 +++++++++++++++++++++++++++++++++++++++++
core/services/s3/src/core.rs | 4 +--
2 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/core/services/s3/src/backend.rs b/core/services/s3/src/backend.rs
index f6002d5a2..bceac617d 100644
--- a/core/services/s3/src/backend.rs
+++ b/core/services/s3/src/backend.rs
@@ -1359,4 +1359,59 @@ mod tests {
"application/json"
);
}
+
+ #[tokio::test]
+ async fn test_presign_stat_encodes_version_id() {
+ let backend = S3Builder::default()
+ .bucket("test")
+ .region("us-east-1")
+ .skip_signature()
+ .disable_config_load()
+ .disable_ec2_metadata()
+ .build()
+ .expect("build");
+
+ let op = OpStat::default().with_version("a+b/c=d%25&e");
+ let args = OpPresign::new(op, Duration::from_secs(3600));
+ let ctx = OperationContext::new();
+ let presigned = backend
+ .presign(&ctx, "test.txt", args)
+ .await
+ .expect("presign")
+ .into_presigned_request();
+
+ assert_eq!(
+ presigned.uri().to_string(),
+
"https://s3.us-east-1.amazonaws.com/test/test.txt?versionId=a%2Bb/c%3Dd%2525%26e"
+ );
+ }
+
+ #[tokio::test]
+ async fn test_presign_read_encodes_version_id() {
+ let backend = S3Builder::default()
+ .bucket("test")
+ .region("us-east-1")
+ .skip_signature()
+ .disable_config_load()
+ .disable_ec2_metadata()
+ .build()
+ .expect("build");
+
+ let op = OpRead::default().with_version("a+b/c=d%25&e");
+ let args = OpPresign::new(
+ PresignOperation::Read(BytesRange::default(), op),
+ Duration::from_secs(3600),
+ );
+ let ctx = OperationContext::new();
+ let presigned = backend
+ .presign(&ctx, "test.txt", args)
+ .await
+ .expect("presign")
+ .into_presigned_request();
+
+ assert_eq!(
+ presigned.uri().to_string(),
+
"https://s3.us-east-1.amazonaws.com/test/test.txt?versionId=a%2Bb/c%3Dd%2525%26e"
+ );
+ }
}
diff --git a/core/services/s3/src/core.rs b/core/services/s3/src/core.rs
index a66d204ee..12f9cc7fb 100644
--- a/core/services/s3/src/core.rs
+++ b/core/services/s3/src/core.rs
@@ -420,7 +420,7 @@ impl S3Core {
query_args.push(format!(
"{}={}",
constants::S3_QUERY_VERSION_ID,
- percent_decode_path(version)
+ percent_encode_path(version)
))
}
if !query_args.is_empty() {
@@ -496,7 +496,7 @@ impl S3Core {
query_args.push(format!(
"{}={}",
constants::S3_QUERY_VERSION_ID,
- percent_decode_path(version)
+ percent_encode_path(version)
))
}
if !query_args.is_empty() {