-
Notifications
You must be signed in to change notification settings - Fork 596
feat(core/services-azblob): support user defined metadata #5274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
23bb518
f645cc6
4c6476a
398efed
39e4d62
72e6e10
155bb1a
1927932
4282d5d
d28eae6
4d6057b
3228bd2
d76c46d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -33,6 +33,8 @@ use reqsign::AzureStorageSigner; | |||
use sha2::Digest; | ||||
use sha2::Sha256; | ||||
|
||||
use super::core::constants; | ||||
use super::core::constants::X_MS_META_NAME_PREFIX; | ||||
use super::error::parse_error; | ||||
use super::lister::AzblobLister; | ||||
use super::writer::AzblobWriter; | ||||
|
@@ -517,6 +519,7 @@ impl Access for AzblobBackend { | |||
write_can_multi: true, | ||||
write_with_cache_control: true, | ||||
write_with_content_type: true, | ||||
write_with_user_metadata: true, | ||||
|
||||
delete: true, | ||||
copy: true, | ||||
|
@@ -545,7 +548,17 @@ impl Access for AzblobBackend { | |||
let status = resp.status(); | ||||
|
||||
match status { | ||||
StatusCode::OK => parse_into_metadata(path, resp.headers()).map(RpStat::new), | ||||
StatusCode::OK => { | ||||
let headers = resp.headers(); | ||||
let mut meta = parse_into_metadata(path, headers)?; | ||||
|
||||
let user_meta = parse_prefixed_headers(&headers, X_MS_META_NAME_PREFIX); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the metadata parsing be done in two steps (first call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi, I tend to keep As I mentioned before, OpenDAL tends to have more readable code. It's acceptable for us to have some duplicated code here and there. We can revisit this part when we have more similar code, rather than just two or three instances. |
||||
if !user_meta.is_empty() { | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check is also done in the s3 backend. Should we always call Or can we for example, add that checking inside opendal/core/src/types/metadata.rs Line 524 in 1927932
I find that checking in each backend if the hashmap is empty is error-prone boilerplate... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's fine to have such a check. OpenDAL tends to have more readable code because we have many services, and that code is rarely modified. |
||||
meta.with_user_metadata(user_meta); | ||||
} | ||||
|
||||
Ok(RpStat::new(meta)) | ||||
} | ||||
_ => Err(parse_error(resp)), | ||||
} | ||||
} | ||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ use std::time::Duration; | |
use base64::prelude::BASE64_STANDARD; | ||
use base64::Engine; | ||
use bytes::Bytes; | ||
use constants::X_MS_META_NAME_PREFIX; | ||
use http::header::HeaderName; | ||
use http::header::CONTENT_LENGTH; | ||
use http::header::CONTENT_TYPE; | ||
|
@@ -42,13 +43,14 @@ use uuid::Uuid; | |
use crate::raw::*; | ||
use crate::*; | ||
|
||
mod constants { | ||
pub mod constants { | ||
pub const X_MS_VERSION: &str = "x-ms-version"; | ||
|
||
pub const X_MS_BLOB_TYPE: &str = "x-ms-blob-type"; | ||
pub const X_MS_COPY_SOURCE: &str = "x-ms-copy-source"; | ||
pub const X_MS_BLOB_CACHE_CONTROL: &str = "x-ms-blob-cache-control"; | ||
pub const X_MS_BLOB_CONDITION_APPENDPOS: &str = "x-ms-blob-condition-appendpos"; | ||
pub const X_MS_META_NAME_PREFIX: &str = "x-ms-meta-"; | ||
|
||
// Server-side encryption with customer-provided headers | ||
pub const X_MS_ENCRYPTION_KEY: &str = "x-ms-encryption-key"; | ||
|
@@ -243,12 +245,19 @@ impl AzblobCore { | |
|
||
let mut req = Request::put(&url); | ||
|
||
if let Some(user_metadata) = args.user_metadata() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm setting the metadata headers only for the Should this also be done for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see that in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not sure for now; I will need some time to delve into the documentation.
I remember that only the first append request can include user metadata, but I'm not sure about that. Feel free to do more research on this. |
||
for (key, value) in user_metadata { | ||
req = req.header(format!("{X_MS_META_NAME_PREFIX}{key}"), value) | ||
} | ||
} | ||
|
||
// Set SSE headers. | ||
req = self.insert_sse_headers(req); | ||
|
||
if let Some(cache_control) = args.cache_control() { | ||
req = req.header(constants::X_MS_BLOB_CACHE_CONTROL, cache_control); | ||
} | ||
|
||
if let Some(size) = size { | ||
req = req.header(CONTENT_LENGTH, size) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ use std::time::Duration; | |
use base64::prelude::BASE64_STANDARD; | ||
use base64::Engine; | ||
use bytes::Bytes; | ||
use constants::X_AMZ_META_PREFIX; | ||
use http::header::HeaderName; | ||
use http::header::CACHE_CONTROL; | ||
use http::header::CONTENT_DISPOSITION; | ||
|
@@ -462,7 +463,7 @@ impl S3Core { | |
// Set user metadata headers. | ||
if let Some(user_metadata) = args.user_metadata() { | ||
for (key, value) in user_metadata { | ||
req = req.header(format!("{}{}", constants::X_AMZ_META_PREFIX, key), value) | ||
req = req.header(format!("{X_AMZ_META_PREFIX}{key}"), value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed this in order to be consistent with what I did in the azure part. It is more idiomatic to use string interpolation |
||
} | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.