Skip to content

Commit

Permalink
fix codes
Browse files Browse the repository at this point in the history
  • Loading branch information
bujnlc8 committed Aug 6, 2024
1 parent 80a28fa commit cf6ad03
Show file tree
Hide file tree
Showing 12 changed files with 331 additions and 209 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/qcos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ jobs:

steps:
- uses: actions/checkout@v3
- name: Lint
run: cargo clippy
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
run: cargo test --verbose -- --nocapture
26 changes: 13 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
[package]
name = "qcos"
version = "0.1.6"
version = "0.1.7"
edition = "2021"
authors = ["bujnlc8 <[email protected]>"]
description = "provide basic interface encapsulation of Tencent Cloud Object Storage (cos)"
repository = "https://github.com/bujnlc8/qcos"
license = "MIT"
keywords = ["cos", "tengxunyun", "tencentcloud"]
keywords = ["cos", "tengxunyun", "tencentcloud", "qcos"]

[dependencies]
reqwest = { version = "0.11", features = ["json","stream"] }
reqwest = { version = "0.12", features = ["json","stream", "rustls-tls"] , default-features = false}
serde = {version="1", features = ["derive"]}
serde_json = "1.0"
chrono = "0.4.19"
ring = "0.16.20"
urlencoding = "2.1.0"
sha1 = "0.10.1"
mime = "0.3.16"
bytes ="1.1.0"
quick-xml = {version = "0.23.0-alpha3", features = ["serialize"]}
async-trait = "0.1.56"
tokio = "1.2.0"
chrono = "0.4.38"
hmac-sha1 = "0.2.2"
sha1 = "0.10.6"
urlencoding = "2.1.3"
mime = "0.3.17"
bytes ="1.7.1"
quick-xml = {version = "0.36.1", features = ["serialize"]}
async-trait = "0.1.81"
tokio = { version = "1.39.2", features = ["full"]}

[dev-dependencies]
tokio = { version = "1.2.0", features=["full"] }
tokio = { version = "1.39.2", features = ["full"]}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**异步版本** `async`/`await`

本包提供腾讯云对象存储(cos) 基本的操作,包括`bucket`创建及删除,对象的上传(支持分块传输)、下载、删除等。后续有时间会补充其他接口的实现
本包提供腾讯云对象存储(cos) 基本的操作,包括`bucket`创建及删除,对象的上传(支持分块传输,设置分块大小及上传线程数量)、下载、删除等。

# How to use

