aliyun_oss_rs/object/
copy_object.rs1use crate::{
2 common::{Acl, StorageClass, format_gmt, invalid_metadata_key, url_encode},
3 error::{Error, normal_error},
4 request::{Oss, OssRequest},
5};
6use http::Method;
7use std::collections::HashMap;
8use time::OffsetDateTime;
9
10pub struct CopyObject {
16 req: OssRequest,
17 tags: HashMap<String, String>,
18}
19
20impl CopyObject {
21 pub(super) fn new(oss: Oss, copy_source: impl ToString) -> Self {
22 let mut req = OssRequest::new(oss, Method::PUT);
23 req.insert_header("x-oss-copy-source", copy_source);
24 CopyObject {
25 req,
26 tags: HashMap::new(),
27 }
28 }
29 pub fn set_acl(mut self, acl: Acl) -> Self {
31 self.req.insert_header("x-oss-object-acl", acl);
32 self
33 }
34 pub fn set_storage_class(mut self, storage_class: StorageClass) -> Self {
36 self.req.insert_header("x-oss-storage-class", storage_class);
37 self
38 }
39 pub fn set_meta(mut self, key: impl ToString, value: impl ToString) -> Self {
43 let key = key.to_string();
44 if !invalid_metadata_key(&key) {
45 self.req
46 .insert_header(format!("x-oss-meta-{}", key.to_string()), value);
47 }
48 self
49 }
50 pub fn set_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self {
53 self.req.insert_header(
54 "x-oss-copy-source-if-modified-since",
55 format_gmt(if_modified_since),
56 );
57 self
58 }
59 pub fn set_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self {
62 self.req.insert_header(
63 "x-oss-copy-source-if-unmodified-since",
64 format_gmt(if_unmodified_since),
65 );
66 self
67 }
68 pub fn set_if_match(mut self, if_match: impl ToString) -> Self {
72 self.req
73 .insert_header("x-oss-copy-source-if-match", if_match);
74 self
75 }
76 pub fn set_if_none_match(mut self, if_none_match: impl ToString) -> Self {
80 self.req
81 .insert_header("x-oss-copy-source-if-none-match", if_none_match);
82 self
83 }
84 pub fn forbid_overwrite(mut self) -> Self {
86 self.req.insert_header("x-oss-forbid-overwrite", "true");
87 self
88 }
89 pub fn set_tagging(mut self, key: impl ToString, value: impl ToString) -> Self {
91 self.tags.insert(key.to_string(), value.to_string());
92 self
93 }
94 pub fn set_metadata_directive(mut self) -> Self {
96 self.req
97 .insert_header("x-oss-metadata-directive", "REPLACE");
98 self
99 }
100 pub fn set_tagging_directive(mut self) -> Self {
102 self.req.insert_header("x-oss-tagging-directive", "Replace");
103 self
104 }
105
106 pub async fn send(mut self) -> Result<(), Error> {
109 let tags = self
111 .tags
112 .into_iter()
113 .map(|(key, value)| {
114 if value.is_empty() {
115 url_encode(&key.to_string())
116 } else {
117 format!(
118 "{}={}",
119 url_encode(&key.to_string()),
120 url_encode(&value.to_string())
121 )
122 }
123 })
124 .collect::<Vec<_>>()
125 .join("&");
126 if !tags.is_empty() {
127 self.req.insert_header("x-oss-tagging", tags);
128 }
129 let response = self.req.send_to_oss()?.await?;
131 let status_code = response.status();
133 match status_code {
134 code if code.is_success() => Ok(()),
135 _ => Err(normal_error(response).await),
136 }
137 }
138}