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 6b2307a5c feat(services/oss): Implement `Write Returns Metadata` for
oss (#5688)
6b2307a5c is described below
commit 6b2307a5c27a0258b40f08041f7784ea5bb6c88a
Author: meteorgan <[email protected]>
AuthorDate: Tue Mar 4 22:07:56 2025 +0800
feat(services/oss): Implement `Write Returns Metadata` for oss (#5688)
* feat(services/oss): Implement Write Returns Metadata for oss
* add write_has_content_md5 to Capability
---
core/src/services/oss/backend.rs | 4 +++-
core/src/services/oss/core.rs | 2 ++
core/src/services/oss/writer.rs | 26 ++++++++++++++++++++++----
core/src/types/capability.rs | 2 ++
core/tests/behavior/async_write.rs | 9 +++++++++
core/tests/behavior/blocking_write.rs | 6 ++++++
6 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/core/src/services/oss/backend.rs b/core/src/services/oss/backend.rs
index 106ee1025..a9aa225b2 100644
--- a/core/src/services/oss/backend.rs
+++ b/core/src/services/oss/backend.rs
@@ -460,6 +460,8 @@ impl Builder for OssBuilder {
Some(usize::MAX)
},
write_with_user_metadata: true,
+ write_has_etag: true,
+ write_has_version: self.config.enable_versioning,
delete: true,
delete_with_version: self.config.enable_versioning,
@@ -541,7 +543,7 @@ impl Access for OssBackend {
let headers = resp.headers();
let mut meta = self.core.parse_metadata(path, resp.headers())?;
- if let Some(v) = parse_header_to_str(headers,
"x-oss-version-id")? {
+ if let Some(v) = parse_header_to_str(headers,
constants::X_OSS_VERSION_ID)? {
meta.set_version(v);
}
diff --git a/core/src/services/oss/core.rs b/core/src/services/oss/core.rs
index 185047b25..c88d4806e 100644
--- a/core/src/services/oss/core.rs
+++ b/core/src/services/oss/core.rs
@@ -54,6 +54,8 @@ pub mod constants {
pub const X_OSS_FORBID_OVERWRITE: &str = "x-oss-forbid-overwrite";
+ pub const X_OSS_VERSION_ID: &str = "x-oss-version-id";
+
pub const RESPONSE_CONTENT_DISPOSITION: &str =
"response-content-disposition";
pub const OSS_QUERY_VERSION_ID: &str = "versionId";
diff --git a/core/src/services/oss/writer.rs b/core/src/services/oss/writer.rs
index 847a93c0f..7ddb69ba4 100644
--- a/core/src/services/oss/writer.rs
+++ b/core/src/services/oss/writer.rs
@@ -17,7 +17,7 @@
use std::sync::Arc;
-use http::StatusCode;
+use http::{HeaderMap, HeaderValue, StatusCode};
use super::core::*;
use super::error::parse_error;
@@ -41,6 +41,21 @@ impl OssWriter {
op,
}
}
+
+ fn parse_metadata(headers: &HeaderMap<HeaderValue>) -> Result<Metadata> {
+ let mut meta = Metadata::default();
+ if let Some(etag) = parse_etag(headers)? {
+ meta.set_etag(etag);
+ }
+ if let Some(md5) = parse_content_md5(headers)? {
+ meta.set_content_md5(md5);
+ }
+ if let Some(version) = parse_header_to_str(headers,
constants::X_OSS_VERSION_ID)? {
+ meta.set_version(version);
+ }
+
+ Ok(meta)
+ }
}
impl oio::MultipartWrite for OssWriter {
@@ -53,10 +68,11 @@ impl oio::MultipartWrite for OssWriter {
let resp = self.core.send(req).await?;
+ let meta = Self::parse_metadata(resp.headers())?;
let status = resp.status();
match status {
- StatusCode::CREATED | StatusCode::OK => Ok(Metadata::default()),
+ StatusCode::CREATED | StatusCode::OK => Ok(meta),
_ => Err(parse_error(resp)),
}
}
@@ -145,10 +161,11 @@ impl oio::MultipartWrite for OssWriter {
.oss_complete_multipart_upload_request(&self.path, upload_id,
false, parts)
.await?;
+ let meta = Self::parse_metadata(resp.headers())?;
let status = resp.status();
match status {
- StatusCode::OK => Ok(Metadata::default()),
+ StatusCode::OK => Ok(meta),
_ => Err(parse_error(resp)),
}
}
@@ -198,10 +215,11 @@ impl oio::AppendWrite for OssWriter {
let resp = self.core.send(req).await?;
+ let meta = Self::parse_metadata(resp.headers())?;
let status = resp.status();
match status {
- StatusCode::OK => Ok(Metadata::default()),
+ StatusCode::OK => Ok(meta),
_ => Err(parse_error(resp)),
}
}
diff --git a/core/src/types/capability.rs b/core/src/types/capability.rs
index ca280ce5e..10ef127b9 100644
--- a/core/src/types/capability.rs
+++ b/core/src/types/capability.rs
@@ -166,6 +166,8 @@ pub struct Capability {
pub write_has_etag: bool,
/// Indicates whether version information is available in write response
pub write_has_version: bool,
+ /// Indicates whether content MD5 checksum is available in write response
+ pub write_has_content_md5: bool,
/// Indicates if directory creation is supported.
pub create_dir: bool,
diff --git a/core/tests/behavior/async_write.rs
b/core/tests/behavior/async_write.rs
index 817c5bf72..867dc8833 100644
--- a/core/tests/behavior/async_write.rs
+++ b/core/tests/behavior/async_write.rs
@@ -273,6 +273,9 @@ pub async fn test_write_returns_metadata(op: Operator) ->
Result<()> {
if cap.write_has_version {
assert_eq!(stat_meta.version(), meta.version());
}
+ if cap.write_has_content_md5 {
+ assert_eq!(stat_meta.content_md5(), meta.content_md5());
+ }
Ok(())
}
@@ -599,6 +602,9 @@ pub async fn test_writer_return_metadata(op: Operator) ->
Result<()> {
if cap.write_has_version {
assert_eq!(stat_meta.version(), meta.version());
}
+ if cap.write_has_content_md5 {
+ assert_eq!(stat_meta.content_md5(), meta.content_md5());
+ }
Ok(())
}
@@ -665,6 +671,9 @@ pub async fn test_write_with_append_returns_metadata(op:
Operator) -> Result<()>
if cap.write_has_version {
assert_eq!(stat_meta.version(), meta.version());
}
+ if cap.write_has_content_md5 {
+ assert_eq!(stat_meta.content_md5(), meta.content_md5());
+ }
Ok(())
}
diff --git a/core/tests/behavior/blocking_write.rs
b/core/tests/behavior/blocking_write.rs
index b3fc3d208..6d1bd9372 100644
--- a/core/tests/behavior/blocking_write.rs
+++ b/core/tests/behavior/blocking_write.rs
@@ -109,6 +109,9 @@ pub fn test_blocking_write_returns_metadata(op:
BlockingOperator) -> Result<()>
if cap.write_has_version {
assert_eq!(meta.version(), stat_meta.version());
}
+ if cap.write_has_content_md5 {
+ assert_eq!(meta.content_md5(), stat_meta.content_md5());
+ }
Ok(())
}
@@ -166,6 +169,9 @@ pub fn test_blocking_write_with_append_returns_metadata(op:
BlockingOperator) ->
if cap.write_has_version {
assert_eq!(meta.version(), stat_meta.version());
}
+ if cap.write_has_content_md5 {
+ assert_eq!(meta.content_md5(), stat_meta.content_md5());
+ }
Ok(())
}