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/incubator-opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 135b389ec refactor(raw): add parse_header_to_str fn (#3804)
135b389ec is described below
commit 135b389ecbd9f69fbd6e00843928e14e45a5cf0f
Author: hoslo <[email protected]>
AuthorDate: Sat Dec 23 18:50:41 2023 +0800
refactor(raw): add parse_header_to_str fn (#3804)
---
core/src/raw/http_util/header.rs | 16 +++++++
core/src/raw/http_util/mod.rs | 1 +
core/src/services/upyun/core.rs | 96 +++++----------------------------------
core/src/services/upyun/writer.rs | 25 +++++-----
4 files changed, 40 insertions(+), 98 deletions(-)
diff --git a/core/src/raw/http_util/header.rs b/core/src/raw/http_util/header.rs
index 8262953de..fdb4312d7 100644
--- a/core/src/raw/http_util/header.rs
+++ b/core/src/raw/http_util/header.rs
@@ -19,6 +19,7 @@ use base64::engine::general_purpose;
use base64::Engine;
use chrono::DateTime;
use chrono::Utc;
+use http::header::AsHeaderName;
use http::header::HeaderName;
use http::header::CACHE_CONTROL;
use http::header::CONTENT_DISPOSITION;
@@ -199,6 +200,21 @@ pub fn parse_content_disposition(headers: &HeaderMap) ->
Result<Option<&str>> {
}
}
+/// Parse header value to string according to name.
+pub fn parse_header_to_str<K: AsHeaderName>(headers: &HeaderMap, name: K) ->
Result<Option<&str>> {
+ match headers.get(name) {
+ None => Ok(None),
+ Some(v) => Ok(Some(v.to_str().map_err(|e| {
+ Error::new(
+ ErrorKind::Unexpected,
+ "header value has to be valid utf-8 string",
+ )
+ .with_operation("http_util::parse_header_to_str")
+ .set_source(e)
+ })?)),
+ }
+}
+
/// parse_into_metadata will parse standards http headers into Metadata.
///
/// # Notes
diff --git a/core/src/raw/http_util/mod.rs b/core/src/raw/http_util/mod.rs
index 0bf62ee93..8dd9a58ee 100644
--- a/core/src/raw/http_util/mod.rs
+++ b/core/src/raw/http_util/mod.rs
@@ -40,6 +40,7 @@ pub use header::parse_content_md5;
pub use header::parse_content_range;
pub use header::parse_content_type;
pub use header::parse_etag;
+pub use header::parse_header_to_str;
pub use header::parse_into_metadata;
pub use header::parse_last_modified;
pub use header::parse_location;
diff --git a/core/src/services/upyun/core.rs b/core/src/services/upyun/core.rs
index 45d890a2c..4c02d1b33 100644
--- a/core/src/services/upyun/core.rs
+++ b/core/src/services/upyun/core.rs
@@ -29,7 +29,7 @@ use crate::*;
use self::constants::*;
-mod constants {
+pub(super) mod constants {
pub const X_UPYUN_FILE_TYPE: &str = "x-upyun-file-type";
pub const X_UPYUN_FILE_SIZE: &str = "x-upyun-file-size";
pub const X_UPYUN_CACHE_CONTROL: &str = "x-upyun-meta-cache-control";
@@ -452,22 +452,8 @@ impl UpyunSigner {
}
}
-pub(super) fn parse_initiate_part(headers: &HeaderMap) -> Result<&str> {
- match headers.get(X_UPYUN_MULTI_UUID) {
- None => Err(Error::new(ErrorKind::Unexpected, "missing uuid")),
- Some(v) => Ok(v.to_str().map_err(|e| {
- Error::new(
- ErrorKind::Unexpected,
- "header value has to be valid utf-8 string",
- )
- .with_operation("parse_initiate_part")
- .set_source(e)
- })?),
- }
-}
-
pub(super) fn parse_info(headers: &HeaderMap) -> Result<Metadata> {
- let mode = if parse_file_type(headers)? == "file" {
+ let mode = if parse_header_to_str(headers, X_UPYUN_FILE_TYPE)? ==
Some("file") {
EntryMode::FILE
} else {
EntryMode::DIR
@@ -475,8 +461,13 @@ pub(super) fn parse_info(headers: &HeaderMap) ->
Result<Metadata> {
let mut m = Metadata::new(mode);
- if let Some(v) = parse_file_size(headers)? {
- m.set_content_length(v);
+ if let Some(v) = parse_header_to_str(headers, X_UPYUN_FILE_SIZE)? {
+ let size = v.parse::<u64>().map_err(|e| {
+ Error::new(ErrorKind::Unexpected, "header value is not valid
integer")
+ .with_operation("parse_info")
+ .set_source(e)
+ })?;
+ m.set_content_length(size);
}
if let Some(v) = parse_content_type(headers)? {
@@ -487,82 +478,17 @@ pub(super) fn parse_info(headers: &HeaderMap) ->
Result<Metadata> {
m.set_content_md5(v);
}
- if let Some(v) = parse_cache_control(headers)? {
+ if let Some(v) = parse_header_to_str(headers, X_UPYUN_CACHE_CONTROL)? {
m.set_cache_control(v);
}
- if let Some(v) = parse_content_disposition(headers)? {
+ if let Some(v) = parse_header_to_str(headers,
X_UPYUN_CONTENT_DISPOSITION)? {
m.set_content_disposition(v);
}
Ok(m)
}
-fn parse_file_type(headers: &HeaderMap) -> Result<&str> {
- match headers.get(X_UPYUN_FILE_TYPE) {
- None => Err(Error::new(ErrorKind::Unexpected, "missing file type")),
- Some(v) => Ok(v.to_str().map_err(|e| {
- Error::new(
- ErrorKind::Unexpected,
- "header value has to be valid utf-8 string",
- )
- .with_operation("parse_file_type")
- .set_source(e)
- })?),
- }
-}
-
-fn parse_file_size(headers: &HeaderMap) -> Result<Option<u64>> {
- match headers.get(X_UPYUN_FILE_SIZE) {
- None => Ok(None),
- Some(v) => Ok(Some(
- v.to_str()
- .map_err(|e| {
- Error::new(
- ErrorKind::Unexpected,
- "header value is not valid utf-8 string",
- )
- .with_operation("http_util::parse_content_length")
- .set_source(e)
- })?
- .parse::<u64>()
- .map_err(|e| {
- Error::new(ErrorKind::Unexpected, "header value is not
valid integer")
- .with_operation("http_util::parse_content_length")
- .set_source(e)
- })?,
- )),
- }
-}
-
-fn parse_cache_control(headers: &HeaderMap) -> Result<Option<&str>> {
- match headers.get(X_UPYUN_CACHE_CONTROL) {
- None => Ok(None),
- Some(v) => Ok(Some(v.to_str().map_err(|e| {
- Error::new(
- ErrorKind::Unexpected,
- "header value has to be valid utf-8 string",
- )
- .with_operation("parse_cache_control")
- .set_source(e)
- })?)),
- }
-}
-
-fn parse_content_disposition(headers: &HeaderMap) -> Result<Option<&str>> {
- match headers.get(X_UPYUN_CONTENT_DISPOSITION) {
- None => Ok(None),
- Some(v) => Ok(Some(v.to_str().map_err(|e| {
- Error::new(
- ErrorKind::Unexpected,
- "header value has to be valid utf-8 string",
- )
- .with_operation("parse_content_disposition")
- .set_source(e)
- })?)),
- }
-}
-
pub fn format_md5(bs: &[u8]) -> String {
let mut hasher = md5::Md5::new();
hasher.update(bs);
diff --git a/core/src/services/upyun/writer.rs
b/core/src/services/upyun/writer.rs
index c0b42e44f..a245ae23c 100644
--- a/core/src/services/upyun/writer.rs
+++ b/core/src/services/upyun/writer.rs
@@ -23,7 +23,8 @@ use http::StatusCode;
use crate::raw::*;
use crate::*;
-use super::core::{parse_initiate_part, UpyunCore};
+use super::core::constants::X_UPYUN_MULTI_UUID;
+use super::core::UpyunCore;
use super::error::parse_error;
pub type UpyunWriters = oio::MultipartUploadWriter<UpyunWriter>;
@@ -71,7 +72,11 @@ impl oio::MultipartUploadWrite for UpyunWriter {
match status {
StatusCode::NO_CONTENT => {
- let id = parse_initiate_part(resp.headers())?;
+ let id =
+ parse_header_to_str(resp.headers(),
X_UPYUN_MULTI_UUID)?.ok_or(Error::new(
+ ErrorKind::Unexpected,
+ &format!("{} header is missing", X_UPYUN_MULTI_UUID),
+ ))?;
Ok(id.to_string())
}
@@ -96,19 +101,13 @@ impl oio::MultipartUploadWrite for UpyunWriter {
let status = resp.status();
match status {
- StatusCode::NO_CONTENT => {
- let etag = parse_etag(resp.headers())?
- .ok_or_else(|| {
- Error::new(
- ErrorKind::Unexpected,
- "ETag not present in returning response",
- )
- })?
- .to_string();
-
+ StatusCode::NO_CONTENT | StatusCode::CREATED => {
resp.into_body().consume().await?;
- Ok(oio::MultipartUploadPart { part_number, etag })
+ Ok(oio::MultipartUploadPart {
+ part_number,
+ etag: "".to_string(),
+ })
}
_ => Err(parse_error(resp).await?),
}