Skip to content

Commit

Permalink
fix(auth): 解决模块之间的依赖问题
Browse files Browse the repository at this point in the history
auth GenCanonicalizedResource 自己计算签名时,不依赖 type 模块的特殊类型 object bucket
query 等

所有 feature 都加载 crate::types 模块,只有 core feature 才加载 crate::types::object
和 crate::types::core 模块
  • Loading branch information
tu6ge committed Apr 14, 2023
1 parent 461099a commit 3965c77
Show file tree
Hide file tree
Showing 6 changed files with 873 additions and 843 deletions.
53 changes: 33 additions & 20 deletions src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
use crate::{
types::{
object::ObjectPathInner, CanonicalizedResource, ContentMd5, ContentType, Date,
InnerCanonicalizedResource, InnerContentMd5, InnerDate, InnerKeyId, InnerKeySecret, KeyId,
KeySecret,
CanonicalizedResource, ContentMd5, ContentType, Date, InnerCanonicalizedResource,
InnerContentMd5, InnerDate, InnerKeyId, InnerKeySecret, KeyId, KeySecret,
CONTINUATION_TOKEN,
},
BucketName, EndPoint, Query,
BucketName, EndPoint,
};
use chrono::Utc;
#[cfg(test)]
Expand All @@ -38,8 +38,8 @@ use http::{
};
#[cfg(test)]
use mockall::automock;
use std::convert::TryInto;
use std::fmt::Display;
use std::{borrow::Cow, convert::TryInto};

#[cfg(test)]
mod test;
Expand Down Expand Up @@ -636,12 +636,12 @@ pub trait GenCanonicalizedResource {
/// 根据 Url 的 query 计算 [`Query`]
///
/// [`Query`]: crate::types::Query
fn oss_query(&self) -> Query;
fn object_list_resource(&self, bucket: &BucketName) -> CanonicalizedResource;

/// 根据 Url 的 path 计算当前使用的 [`ObjectPathInner`]
///
/// [`ObjectPathInner`]: crate::config::ObjectPathInner
fn object_path(&self) -> Option<ObjectPathInner>;
fn object_path(&self) -> Option<Cow<'_, str>>;
}

/// Oss 域名的几种状态
Expand Down Expand Up @@ -683,17 +683,17 @@ impl GenCanonicalizedResource for Url {
Some(BUCKET_INFO),
)),
// 查 object_list
Some(q) if q.ends_with(LIST_TYPE2) || q.contains(LIST_TYPE2_AND) => Some(
CanonicalizedResource::from_bucket_query2(&bucket, &self.oss_query()),
),
Some(q) if q.ends_with(LIST_TYPE2) || q.contains(LIST_TYPE2_AND) => {
Some(self.object_list_resource(&bucket))
}
// 其他情况待定
_ => todo!("Unable to obtain can information based on existing query information"),
};
}

// 获取 ObjectPath 失败,返回 None,否则根据 ObjectPath 计算 CanonicalizedResource
self.object_path()
.map(|path| CanonicalizedResource::from_object((bucket.as_ref(), path.as_ref()), []))
.map(|path| CanonicalizedResource::from_object_without_query(bucket.as_ref(), path))
}

fn oss_host(&self) -> OssHost {
Expand Down Expand Up @@ -730,22 +730,35 @@ impl GenCanonicalizedResource for Url {
}
}

fn oss_query(&self) -> Query {
self.query_pairs()
.filter(|(_, val)| !val.is_empty())
.collect()
fn object_list_resource(&self, bucket: &BucketName) -> CanonicalizedResource {
let mut query = self.query_pairs().filter(|(_, val)| !val.is_empty());
match query.find(|(key, _)| key == CONTINUATION_TOKEN) {
Some((_, token)) => CanonicalizedResource::new(format!(
"/{}/?continuation-token={}",
bucket.as_ref(),
token
)),
None => CanonicalizedResource::new(format!("/{}/", bucket.as_ref())),
}
}

fn object_path(&self) -> Option<ObjectPathInner> {
fn object_path(&self) -> Option<Cow<'_, str>> {
use percent_encoding::percent_decode;

if self.path().ends_with('/') {
return None;
}

let input = if self.path().starts_with('/') {
&self.path()[1..]
} else {
self.path()
}
.as_bytes();
ObjectPathInner::new(percent_decode(input).decode_utf8().ok()?).ok()
percent_decode(input)
.decode_utf8()
.ok()
.map(|str| str.to_owned())
}
}

Expand All @@ -758,11 +771,11 @@ impl GenCanonicalizedResource for Request {
self.url().oss_host()
}

