From dd250c34ece35f328d51197b563e17818682fc32 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Tue, 13 Feb 2024 11:57:29 +0800 Subject: [PATCH 01/25] save work --- core/src/services/azblob/backend.rs | 5 +- core/src/services/azblob/core.rs | 141 ++++++++++++++++++++++++++-- core/src/services/azblob/writer.rs | 79 +++++++++++++++- 3 files changed, 215 insertions(+), 10 deletions(-) diff --git a/core/src/services/azblob/backend.rs b/core/src/services/azblob/backend.rs index 1a24335da84..65a25bcf195 100644 --- a/core/src/services/azblob/backend.rs +++ b/core/src/services/azblob/backend.rs @@ -567,8 +567,9 @@ impl Accessor for AzblobBackend { read_with_override_content_disposition: true, write: true, - write_can_empty: true, write_can_append: true, + write_can_empty: true, + write_can_multi: true, write_with_cache_control: true, write_with_content_type: true, @@ -631,7 +632,7 @@ impl Accessor for AzblobBackend { let w = if args.append() { AzblobWriters::Two(oio::AppendWriter::new(w)) } else { - AzblobWriters::One(oio::OneShotWriter::new(w)) + AzblobWriters::One(oio::BlockWriter::new(w, args.concurrent())) }; Ok((RpWrite::default(), w)) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 64420683dc3..3931fb8f4bf 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -15,13 +15,7 @@ // specific language governing permissions and limitations // under the License. -use std::fmt; -use std::fmt::Debug; -use std::fmt::Formatter; -use std::fmt::Write; -use std::time::Duration; - -use http::header::HeaderName; +use bytes::Bytes; use http::header::CONTENT_LENGTH; use http::header::CONTENT_TYPE; use http::header::IF_MATCH; @@ -29,14 +23,24 @@ use http::header::IF_NONE_MATCH; use http::HeaderValue; use http::Request; use http::Response; +use http::{header::HeaderName, StatusCode}; use reqsign::AzureStorageCredential; use reqsign::AzureStorageLoader; use reqsign::AzureStorageSigner; use serde::Deserialize; +use serde::Serialize; +use std::fmt; +use std::fmt::Debug; +use std::fmt::Formatter; +use std::fmt::Write; +use std::time::Duration; +use uuid::Uuid; use crate::raw::*; use crate::*; +use super::error::parse_error; + mod constants { pub const X_MS_VERSION: &str = "x-ms-version"; @@ -370,6 +374,113 @@ impl AzblobCore { Ok(req) } + pub fn azblob_put_block_list_request( + &self, + path: &str, + size: Option, + args: &OpWrite, + body: AsyncBody, + ) -> Result> { + let p = build_abs_path(&self.root, path); + + let url = format!( + "{}/{}/{}?comp=blocklist", + self.endpoint, + self.container, + percent_encode_path(&p) + ); + let mut req = Request::put(&url); + + if let Some(size) = size { + req = req.header(CONTENT_LENGTH, size) + } + if let Some(content_type) = args.content_type() { + req = req.header(CONTENT_TYPE, content_type); + }; + + // Set SSE headers. + req = self.insert_sse_headers(req); + + // Set body + let req = req.body(body).map_err(new_request_build_error)?; + + Ok(req) + } + + pub async fn azblob_put_block_list( + &self, + path: &str, + size: Option, + args: &OpWrite, + body: AsyncBody, + ) -> Result> { + let mut req = self.azblob_put_block_list_request(path, size, args, body)?; + + self.sign(&mut req).await?; + self.send(req).await + } + + pub async fn azblob_complete_put_block_list_request( + &self, + path: &str, + block_ids: Vec, + ) -> Result> { + let p = build_abs_path(&self.root, path); + let first_block_id = format!("{}{}", p, block_ids[0].clone()); + + let sources: Vec = block_ids[1..] + .iter() + .map(|s| format!("{}{}", p, s)) + .collect(); + // concat blocks + let req = self.concat_block_list_request(&first_block_id, sources)?; + Ok(req) + // self.sign(&mut req).await?; + + // let resp = self.send(req).await?; + // let status = resp.status(); + } + + /// CONCAT will concat sources to the path + pub fn concat_block_list_request( + &self, + path: &str, + sources: Vec, + ) -> Result> { + let p = build_abs_path(&self.root, path); + + let sources = sources + .iter() + .map(|p| build_rooted_abs_path(&self.root, p)) + .collect::>() + .join(","); + + let url = format!( + "{}/{}/{}?comp=blocklist", + self.endpoint, + self.container, + percent_encode_path(&p) + ); + + let req = Request::post(url); + + req.body(AsyncBody::Empty).map_err(new_request_build_error) + } + + pub async fn azblob_complete_put_block_list( + &self, + path: &str, + block_ids: Vec, + ) -> Result> { + let mut req = self + .azblob_complete_put_block_list_request(path, block_ids) + .await?; + + self.sign(&mut req).await?; + + self.send(req).await + } + pub fn azblob_head_blob_request( &self, path: &str, @@ -548,6 +659,22 @@ pub struct Blobs { pub blob_prefix: Vec, } +#[derive(Clone, Default, Debug, Serialize)] +#[serde(default, rename_all = "PascalCase")] +pub struct CompleteMultipartUploadRequestPart { + #[serde(rename = "PartNumber")] + pub part_number: usize, + #[serde(rename = "ETag")] + pub etag: String, +} + +/// Request of CompleteMultipartUploadRequest +#[derive(Default, Debug, Serialize)] +#[serde(default, rename = "CompleteMultipartUpload", rename_all = "PascalCase")] +pub struct CompleteMultipartUploadRequest { + pub part: Vec, +} + #[derive(Default, Debug, Deserialize)] #[serde(default, rename_all = "PascalCase")] pub struct BlobPrefix { diff --git a/core/src/services/azblob/writer.rs b/core/src/services/azblob/writer.rs index 6e8b415dd98..450c4b822f5 100644 --- a/core/src/services/azblob/writer.rs +++ b/core/src/services/azblob/writer.rs @@ -19,6 +19,7 @@ use std::sync::Arc; use async_trait::async_trait; use http::StatusCode; +use uuid::Uuid; use super::core::AzblobCore; use super::error::parse_error; @@ -27,7 +28,7 @@ use crate::*; const X_MS_BLOB_TYPE: &str = "x-ms-blob-type"; -pub type AzblobWriters = TwoWays, oio::AppendWriter>; +pub type AzblobWriters = TwoWays, oio::AppendWriter>; pub struct AzblobWriter { core: Arc, @@ -137,3 +138,79 @@ impl oio::AppendWrite for AzblobWriter { } } } + +#[async_trait] +impl oio::BlockWrite for AzblobWriter { + async fn write_once(&self, size: u64, body: AsyncBody) -> Result<()> { + let mut req: http::Request = + self.core + .azblob_put_blob_request(&self.path, Some(size), &self.op, body)?; + self.core.sign(&mut req).await?; + + let resp = self.core.send(req).await?; + + let status = resp.status(); + + match status { + StatusCode::CREATED | StatusCode::OK => { + resp.into_body().consume().await?; + Ok(()) + } + _ => Err(parse_error(resp).await?), + } + } + + async fn write_block(&self, _block_id: Uuid, size: u64, body: AsyncBody) -> Result<()> { + let resp = self + .core + .azblob_put_block_list(&self.path, Some(size), &self.op, body) + .await?; + + let status = resp.status(); + match status { + StatusCode::CREATED | StatusCode::OK => { + resp.into_body().consume().await?; + Ok(()) + } + _ => Err(parse_error(resp).await?), + } + } + + async fn complete_block(&self, block_ids: Vec) -> Result<()> { + if block_ids.len() < 2 { + return Err(Error::new( + ErrorKind::ConditionNotMatch, + "block list length is less than 2", + )); + } + let resp = self + .core + .azblob_complete_put_block_list(&self.path, block_ids) + .await?; + + let status = resp.status(); + + let status = resp.status(); + match status { + StatusCode::OK => { + resp.into_body().consume().await?; + Ok(()) + } + _ => Err(parse_error(resp).await?), + } + } + + async fn abort_block(&self, block_ids: Vec) -> Result<()> { + // Azure blob storage will gc uncommitted blocks after 7 days. + for block_id in block_ids { + let resp = self.core.azblob_delete_blob(&block_id.to_string()).await?; + match resp.status() { + StatusCode::OK => { + resp.into_body().consume().await?; + } + _ => return Err(parse_error(resp).await?), + } + } + Ok(()) + } +} From 98c05973af62afb6f4190ed129bfe96c4adac422 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Wed, 14 Feb 2024 11:26:54 +0800 Subject: [PATCH 02/25] save work --- core/src/services/azblob/core.rs | 49 +++++++++++------------------- core/src/services/azblob/writer.rs | 10 +----- 2 files changed, 19 insertions(+), 40 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 3931fb8f4bf..37ba515457c 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -426,35 +426,6 @@ impl AzblobCore { block_ids: Vec, ) -> Result> { let p = build_abs_path(&self.root, path); - let first_block_id = format!("{}{}", p, block_ids[0].clone()); - - let sources: Vec = block_ids[1..] - .iter() - .map(|s| format!("{}{}", p, s)) - .collect(); - // concat blocks - let req = self.concat_block_list_request(&first_block_id, sources)?; - Ok(req) - // self.sign(&mut req).await?; - - // let resp = self.send(req).await?; - // let status = resp.status(); - } - - /// CONCAT will concat sources to the path - pub fn concat_block_list_request( - &self, - path: &str, - sources: Vec, - ) -> Result> { - let p = build_abs_path(&self.root, path); - - let sources = sources - .iter() - .map(|p| build_rooted_abs_path(&self.root, p)) - .collect::>() - .join(","); - let url = format!( "{}/{}/{}?comp=blocklist", self.endpoint, @@ -462,9 +433,25 @@ impl AzblobCore { percent_encode_path(&p) ); - let req = Request::post(url); + let req = Request::post(&url); + + // Set SSE headers. + let req = self.insert_sse_headers(req); + + // Set body + let mut req_body = "".to_string(); + req_body.push_str("\n"); - req.body(AsyncBody::Empty).map_err(new_request_build_error) + for block_id in block_ids { + req_body.push_str(""); + req_body.push_str(&block_id.to_string()); + req_body.push_str("\n"); + } + + req_body.push_str(""); + let body = AsyncBody::Bytes(Bytes::from(req_body.to_string())); + let req = req.body(body).map_err(new_request_build_error)?; + Ok(req) } pub async fn azblob_complete_put_block_list( diff --git a/core/src/services/azblob/writer.rs b/core/src/services/azblob/writer.rs index 450c4b822f5..fca2cf458bf 100644 --- a/core/src/services/azblob/writer.rs +++ b/core/src/services/azblob/writer.rs @@ -177,22 +177,14 @@ impl oio::BlockWrite for AzblobWriter { } async fn complete_block(&self, block_ids: Vec) -> Result<()> { - if block_ids.len() < 2 { - return Err(Error::new( - ErrorKind::ConditionNotMatch, - "block list length is less than 2", - )); - } let resp = self .core .azblob_complete_put_block_list(&self.path, block_ids) .await?; - let status = resp.status(); - let status = resp.status(); match status { - StatusCode::OK => { + StatusCode::CREATED | StatusCode::OK => { resp.into_body().consume().await?; Ok(()) } From 5ac17975b0797e653d21dc8203ed2a7593e41dcb Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Wed, 14 Feb 2024 17:22:42 +0800 Subject: [PATCH 03/25] finish framework --- core/src/services/azblob/core.rs | 21 ++++++++++----------- core/src/services/azblob/writer.rs | 28 ---------------------------- 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 37ba515457c..ffd76a4a846 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -16,6 +16,7 @@ // under the License. use bytes::Bytes; +use http::header::HeaderName; use http::header::CONTENT_LENGTH; use http::header::CONTENT_TYPE; use http::header::IF_MATCH; @@ -23,7 +24,6 @@ use http::header::IF_NONE_MATCH; use http::HeaderValue; use http::Request; use http::Response; -use http::{header::HeaderName, StatusCode}; use reqsign::AzureStorageCredential; use reqsign::AzureStorageLoader; use reqsign::AzureStorageSigner; @@ -39,8 +39,6 @@ use uuid::Uuid; use crate::raw::*; use crate::*; -use super::error::parse_error; - mod constants { pub const X_MS_VERSION: &str = "x-ms-version"; @@ -381,6 +379,7 @@ impl AzblobCore { args: &OpWrite, body: AsyncBody, ) -> Result> { + // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list? let p = build_abs_path(&self.root, path); let url = format!( @@ -439,16 +438,16 @@ impl AzblobCore { let req = self.insert_sse_headers(req); // Set body - let mut req_body = "".to_string(); - req_body.push_str("\n"); + let req_body = { + let block_list = block_ids + .iter() + .map(|block_id| format!(" {}", block_id)) + .collect::>() + .join("\n"); - for block_id in block_ids { - req_body.push_str(""); - req_body.push_str(&block_id.to_string()); - req_body.push_str("\n"); - } + format!("\n{}\n", block_list) + }; - req_body.push_str(""); let body = AsyncBody::Bytes(Bytes::from(req_body.to_string())); let req = req.body(body).map_err(new_request_build_error)?; Ok(req) diff --git a/core/src/services/azblob/writer.rs b/core/src/services/azblob/writer.rs index fca2cf458bf..fceba0f1e5d 100644 --- a/core/src/services/azblob/writer.rs +++ b/core/src/services/azblob/writer.rs @@ -43,34 +43,6 @@ impl AzblobWriter { } } -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -impl oio::OneShotWrite for AzblobWriter { - async fn write_once(&self, bs: &dyn oio::WriteBuf) -> Result<()> { - let bs = oio::ChunkedBytes::from_vec(bs.vectored_bytes(bs.remaining())); - let mut req = self.core.azblob_put_blob_request( - &self.path, - Some(bs.len() as u64), - &self.op, - AsyncBody::ChunkedBytes(bs), - )?; - - self.core.sign(&mut req).await?; - - let resp = self.core.send(req).await?; - - let status = resp.status(); - - match status { - StatusCode::CREATED | StatusCode::OK => { - resp.into_body().consume().await?; - Ok(()) - } - _ => Err(parse_error(resp).await?), - } - } -} - #[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] impl oio::AppendWrite for AzblobWriter { From f2bb785120c6e5d1d91082e0cd48483f455736ff Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Wed, 14 Feb 2024 17:30:30 +0800 Subject: [PATCH 04/25] add some comments --- core/src/services/azblob/core.rs | 1 + core/src/services/azblob/writer.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index ffd76a4a846..a62c12bc700 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -438,6 +438,7 @@ impl AzblobCore { let req = self.insert_sse_headers(req); // Set body + // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list? let req_body = { let block_list = block_ids .iter() diff --git a/core/src/services/azblob/writer.rs b/core/src/services/azblob/writer.rs index fceba0f1e5d..137bfe665dd 100644 --- a/core/src/services/azblob/writer.rs +++ b/core/src/services/azblob/writer.rs @@ -111,6 +111,8 @@ impl oio::AppendWrite for AzblobWriter { } } +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[async_trait] impl oio::BlockWrite for AzblobWriter { async fn write_once(&self, size: u64, body: AsyncBody) -> Result<()> { From c433f973c935659b12dd495bbfe0a653715de819 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Wed, 14 Feb 2024 17:33:01 +0800 Subject: [PATCH 05/25] minor --- core/src/services/azblob/core.rs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index a62c12bc700..69f43d93b18 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -28,7 +28,6 @@ use reqsign::AzureStorageCredential; use reqsign::AzureStorageLoader; use reqsign::AzureStorageSigner; use serde::Deserialize; -use serde::Serialize; use std::fmt; use std::fmt::Debug; use std::fmt::Formatter; @@ -646,22 +645,6 @@ pub struct Blobs { pub blob_prefix: Vec, } -#[derive(Clone, Default, Debug, Serialize)] -#[serde(default, rename_all = "PascalCase")] -pub struct CompleteMultipartUploadRequestPart { - #[serde(rename = "PartNumber")] - pub part_number: usize, - #[serde(rename = "ETag")] - pub etag: String, -} - -/// Request of CompleteMultipartUploadRequest -#[derive(Default, Debug, Serialize)] -#[serde(default, rename = "CompleteMultipartUpload", rename_all = "PascalCase")] -pub struct CompleteMultipartUploadRequest { - pub part: Vec, -} - #[derive(Default, Debug, Deserialize)] #[serde(default, rename_all = "PascalCase")] pub struct BlobPrefix { From 62fb68950f8a70adbb0ab07c28cba7745f3fd77c Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Thu, 15 Feb 2024 11:14:26 +0800 Subject: [PATCH 06/25] minor --- core/src/services/azblob/writer.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/core/src/services/azblob/writer.rs b/core/src/services/azblob/writer.rs index 137bfe665dd..7c560c156b0 100644 --- a/core/src/services/azblob/writer.rs +++ b/core/src/services/azblob/writer.rs @@ -166,17 +166,10 @@ impl oio::BlockWrite for AzblobWriter { } } - async fn abort_block(&self, block_ids: Vec) -> Result<()> { - // Azure blob storage will gc uncommitted blocks after 7 days. - for block_id in block_ids { - let resp = self.core.azblob_delete_blob(&block_id.to_string()).await?; - match resp.status() { - StatusCode::OK => { - resp.into_body().consume().await?; - } - _ => return Err(parse_error(resp).await?), - } - } + async fn abort_block(&self, _block_ids: Vec) -> Result<()> { + // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list?tabs=microsoft-entra-id + // Any uncommitted blocks are garbage collected if there are no successful calls to Put Block or Put Block List on the blob within a week. + // If Put Blob is called on the blob, any uncommitted blocks are garbage collected. Ok(()) } } From b3970cc77d647594df5c9ace0fba67507239e3d8 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Thu, 15 Feb 2024 16:37:52 +0800 Subject: [PATCH 07/25] remove redudant clone --- core/src/services/azblob/core.rs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 69f43d93b18..235f9955049 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -388,16 +388,24 @@ impl AzblobCore { percent_encode_path(&p) ); let mut req = Request::put(&url); + // 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) } - if let Some(content_type) = args.content_type() { - req = req.header(CONTENT_TYPE, content_type); - }; - // Set SSE headers. - req = self.insert_sse_headers(req); + if let Some(ty) = args.content_type() { + req = req.header(CONTENT_TYPE, ty) + } + + req = req.header( + HeaderName::from_static(constants::X_MS_BLOB_TYPE), + "BlockBlob", + ); // Set body let req = req.body(body).map_err(new_request_build_error)?; @@ -434,7 +442,12 @@ impl AzblobCore { let req = Request::post(&url); // Set SSE headers. - let req = self.insert_sse_headers(req); + let mut req = self.insert_sse_headers(req); + + req = req.header( + HeaderName::from_static(constants::X_MS_BLOB_TYPE), + "BlockBlob", + ); // Set body // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list? @@ -448,7 +461,7 @@ impl AzblobCore { format!("\n{}\n", block_list) }; - let body = AsyncBody::Bytes(Bytes::from(req_body.to_string())); + let body = AsyncBody::Bytes(Bytes::from(req_body)); let req = req.body(body).map_err(new_request_build_error)?; Ok(req) } From 74cd20812da2afa34b7d6fe46807ae21b53dfd59 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Thu, 15 Feb 2024 20:44:00 +0800 Subject: [PATCH 08/25] add base64 encode --- core/src/services/azblob/core.rs | 58 ++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 235f9955049..00bbc63e3ae 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -15,8 +15,11 @@ // specific language governing permissions and limitations // under the License. +use base64::prelude::BASE64_STANDARD; +use base64::Engine; use bytes::Bytes; use http::header::HeaderName; + use http::header::CONTENT_LENGTH; use http::header::CONTENT_TYPE; use http::header::IF_MATCH; @@ -27,7 +30,7 @@ use http::Response; use reqsign::AzureStorageCredential; use reqsign::AzureStorageLoader; use reqsign::AzureStorageSigner; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use std::fmt; use std::fmt::Debug; use std::fmt::Formatter; @@ -449,20 +452,17 @@ impl AzblobCore { "BlockBlob", ); - // Set body - // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list? - let req_body = { - let block_list = block_ids - .iter() - .map(|block_id| format!(" {}", block_id)) - .collect::>() - .join("\n"); - - format!("\n{}\n", block_list) - }; + let content = quick_xml::se::to_string(&PutBlockListRequest { + uncommitted: block_ids + .into_iter() + .map(|block_id| BASE64_STANDARD.encode(block_id)) + .collect(), + }) + .map_err(new_xml_deserialize_error)?; + let req = req + .body(AsyncBody::Bytes(Bytes::from(content))) + .map_err(new_request_build_error)?; - let body = AsyncBody::Bytes(Bytes::from(req_body)); - let req = req.body(body).map_err(new_request_build_error)?; Ok(req) } @@ -643,6 +643,13 @@ impl AzblobCore { } } +/// Request of CompleteMultipartUploadRequest +#[derive(Default, Debug, Serialize)] +#[serde(default, rename = "", rename_all = "PascalCase")] +pub struct PutBlockListRequest { + pub uncommitted: Vec, +} + #[derive(Default, Debug, Deserialize)] #[serde(default, rename_all = "PascalCase")] pub struct ListBlobsOutput { @@ -871,4 +878,27 @@ mod tests { de::from_reader(Bytes::from(bs).reader()).expect("must success") } + + /// This example is from https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list?tabs=microsoft-entra-id + #[test] + fn test_serialize_put_block_list_request() { + let req = PutBlockListRequest { + uncommitted: vec!["1".to_string(), "2".to_string(), "3".to_string()], + }; + + let actual = quick_xml::se::to_string(&req).expect("must succeed"); + + pretty_assertions::assert_eq!( + actual, + r#" + 1 + 2 + 3 + "# + // Cleanup space and new line + .replace([' ', '\n'], "") + // Escape `"` by hand to address + .replace('"', """) + ) + } } From 033f9381722347907044c23fe8cb71918398d7a9 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Fri, 16 Feb 2024 20:40:33 +0800 Subject: [PATCH 09/25] minor fix --- core/Cargo.toml | 4 +--- core/src/services/azblob/core.rs | 7 ++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index 69d1010d16b..4a2056b298a 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -296,9 +296,7 @@ dashmap = { version = "5.4", optional = true } # for services-etcd etcd-client = { version = "0.12", optional = true, features = ["tls"] } # for services-foundationdb -foundationdb = { version = "0.8.0", features = [ - "embedded-fdb-include", -], optional = true } +foundationdb = { version = "0.8.0", features = ["embedded-fdb-include"], optional = true } # for services-hdfs hdrs = { version = "0.3.0", optional = true, features = ["async_file"] } # for services-upyun diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 00bbc63e3ae..bfad590c3eb 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -643,9 +643,9 @@ impl AzblobCore { } } -/// Request of CompleteMultipartUploadRequest +/// Request of PutBlockListRequest #[derive(Default, Debug, Serialize)] -#[serde(default, rename = "", rename_all = "PascalCase")] +#[serde(default, rename = "BlockList", rename_all = "PascalCase")] pub struct PutBlockListRequest { pub uncommitted: Vec, } @@ -890,7 +890,8 @@ mod tests { pretty_assertions::assert_eq!( actual, - r#" + r#" + 1 2 3 From f63b2ff51de690d0ef863cbcb8cfc4fa94461d88 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Fri, 16 Feb 2024 21:26:05 +0800 Subject: [PATCH 10/25] put blocklist part should contain block_id --- core/src/services/azblob/core.rs | 11 +++++++---- core/src/services/azblob/writer.rs | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index bfad590c3eb..9c37ea1f219 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -377,6 +377,7 @@ impl AzblobCore { pub fn azblob_put_block_list_request( &self, path: &str, + block_id: Uuid, size: Option, args: &OpWrite, body: AsyncBody, @@ -385,10 +386,11 @@ impl AzblobCore { let p = build_abs_path(&self.root, path); let url = format!( - "{}/{}/{}?comp=blocklist", + "{}/{}/{}?comp=block&block_id={}", self.endpoint, self.container, - percent_encode_path(&p) + percent_encode_path(&p), + BASE64_STANDARD.encode(block_id), ); let mut req = Request::put(&url); // Set SSE headers. @@ -419,11 +421,12 @@ impl AzblobCore { pub async fn azblob_put_block_list( &self, path: &str, + block_id: Uuid, size: Option, args: &OpWrite, body: AsyncBody, ) -> Result> { - let mut req = self.azblob_put_block_list_request(path, size, args, body)?; + let mut req = self.azblob_put_block_list_request(path, block_id, size, args, body)?; self.sign(&mut req).await?; self.send(req).await @@ -439,7 +442,7 @@ impl AzblobCore { "{}/{}/{}?comp=blocklist", self.endpoint, self.container, - percent_encode_path(&p) + percent_encode_path(&p), ); let req = Request::post(&url); diff --git a/core/src/services/azblob/writer.rs b/core/src/services/azblob/writer.rs index 7c560c156b0..375ad6bc054 100644 --- a/core/src/services/azblob/writer.rs +++ b/core/src/services/azblob/writer.rs @@ -134,10 +134,10 @@ impl oio::BlockWrite for AzblobWriter { } } - async fn write_block(&self, _block_id: Uuid, size: u64, body: AsyncBody) -> Result<()> { + async fn write_block(&self, block_id: Uuid, size: u64, body: AsyncBody) -> Result<()> { let resp = self .core - .azblob_put_block_list(&self.path, Some(size), &self.op, body) + .azblob_put_block_list(&self.path, block_id, Some(size), &self.op, body) .await?; let status = resp.status(); From 13f90da30cdd8ee3c83a93a3aea60cd1d274586d Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 10:30:44 +0800 Subject: [PATCH 11/25] minor fix --- core/src/services/azblob/core.rs | 11 ++++++----- core/src/services/azblob/writer.rs | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 9c37ea1f219..31ae686894b 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -374,7 +374,7 @@ impl AzblobCore { Ok(req) } - pub fn azblob_put_block_list_request( + pub fn azblob_put_block_request( &self, path: &str, block_id: Uuid, @@ -382,11 +382,12 @@ impl AzblobCore { args: &OpWrite, body: AsyncBody, ) -> Result> { - // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list? + // To be written as part of a blob, a block must have been successfully written to the server in an earlier Put Block operation. + // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block?tabs=microsoft-entra-id let p = build_abs_path(&self.root, path); let url = format!( - "{}/{}/{}?comp=block&block_id={}", + "{}/{}/{}?comp=block&blockid={}", self.endpoint, self.container, percent_encode_path(&p), @@ -418,7 +419,7 @@ impl AzblobCore { Ok(req) } - pub async fn azblob_put_block_list( + pub async fn azblob_put_block( &self, path: &str, block_id: Uuid, @@ -426,7 +427,7 @@ impl AzblobCore { args: &OpWrite, body: AsyncBody, ) -> Result> { - let mut req = self.azblob_put_block_list_request(path, block_id, size, args, body)?; + let mut req = self.azblob_put_block_request(path, block_id, size, args, body)?; self.sign(&mut req).await?; self.send(req).await diff --git a/core/src/services/azblob/writer.rs b/core/src/services/azblob/writer.rs index 375ad6bc054..f0d4dda8ab8 100644 --- a/core/src/services/azblob/writer.rs +++ b/core/src/services/azblob/writer.rs @@ -137,7 +137,7 @@ impl oio::BlockWrite for AzblobWriter { async fn write_block(&self, block_id: Uuid, size: u64, body: AsyncBody) -> Result<()> { let resp = self .core - .azblob_put_block_list(&self.path, block_id, Some(size), &self.op, body) + .azblob_put_block(&self.path, block_id, Some(size), &self.op, body) .await?; let status = resp.status(); From 2d3701373fb87a9a5d557d5ae5ae5bc84b7a03bf Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 11:10:47 +0800 Subject: [PATCH 12/25] fix base64 encode --- core/src/services/azblob/core.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 31ae686894b..a8433d44ec2 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -391,7 +391,7 @@ impl AzblobCore { self.endpoint, self.container, percent_encode_path(&p), - BASE64_STANDARD.encode(block_id), + BASE64_STANDARD.encode(block_id.as_bytes()), ); let mut req = Request::put(&url); // Set SSE headers. @@ -459,7 +459,7 @@ impl AzblobCore { let content = quick_xml::se::to_string(&PutBlockListRequest { uncommitted: block_ids .into_iter() - .map(|block_id| BASE64_STANDARD.encode(block_id)) + .map(|block_id| BASE64_STANDARD.encode(block_id.as_bytes())) .collect(), }) .map_err(new_xml_deserialize_error)?; From d45609768066855c0e6f254f86cc6deb94254ebf Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 11:52:07 +0800 Subject: [PATCH 13/25] should do url encode after base64 encode --- core/Cargo.lock | 1 + core/Cargo.toml | 1 + core/src/services/azblob/core.rs | 14 ++++++++++---- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/Cargo.lock b/core/Cargo.lock index fbaaf3f2a8a..7173f026b74 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -4081,6 +4081,7 @@ dependencies = [ "tokio-postgres", "tracing", "tracing-subscriber", + "url", "uuid", "wiremock", ] diff --git a/core/Cargo.toml b/core/Cargo.toml index 4a2056b298a..4b5a0c37df8 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -262,6 +262,7 @@ reqwest = { version = "0.11.18", features = [ serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1.27", features = ["sync"] } +url = "2.5.0" uuid = { version = "1", features = ["serde", "v4"] } # Test only dependencies diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index a8433d44ec2..87150bf78d3 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -19,7 +19,6 @@ use base64::prelude::BASE64_STANDARD; use base64::Engine; use bytes::Bytes; use http::header::HeaderName; - use http::header::CONTENT_LENGTH; use http::header::CONTENT_TYPE; use http::header::IF_MATCH; @@ -36,6 +35,7 @@ use std::fmt::Debug; use std::fmt::Formatter; use std::fmt::Write; use std::time::Duration; +use url::form_urlencoded::byte_serialize; use uuid::Uuid; use crate::raw::*; @@ -385,13 +385,14 @@ impl AzblobCore { // To be written as part of a blob, a block must have been successfully written to the server in an earlier Put Block operation. // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block?tabs=microsoft-entra-id let p = build_abs_path(&self.root, path); - + let encoded_block_id: String = + byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()).collect(); let url = format!( "{}/{}/{}?comp=block&blockid={}", self.endpoint, self.container, percent_encode_path(&p), - BASE64_STANDARD.encode(block_id.as_bytes()), + encoded_block_id, ); let mut req = Request::put(&url); // Set SSE headers. @@ -459,7 +460,12 @@ impl AzblobCore { let content = quick_xml::se::to_string(&PutBlockListRequest { uncommitted: block_ids .into_iter() - .map(|block_id| BASE64_STANDARD.encode(block_id.as_bytes())) + .map(|block_id| { + let encoded_block_id: String = + byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()) + .collect(); + encoded_block_id + }) .collect(), }) .map_err(new_xml_deserialize_error)?; From 1331dbd6e0788cf4665619512dbbebf1d1b30726 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 15:56:49 +0800 Subject: [PATCH 14/25] use latest when complete put block list --- core/src/services/azblob/core.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 87150bf78d3..c1dc0b956c9 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -458,7 +458,7 @@ impl AzblobCore { ); let content = quick_xml::se::to_string(&PutBlockListRequest { - uncommitted: block_ids + latest: block_ids .into_iter() .map(|block_id| { let encoded_block_id: String = @@ -657,7 +657,7 @@ impl AzblobCore { #[derive(Default, Debug, Serialize)] #[serde(default, rename = "BlockList", rename_all = "PascalCase")] pub struct PutBlockListRequest { - pub uncommitted: Vec, + pub latest: Vec, } #[derive(Default, Debug, Deserialize)] @@ -893,7 +893,7 @@ mod tests { #[test] fn test_serialize_put_block_list_request() { let req = PutBlockListRequest { - uncommitted: vec!["1".to_string(), "2".to_string(), "3".to_string()], + latest: vec!["1".to_string(), "2".to_string(), "3".to_string()], }; let actual = quick_xml::se::to_string(&req).expect("must succeed"); @@ -902,9 +902,9 @@ mod tests { actual, r#" - 1 - 2 - 3 + 1 + 2 + 3 "# // Cleanup space and new line .replace([' ', '\n'], "") From 1a6ef7d9f3e4229a89924d00c6829933bc270b85 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 16:24:47 +0800 Subject: [PATCH 15/25] enhance ut --- core/src/services/azblob/core.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index c1dc0b956c9..d0aad66086c 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -654,7 +654,7 @@ impl AzblobCore { } /// Request of PutBlockListRequest -#[derive(Default, Debug, Serialize)] +#[derive(Default, Debug, Serialize, Deserialize)] #[serde(default, rename = "BlockList", rename_all = "PascalCase")] pub struct PutBlockListRequest { pub latest: Vec, @@ -910,6 +910,20 @@ mod tests { .replace([' ', '\n'], "") // Escape `"` by hand to address .replace('"', """) - ) + ); + + let bs = " + + 1 + 2 + 3 + "; + + let out: PutBlockListRequest = + de::from_reader(Bytes::from(bs).reader()).expect("must success"); + assert_eq!( + out.latest, + vec!["1".to_string(), "2".to_string(), "3".to_string()] + ); } } From 7e170212faaef1287b2ad563d9a4a6b66c8c09a9 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 16:34:48 +0800 Subject: [PATCH 16/25] put block list use put not post --- core/src/services/azblob/core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index d0aad66086c..2c1e6703099 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -447,7 +447,7 @@ impl AzblobCore { percent_encode_path(&p), ); - let req = Request::post(&url); + let req = Request::put(&url); // Set SSE headers. let mut req = self.insert_sse_headers(req); From 53dd3bbf3f8cb79d196012c38f507a4970a6c6b1 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 17:08:03 +0800 Subject: [PATCH 17/25] add content length --- core/src/services/azblob/core.rs | 21 +++++++++------------ core/src/services/azblob/writer.rs | 2 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 2c1e6703099..91554fe1d35 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -408,12 +408,6 @@ impl AzblobCore { if let Some(ty) = args.content_type() { req = req.header(CONTENT_TYPE, ty) } - - req = req.header( - HeaderName::from_static(constants::X_MS_BLOB_TYPE), - "BlockBlob", - ); - // Set body let req = req.body(body).map_err(new_request_build_error)?; @@ -438,6 +432,7 @@ impl AzblobCore { &self, path: &str, block_ids: Vec, + args: &OpWrite, ) -> Result> { let p = build_abs_path(&self.root, path); let url = format!( @@ -451,11 +446,9 @@ impl AzblobCore { // Set SSE headers. let mut req = self.insert_sse_headers(req); - - req = req.header( - HeaderName::from_static(constants::X_MS_BLOB_TYPE), - "BlockBlob", - ); + if let Some(cache_control) = args.cache_control() { + req = req.header(constants::X_MS_BLOB_CACHE_CONTROL, cache_control); + } let content = quick_xml::se::to_string(&PutBlockListRequest { latest: block_ids @@ -469,6 +462,9 @@ impl AzblobCore { .collect(), }) .map_err(new_xml_deserialize_error)?; + + req = req.header(CONTENT_LENGTH, content.len()); + let req = req .body(AsyncBody::Bytes(Bytes::from(content))) .map_err(new_request_build_error)?; @@ -480,9 +476,10 @@ impl AzblobCore { &self, path: &str, block_ids: Vec, + args: &OpWrite, ) -> Result> { let mut req = self - .azblob_complete_put_block_list_request(path, block_ids) + .azblob_complete_put_block_list_request(path, block_ids, args) .await?; self.sign(&mut req).await?; diff --git a/core/src/services/azblob/writer.rs b/core/src/services/azblob/writer.rs index f0d4dda8ab8..e0cbc72f9ae 100644 --- a/core/src/services/azblob/writer.rs +++ b/core/src/services/azblob/writer.rs @@ -153,7 +153,7 @@ impl oio::BlockWrite for AzblobWriter { async fn complete_block(&self, block_ids: Vec) -> Result<()> { let resp = self .core - .azblob_complete_put_block_list(&self.path, block_ids) + .azblob_complete_put_block_list(&self.path, block_ids, &self.op) .await?; let status = resp.status(); From e53019865ffc6f0cb21498518bf98e50f57122d5 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 17:24:36 +0800 Subject: [PATCH 18/25] empty commit for retry From 97497161eaa0cb32db59536b61b6b77629a22279 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 20:51:05 +0800 Subject: [PATCH 19/25] resolve some comments --- core/Cargo.toml | 4 +++- core/src/services/azblob/core.rs | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index 4b5a0c37df8..32665689c98 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -297,7 +297,9 @@ dashmap = { version = "5.4", optional = true } # for services-etcd etcd-client = { version = "0.12", optional = true, features = ["tls"] } # for services-foundationdb -foundationdb = { version = "0.8.0", features = ["embedded-fdb-include"], optional = true } +foundationdb = { version = "0.8.0", features = [ + "embedded-fdb-include", +], optional = true } # for services-hdfs hdrs = { version = "0.3.0", optional = true, features = ["async_file"] } # for services-upyun diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 91554fe1d35..88778877e48 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -386,7 +386,7 @@ impl AzblobCore { // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block?tabs=microsoft-entra-id let p = build_abs_path(&self.root, path); let encoded_block_id: String = - byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()).collect(); + byte_serialize(BASE64_STANDARD.encode(block_id).as_bytes()).collect(); let url = format!( "{}/{}/{}?comp=block&blockid={}", self.endpoint, @@ -455,8 +455,7 @@ impl AzblobCore { .into_iter() .map(|block_id| { let encoded_block_id: String = - byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()) - .collect(); + byte_serialize(BASE64_STANDARD.encode(block_id).as_bytes()).collect(); encoded_block_id }) .collect(), From a8424bf7796491180173c0e4c0e1da9292c8a904 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 20:57:39 +0800 Subject: [PATCH 20/25] come bacl, to_string for block_id --- core/src/services/azblob/core.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 88778877e48..c6a43a55426 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -386,7 +386,7 @@ impl AzblobCore { // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block?tabs=microsoft-entra-id let p = build_abs_path(&self.root, path); let encoded_block_id: String = - byte_serialize(BASE64_STANDARD.encode(block_id).as_bytes()).collect(); + byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()).collect(); let url = format!( "{}/{}/{}?comp=block&blockid={}", self.endpoint, @@ -455,7 +455,7 @@ impl AzblobCore { .into_iter() .map(|block_id| { let encoded_block_id: String = - byte_serialize(BASE64_STANDARD.encode(block_id).as_bytes()).collect(); + byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()).collect(); encoded_block_id }) .collect(), From 8fd82565eaa6e487df40c211173a47f7c60459b8 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sat, 17 Feb 2024 21:00:52 +0800 Subject: [PATCH 21/25] fmt --- core/src/services/azblob/core.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index c6a43a55426..91554fe1d35 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -455,7 +455,8 @@ impl AzblobCore { .into_iter() .map(|block_id| { let encoded_block_id: String = - byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()).collect(); + byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()) + .collect(); encoded_block_id }) .collect(), From 1269eea00a2f92dd675a30fb4a93be29d489dddf Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sun, 18 Feb 2024 10:18:16 +0800 Subject: [PATCH 22/25] resolve comments --- core/Cargo.lock | 1 - core/Cargo.toml | 1 - core/src/services/azblob/core.rs | 7 +++---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/core/Cargo.lock b/core/Cargo.lock index 7173f026b74..fbaaf3f2a8a 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -4081,7 +4081,6 @@ dependencies = [ "tokio-postgres", "tracing", "tracing-subscriber", - "url", "uuid", "wiremock", ] diff --git a/core/Cargo.toml b/core/Cargo.toml index 32665689c98..69d1010d16b 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -262,7 +262,6 @@ reqwest = { version = "0.11.18", features = [ serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1.27", features = ["sync"] } -url = "2.5.0" uuid = { version = "1", features = ["serde", "v4"] } # Test only dependencies diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 91554fe1d35..9d42f488348 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -35,7 +35,6 @@ use std::fmt::Debug; use std::fmt::Formatter; use std::fmt::Write; use std::time::Duration; -use url::form_urlencoded::byte_serialize; use uuid::Uuid; use crate::raw::*; @@ -385,8 +384,9 @@ impl AzblobCore { // To be written as part of a blob, a block must have been successfully written to the server in an earlier Put Block operation. // refer to https://learn.microsoft.com/en-us/rest/api/storageservices/put-block?tabs=microsoft-entra-id let p = build_abs_path(&self.root, path); + let encoded_block_id: String = - byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()).collect(); + percent_encode_path(&BASE64_STANDARD.encode(block_id.simple().to_string())); let url = format!( "{}/{}/{}?comp=block&blockid={}", self.endpoint, @@ -455,8 +455,7 @@ impl AzblobCore { .into_iter() .map(|block_id| { let encoded_block_id: String = - byte_serialize(BASE64_STANDARD.encode(block_id.to_string()).as_bytes()) - .collect(); + percent_encode_path(&BASE64_STANDARD.encode(block_id.simple().to_string())); encoded_block_id }) .collect(), From 5f99a19244be3a2be4a88a66f2dcabb3658b2fdb Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sun, 18 Feb 2024 10:29:40 +0800 Subject: [PATCH 23/25] remove .simple() to see whether CI can pass --- core/src/services/azblob/core.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 9d42f488348..129af170cb0 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -386,7 +386,7 @@ impl AzblobCore { let p = build_abs_path(&self.root, path); let encoded_block_id: String = - percent_encode_path(&BASE64_STANDARD.encode(block_id.simple().to_string())); + percent_encode_path(&BASE64_STANDARD.encode(block_id.to_string())); let url = format!( "{}/{}/{}?comp=block&blockid={}", self.endpoint, @@ -455,7 +455,7 @@ impl AzblobCore { .into_iter() .map(|block_id| { let encoded_block_id: String = - percent_encode_path(&BASE64_STANDARD.encode(block_id.simple().to_string())); + percent_encode_path(&BASE64_STANDARD.encode(block_id.to_string())); encoded_block_id }) .collect(), From 3091645a8ae7a64eff0d0d3bd6105b499d277bf3 Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sun, 18 Feb 2024 12:13:21 +0800 Subject: [PATCH 24/25] do not percent_encode_path in xml body --- core/src/services/azblob/core.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index 129af170cb0..ad55c4525cb 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use base64::prelude::BASE64_STANDARD; +use base64::prelude::BASE64_URL_SAFE; use base64::Engine; use bytes::Bytes; use http::header::HeaderName; @@ -386,7 +386,7 @@ impl AzblobCore { let p = build_abs_path(&self.root, path); let encoded_block_id: String = - percent_encode_path(&BASE64_STANDARD.encode(block_id.to_string())); + percent_encode_path(&BASE64_URL_SAFE.encode(block_id.as_bytes())); let url = format!( "{}/{}/{}?comp=block&blockid={}", self.endpoint, @@ -454,8 +454,7 @@ impl AzblobCore { latest: block_ids .into_iter() .map(|block_id| { - let encoded_block_id: String = - percent_encode_path(&BASE64_STANDARD.encode(block_id.to_string())); + let encoded_block_id: String = BASE64_URL_SAFE.encode(block_id.as_bytes()); encoded_block_id }) .collect(), From c332fc92daf5012b534a7c759a924d3b9804492d Mon Sep 17 00:00:00 2001 From: congyi <15605187270@163.com> Date: Sun, 18 Feb 2024 12:32:22 +0800 Subject: [PATCH 25/25] use BASE64_STANDARD --- core/src/services/azblob/core.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/services/azblob/core.rs b/core/src/services/azblob/core.rs index ad55c4525cb..c0c6790b17e 100644 --- a/core/src/services/azblob/core.rs +++ b/core/src/services/azblob/core.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use base64::prelude::BASE64_URL_SAFE; +use base64::prelude::BASE64_STANDARD; use base64::Engine; use bytes::Bytes; use http::header::HeaderName; @@ -386,7 +386,7 @@ impl AzblobCore { let p = build_abs_path(&self.root, path); let encoded_block_id: String = - percent_encode_path(&BASE64_URL_SAFE.encode(block_id.as_bytes())); + percent_encode_path(&BASE64_STANDARD.encode(block_id.as_bytes())); let url = format!( "{}/{}/{}?comp=block&blockid={}", self.endpoint, @@ -454,7 +454,7 @@ impl AzblobCore { latest: block_ids .into_iter() .map(|block_id| { - let encoded_block_id: String = BASE64_URL_SAFE.encode(block_id.as_bytes()); + let encoded_block_id: String = BASE64_STANDARD.encode(block_id.as_bytes()); encoded_block_id }) .collect(),