Expand All @@ -21,7 +21,7 @@ async fn main() {
);
let mut acl_header = AclHeader::new();
acl_header.insert_object_x_cos_acl(ObjectAcl::PublicRead);
let res = client.put_object("test.png", "test.png", mime::IMAGE_PNG, Some(&acl_header)).await;
let res = client.put_object("test.png", "test.png", mime::IMAGE_PNG, Some(acl_header)).await;
if res.error_no == ErrNo::SUCCESS {
println!("success");
} else {
Expand All @@ -41,5 +41,5 @@ insert into your project's cargo.toml block next line

```
[dependencies]
qcos = "0.1.6"
qcos = "0.1.7"
```
4 changes: 2 additions & 2 deletions examples/bucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async fn main() {
// 创建bucket(有权限控制)
let mut acl = AclHeader::new();
acl.insert_bucket_x_cos_acl(BucketAcl::PRIVATE);
let res = client.put_bucket(Some(&acl)).await;
let res = client.put_bucket(Some(acl)).await;
if res.error_no == ErrNo::SUCCESS {
println!("SUCCESS");
} else {
Expand All @@ -61,7 +61,7 @@ async fn main() {
// 写入存储桶的访问控制列表(ACL)
let mut acl_header = AclHeader::new();
acl_header.insert_bucket_x_cos_acl(BucketAcl::PRIVATE);
let res = client.put_bucket_acl(&acl_header).await;
let res = client.put_bucket_acl(acl_header).await;
if res.error_no == ErrNo::SUCCESS {
println!("SUCCESS");
} else {
Expand Down
21 changes: 14 additions & 7 deletions examples/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ async fn main() {
);
// 普通上传,无权限控制
let res = client
.put_object("Cargo.toml", "Cargo.toml", mime::TEXT_PLAIN_UTF_8, None)
.put_object(
"Cargo.toml",
"Cargo.toml",
Some(mime::TEXT_PLAIN_UTF_8),
None,
)
.await;
if res.error_no == ErrNo::SUCCESS {
println!("SUCCESS");
Expand All @@ -29,8 +34,8 @@ async fn main() {
.put_object(
"Cargo.toml",
"Cargo.toml",
mime::TEXT_PLAIN_UTF_8,
Some(&acl),
Some(mime::TEXT_PLAIN_UTF_8),
Some(acl),
)
.await;
if res.error_no == ErrNo::SUCCESS {
Expand All @@ -40,13 +45,15 @@ async fn main() {
}
// 分块传输
let res = client
.clone()
.put_big_object(
"Cargo.toml",
"Cargo.toml",
mime::TEXT_PLAIN_UTF_8,
"ARCHIVE",
Some(mime::TEXT_PLAIN_UTF_8),
Some(qcos::objects::StorageClassEnum::ARCHIVE),
None,
Some(1024 * 1024),
None,
1024,
)
.await;
if res.error_no == ErrNo::SUCCESS {
Expand All @@ -59,7 +66,7 @@ async fn main() {
.put_object_binary(
std::fs::read("Cargo.toml").unwrap(),
"Cargo.toml",
mime::TEXT_PLAIN_UTF_8,
Some(mime::TEXT_PLAIN_UTF_8),
None,
)
.await;
Expand Down
55 changes: 36 additions & 19 deletions src/acl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ pub enum ObjectAcl {
BucketOwnerFullControl,
}

impl From<ObjectAcl> for String {
fn from(val: ObjectAcl) -> Self {
match val {
ObjectAcl::DEFAULT => String::from("value"),
ObjectAcl::PRIVATE => String::from("private"),
ObjectAcl::PublicRead => String::from("public-read"),
ObjectAcl::BucketOwnerRead => String::from("bucket-owner-read"),
ObjectAcl::AuthenticatedRead => String::from("authenticated-read"),
ObjectAcl::BucketOwnerFullControl => String::from("bucket-owner-full-control"),
}
}
}

/// 存储桶的预设 ACL
#[derive(Debug, PartialEq)]
pub enum BucketAcl {
Expand All @@ -32,10 +45,28 @@ pub enum BucketAcl {
AuthenticatedRead,
}

impl From<BucketAcl> for String {
fn from(value: BucketAcl) -> Self {
match value {
BucketAcl::PRIVATE => String::from("private"),
BucketAcl::PublicRead => String::from("public-read"),
BucketAcl::PublicReadWrite => String::from("public-read-write"),
BucketAcl::AuthenticatedRead => String::from("authenticated-read"),
}
}
}

#[derive(Debug, Clone)]
pub struct AclHeader {
headers: HashMap<String, String>,
}

impl Default for AclHeader {
fn default() -> Self {
Self::new()
}
}

impl AclHeader {
pub fn new() -> AclHeader {
let m = HashMap::new();
Expand All @@ -51,16 +82,8 @@ impl AclHeader {
/// 例如 default,private,public-read 等,默认为 default
/// 注意:如果您不需要进行对象 ACL 控制,请设置为 default 或者此项不进行设置,默认继承存储桶权限
pub fn insert_object_x_cos_acl(&mut self, x_cos_acl: ObjectAcl) -> &mut Self {
let v;
match x_cos_acl {
ObjectAcl::AuthenticatedRead => v = "authenticated-read",
ObjectAcl::DEFAULT => v = "default",
ObjectAcl::PublicRead => v = "public-read",
ObjectAcl::PRIVATE => v = "private",
ObjectAcl::BucketOwnerRead => v = "bucket-owner-read",
ObjectAcl::BucketOwnerFullControl => v = "bucket-owner-full-control",
}
self.headers.insert("x-cos-acl".to_string(), v.to_string());
self.headers
.insert("x-cos-acl".to_string(), x_cos_acl.into());
self
}

Expand Down Expand Up @@ -102,14 +125,8 @@ impl AclHeader {
/// 定义存储桶的访问控制列表(ACL)属性。枚举值请参见 ACL 概述 文档中存储桶的预设 ACL 部分,
/// 如 private,public-read 等,默认为 private
pub fn insert_bucket_x_cos_acl(&mut self, x_cos_acl: BucketAcl) -> &mut Self {
let v;
match x_cos_acl {
BucketAcl::AuthenticatedRead => v = "authenticated-read",
BucketAcl::PRIVATE => v = "private",
BucketAcl::PublicRead => v = "publish-read",
BucketAcl::PublicReadWrite => v = "public-read-write",
}
self.headers.insert("x-cos-acl".to_string(), v.to_string());
self.headers
.insert("x-cos-acl".to_string(), x_cos_acl.into());
self
}

Expand Down Expand Up @@ -137,7 +154,7 @@ mod test {
.insert_x_cos_grant_write_acp("x_cos_grant_write_acp".to_string())
.insert_bucket_x_cos_grant_write("x_cos_grant_write".to_string());

assert_eq!(acl_header.headers["x-cos-acl"], "publish-read".to_string());
assert_eq!(acl_header.headers["x-cos-acl"], "public-read".to_string());
assert_eq!(
acl_header.headers["x-cos-grant-read"],
"x-cos-grant-read".to_string()
Expand Down
25 changes: 13 additions & 12 deletions src/bucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::collections::HashMap;
pub trait Bucket {
/// 在指定账号下创建一个存储桶
/// 创建存储桶时,如果没有指定访问权限,则默认使用私有读写(private)权限。
async fn put_bucket(&self, acl_header: Option<&AclHeader>) -> Response;
async fn put_bucket(&self, acl_header: Option<AclHeader>) -> Response;

/// 用于删除指定的存储桶。该 API 的请求者需要对存储桶有写入权限。
async fn delete_bucket(&self) -> Response;
Expand All @@ -31,7 +31,7 @@ pub trait Bucket {
async fn check_bucket(&self) -> Response;

/// 写入存储桶的访问控制列表(ACL)
async fn put_bucket_acl(&self, acl_header: &AclHeader) -> Response;
async fn put_bucket_acl(&self, acl_header: AclHeader) -> Response;
}

#[async_trait::async_trait]
Expand All @@ -47,11 +47,11 @@ impl Bucket for Client {
/// let mut acl_header = AclHeader::new();
/// acl_header.insert_bucket_x_cos_acl(BucketAcl::PublicRead);
/// let client = Client::new("foo", "bar", "qcloudtest-1256650966", "ap-guangzhou");
/// let res = client.put_bucket(Some(&acl_header)).await;
/// let res = client.put_bucket(Some(acl_header)).await;
/// assert!(res.error_message.contains("403"));
/// };
/// ```
async fn put_bucket(&self, acl_header: Option<&AclHeader>) -> Response {
async fn put_bucket(&self, acl_header: Option<AclHeader>) -> Response {
let headers = self.get_headers_with_auth("put", "/", acl_header, None, None);
let resp = Request::put(
self.get_full_url_from_path("/").as_str(),
Expand Down Expand Up @@ -109,22 +109,22 @@ impl Bucket for Client {
max_keys: i32,
) -> Response {
let mut query = HashMap::new();
if prefix.len() > 0 {
if !prefix.is_empty() {
query.insert("prefix".to_string(), prefix.to_string());
}
if delimiter.len() > 0 {
if !delimiter.is_empty() {
query.insert("delimiter".to_string(), delimiter.to_string());
}
if encoding_type.len() > 0 {
if !encoding_type.is_empty() {
query.insert("encoding-type".to_string(), encoding_type.to_string());
}
if marker.len() > 0 {
if !marker.is_empty() {
query.insert("marker".to_string(), marker.to_string());
}
if max_keys <= 1000 && max_keys > 0 {
query.insert("max-keys".to_string(), max_keys.to_string());
}
let headers = self.get_headers_with_auth("get", "/", None, None, Some(&query));
let headers = self.get_headers_with_auth("get", "/", None, None, Some(query.clone()));
let resp = Request::get(
self.get_full_url_from_path("/").as_str(),
Some(&query),
Expand Down Expand Up @@ -170,14 +170,15 @@ impl Bucket for Client {
/// let mut acl_header = AclHeader::new();
/// acl_header.insert_bucket_x_cos_acl(BucketAcl::PublicRead);
/// let client = Client::new("foo", "bar", "qcloudtest-1256650966", "ap-guangzhou");
/// let res = client.put_bucket(Some(&acl_header)).await;
/// let res = client.put_bucket(Some(acl_header)).await;
/// assert!(res.error_message.contains("403"));
/// };
/// ```
async fn put_bucket_acl(&self, acl_header: &AclHeader) -> Response {
async fn put_bucket_acl(&self, acl_header: AclHeader) -> Response {
let mut query = HashMap::new();
query.insert("acl".to_string(), "".to_string());
let headers = self.get_headers_with_auth("put", "/", Some(acl_header), None, Some(&query));
let headers =
self.get_headers_with_auth("put", "/", Some(acl_header), None, Some(query.clone()));
let resp = Request::put(
self.get_full_url_from_path("/").as_str(),
Some(&query),
Expand Down
9 changes: 5 additions & 4 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::signer::Signer;
use chrono::Utc;
use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct Client {
secrect_id: String,
secrect_key: String,
Expand Down Expand Up @@ -79,9 +80,9 @@ impl Client {
&self,
method: &str,
url_path: &str,
acl_header: Option<&AclHeader>,
acl_header: Option<AclHeader>,
origin_headers: Option<HashMap<String, String>>,
query: Option<&HashMap<String, String>>,
query: Option<HashMap<String, String>>,
) -> HashMap<String, String> {
let mut headers;
if let Some(origin_headers) = origin_headers {
Expand All @@ -94,7 +95,7 @@ impl Client {
headers.insert(k.to_string(), v.to_string());
}
}
let signature = Signer::new(method, url_path, Some(&headers), query).get_signature(
let signature = Signer::new(method, url_path, Some(headers.clone()), query).get_signature(
self.get_secrect_key(),
self.get_secrect_id(),
7200,
Expand All @@ -117,7 +118,7 @@ impl Client {
let full_url = self.get_full_url_from_path(url_path.as_str());
let mut headers = HashMap::new();
headers.insert("host".to_string(), self.get_host());
let signature = Signer::new("get", &url_path, Some(&headers), None).get_signature(
let signature = Signer::new("get", &url_path, Some(headers), None).get_signature(
self.get_secrect_key(),
self.get_secrect_id(),
expire,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
async fn main() {
let client = Client::new("foo", "bar", "qcloudtest-1256650966", "ap-guangzhou");
/// 上传文件
let res = client.put_object("Cargo.toml", "Cargo.toml", mime::TEXT_PLAIN_UTF_8, None).await;
let res = client.put_object("Cargo.toml", "Cargo.toml", Some(mime::TEXT_PLAIN_UTF_8), None).await;
/// 删除文件
let res = client.delete_object("Cargo.toml").await;
}
Expand Down
Loading

0 comments on commit cf6ad03

Please sign in to comment.