fn oss_query(&self) -> Query {
self.url().oss_query()
fn object_list_resource(&self, bucket: &BucketName) -> CanonicalizedResource {
self.url().object_list_resource(bucket)
}

fn object_path(&self) -> Option<ObjectPathInner> {
fn object_path(&self) -> Option<Cow<'_, str>> {
self.url().object_path()
}
}
Expand Down
50 changes: 23 additions & 27 deletions src/auth/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,11 +678,7 @@ mod tests_canonicalized_resource {
use http::Method;
use reqwest::Url;

use crate::{
auth::OssHost,
types::{object::ObjectPathInner, CanonicalizedResource},
BucketName,
};
use crate::{auth::OssHost, types::CanonicalizedResource, BucketName};

use super::super::GenCanonicalizedResource;

Expand Down Expand Up @@ -760,41 +756,36 @@ mod tests_canonicalized_resource {
}

#[test]
fn test_oss_query() {
use crate::{QueryKey, QueryValue};
fn test_object_list_resource() {
let url: Url = "https://example.com/path1?delimiter=5".parse().unwrap();
let query = url.oss_query();
assert!(query[QueryKey::Delimiter] == QueryValue::new("5"));
let bucket = "abc".parse().unwrap();
let resource = url.object_list_resource(&bucket);
assert!(resource == "/abc/");

let url: Url = "https://example.com/path1?continuation-token=bar&delimiter=5"
.parse()
.unwrap();
let bucket = "abc".parse().unwrap();
let resource = url.object_list_resource(&bucket);
assert!(resource == "/abc/?continuation-token=bar");
}

#[test]
fn test_object_path() {
let url: Url = "https://example.com/path1".parse().unwrap();
assert_eq!(
url.object_path(),
Some(ObjectPathInner::new("path1").unwrap())
);
assert_eq!(url.object_path().unwrap(), "path1");

let url: Url = "https://example.com/path1/object2".parse().unwrap();
assert_eq!(
url.object_path(),
Some(ObjectPathInner::new("path1/object2").unwrap())
);
assert_eq!(url.object_path().unwrap(), "path1/object2");

let url: Url = "https://example.com/路径/object2".parse().unwrap();
assert_eq!(
url.object_path(),
Some(ObjectPathInner::new("路径/object2").unwrap())
);
assert_eq!(url.object_path().unwrap(), "路径/object2");

let url: Url = "https://example.com/path1/object2?foo=bar".parse().unwrap();
assert_eq!(
url.object_path(),
Some(ObjectPathInner::new("path1/object2").unwrap())
);
assert_eq!(url.object_path().unwrap(), "path1/object2");

let url: Url = "https://example.com/path1/".parse().unwrap();
assert_eq!(url.object_path(), None);
assert!(url.object_path().is_none());
}

#[test]
Expand All @@ -813,7 +804,12 @@ mod tests_canonicalized_resource {
request.url().canonicalized_resource(),
);
assert_eq!(request.oss_host(), request.url().oss_host(),);
assert_eq!(request.oss_query(), request.url().oss_query(),);

let bucket = "abc".parse().unwrap();
assert_eq!(
request.object_list_resource(&bucket),
request.url().object_list_resource(&bucket),
);
assert_eq!(request.object_path(), request.url().object_path(),);
}
}
15 changes: 8 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,23 +231,24 @@ let client = aliyun_oss_client::Client::new(
extern crate test;

/// 库内置类型的定义模块
#[cfg(any(feature = "core", feature = "auth", test))]
pub mod types;
#[cfg(any(feature = "core", test))]
#[cfg(feature = "core")]
use builder::ClientWithMiddleware;
#[cfg(any(feature = "core", test))]
#[cfg(feature = "core")]
use config::Config;

/// 重新导出 http 库的一些方法,便于开发者调用 lib 未提供的 api
#[cfg(any(feature = "core", test))]
#[cfg(feature = "core")]
pub use http::{
header::{HeaderMap, HeaderName, HeaderValue},
Method,
};
#[cfg(any(feature = "core", test))]

#[cfg(feature = "core")]
pub use types::object::{ObjectDir, ObjectPath};
#[cfg(any(feature = "core", feature = "auth", test))]
pub use types::{BucketName, EndPoint, KeyId, KeySecret, Query, QueryKey, QueryValue};
pub use types::{BucketName, EndPoint, KeyId, KeySecret};
#[cfg(feature = "core")]
pub use types::{Query, QueryKey, QueryValue};

/// # 验证模块
/// 包含了签名验证的一些方法,header 以及参数的封装
Expand Down
11 changes: 9 additions & 2 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ use std::num::ParseIntError;

use quick_xml::{events::Event, Reader};

use crate::types::InvalidEndPoint;
#[cfg(feature = "core")]
use crate::{
errors::OssError,
Expand Down Expand Up @@ -387,6 +388,8 @@ pub trait ListError: StdError + 'static {}

impl ListError for ParseIntError {}

impl ListError for InvalidEndPoint {}

#[cfg(feature = "core")]
impl ListError for InvalidObjectPath {}
#[cfg(feature = "core")]
Expand Down Expand Up @@ -438,6 +441,7 @@ impl From<ListErrorKind> for InnerListError {

impl InnerListError {
#[cfg(test)]
#[allow(dead_code)]
pub(crate) fn from_xml() -> Self {
Self {
kind: ListErrorKind::Xml(quick_xml::Error::TextNotFound),
Expand Down Expand Up @@ -801,9 +805,12 @@ mod tests {

#[test]
fn test_list_from() {
let string = InvalidObjectPath { _priv: () };
let string = InvalidEndPoint { _priv: () };
let err: InnerListError = string.into();
assert_eq!(format!("{err}"), "invalid object path");
assert_eq!(
format!("{err}"),
"endpoint must not with `-` prefix or `-` suffix or `oss-` prefix"
);
}

#[test]
Expand Down
Loading

0 comments on commit 3965c77

Please sign in to comment.