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 deee67156 feat(services/azblob): implement write returns metadata (#5958) deee67156 is described below commit deee6715606d1c970b37b966ed4a87e549a1edb3 Author: meteorgan <meteorite....@gmail.com> AuthorDate: Sun Apr 6 22:43:06 2025 +0800 feat(services/azblob): implement write returns metadata (#5958) * feat(services/azblob): implement write returns metadata * skip content-md5 from and response * fix the import and comments --- core/src/services/azblob/backend.rs | 4 ++++ core/src/services/azblob/core.rs | 4 ++++ core/src/services/azblob/writer.rs | 34 +++++++++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/core/src/services/azblob/backend.rs b/core/src/services/azblob/backend.rs index eafe32ddb..331d9b954 100644 --- a/core/src/services/azblob/backend.rs +++ b/core/src/services/azblob/backend.rs @@ -32,6 +32,7 @@ use sha2::Digest; use sha2::Sha256; use super::core::constants::X_MS_META_PREFIX; +use super::core::constants::X_MS_VERSION_ID; use super::core::AzblobCore; use super::delete::AzblobDeleter; use super::error::parse_error; @@ -567,6 +568,9 @@ impl Access for AzblobBackend { StatusCode::OK => { let headers = resp.headers(); let mut meta = parse_into_metadata(path, headers)?; + if let Some(version_id) = parse_header_to_str(headers, X_MS_VERSION_ID)? { + meta.set_version(version_id); + } let user_meta = parse_prefixed_headers(headers, X_MS_META_PREFIX); if !user_meta.is_empty() { diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 87fd4da11..7f664e64b 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -47,6 +47,7 @@ use crate::raw::*; use crate::*; pub mod constants { + // Indicates the Blob Storage version that was used to execute the request pub const X_MS_VERSION: &str = "x-ms-version"; pub const X_MS_BLOB_TYPE: &str = "x-ms-blob-type"; @@ -55,6 +56,9 @@ pub mod constants { pub const X_MS_BLOB_CONDITION_APPENDPOS: &str = "x-ms-blob-condition-appendpos"; pub const X_MS_META_PREFIX: &str = "x-ms-meta-"; + // indicates the version of the blob, and it can be used in subsequent requests to access the blob. + pub const X_MS_VERSION_ID: &str = "x-ms-version-id"; + // Server-side encryption with customer-provided headers pub const X_MS_ENCRYPTION_KEY: &str = "x-ms-encryption-key"; pub const X_MS_ENCRYPTION_KEY_SHA256: &str = "x-ms-encryption-key-sha256"; diff --git a/core/src/services/azblob/writer.rs b/core/src/services/azblob/writer.rs index 17cf8b676..d67b43e5a 100644 --- a/core/src/services/azblob/writer.rs +++ b/core/src/services/azblob/writer.rs @@ -20,6 +20,7 @@ use std::sync::Arc; use http::StatusCode; use uuid::Uuid; +use super::core::constants::X_MS_VERSION_ID; use super::core::AzblobCore; use super::error::parse_error; use crate::raw::*; @@ -40,6 +41,26 @@ impl AzblobWriter { pub fn new(core: Arc<AzblobCore>, op: OpWrite, path: String) -> Self { AzblobWriter { core, op, path } } + + // skip extracting `content-md5` here, as it pertains to the content of the request rather than + // the content of the block itself for the `append` and `complete put block list` operations. + fn parse_metadata(headers: &http::HeaderMap) -> Result<Metadata> { + let mut metadata = Metadata::default(); + + if let Some(last_modified) = parse_last_modified(headers)? { + metadata.set_last_modified(last_modified); + } + let etag = parse_etag(headers)?; + if let Some(etag) = etag { + metadata.set_etag(etag); + } + let version_id = parse_header_to_str(headers, X_MS_VERSION_ID)?; + if let Some(version_id) = version_id { + metadata.set_version(version_id); + } + + Ok(metadata) + } } impl oio::AppendWrite for AzblobWriter { @@ -97,9 +118,10 @@ impl oio::AppendWrite for AzblobWriter { let resp = self.core.send(req).await?; + let meta = AzblobWriter::parse_metadata(resp.headers())?; let status = resp.status(); match status { - StatusCode::CREATED => Ok(Metadata::default()), + StatusCode::CREATED => Ok(meta), _ => Err(parse_error(resp)), } } @@ -116,8 +138,13 @@ impl oio::BlockWrite for AzblobWriter { let status = resp.status(); + let mut meta = AzblobWriter::parse_metadata(resp.headers())?; + let md5 = parse_content_md5(resp.headers())?; + if let Some(md5) = md5 { + meta.set_content_md5(md5); + } match status { - StatusCode::CREATED | StatusCode::OK => Ok(Metadata::default()), + StatusCode::CREATED | StatusCode::OK => Ok(meta), _ => Err(parse_error(resp)), } } @@ -141,9 +168,10 @@ impl oio::BlockWrite for AzblobWriter { .azblob_complete_put_block_list(&self.path, block_ids, &self.op) .await?; + let meta = AzblobWriter::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)), } }