xt_oss/oss/api/bucket/
cors.rs

1use crate::oss;
2
3use self::builders::{
4    DeleteBucketCorsBuilder, GetBucketCorsBuilder, OptionsBuilder, PutBucketCorsBuilder,
5};
6
7pub mod builders {
8    use reqwest::header::ORIGIN;
9
10    use crate::{
11        oss::{
12            self,
13            api::{self, insert_custom_header, insert_header, ApiResponseFrom},
14            entities::cors::CORSConfiguration,
15            http,
16        },
17        util::AllowedHeaderItem,
18    };
19
20    pub struct PutBucketCorsBuilder<'a> {
21        client: &'a oss::Client<'a>,
22        config: CORSConfiguration,
23    }
24
25    #[allow(unused)]
26    impl<'a> PutBucketCorsBuilder<'a> {
27        pub fn new(client: &'a oss::Client) -> Self {
28            Self {
29                client,
30                config: CORSConfiguration::default(),
31            }
32        }
33
34        pub fn with_config(mut self, value: CORSConfiguration) -> Self {
35            self.config = value;
36            self
37        }
38
39        pub async fn execute(&self) -> api::ApiResult {
40            let res = format!("/{}/?{}", self.client.bucket(), "cors");
41            let url = format!("{}/?{}", self.client.base_url(), "cors");
42            let content = quick_xml::se::to_string(&self.config).unwrap();
43            let data = oss::Bytes::from(content);
44            let resp = self
45                .client
46                .request
47                .task()
48                .with_url(&url)
49                .with_method(http::Method::PUT)
50                .with_resource(&res)
51                .with_body(data)
52                .execute_timeout(self.client.options.timeout)
53                .await?;
54
55            Ok(ApiResponseFrom(resp).to_empty().await)
56        }
57    }
58
59    pub struct GetBucketCorsBuilder<'a> {
60        client: &'a oss::Client<'a>,
61    }
62
63    impl<'a> GetBucketCorsBuilder<'a> {
64        pub(crate) fn new(client: &'a oss::Client) -> Self {
65            Self { client }
66        }
67
68        pub async fn execute(&self) -> api::ApiResult<CORSConfiguration> {
69            let res = format!("/{}/?{}", self.client.bucket(), "cors");
70            let url = format!("{}/?{}", self.client.base_url(), "cors");
71
72            let resp = self
73                .client
74                .request
75                .task()
76                .with_url(&url)
77                .with_resource(&res)
78                .execute_timeout(self.client.options.timeout)
79                .await?;
80
81            Ok(ApiResponseFrom(resp).to_type().await)
82        }
83    }
84
85    pub struct DeleteBucketCorsBuilder<'a> {
86        client: &'a oss::Client<'a>,
87    }
88
89    impl<'a> DeleteBucketCorsBuilder<'a> {
90        pub(crate) fn new(client: &'a oss::Client) -> Self {
91            Self { client }
92        }
93
94        pub async fn execute(&self) -> api::ApiResult {
95            let url = format!("{}/?{}", self.client.base_url(), "cors");
96            let res = format!("/{}/?{}", self.client.bucket(), "cors");
97
98            let resp = self
99                .client
100                .request
101                .task()
102                .with_url(&url)
103                .with_resource(&res)
104                .with_method(http::Method::DELETE)
105                .execute_timeout(self.client.options.timeout)
106                .await?;
107
108            Ok(ApiResponseFrom(resp).to_empty().await)
109        }
110    }
111
112    pub struct OptionsBuilder<'a> {
113        client: &'a oss::Client<'a>,
114        object: &'a str,
115        origin: &'a str,
116        request_method: http::Method,
117        request_headers: AllowedHeaderItem,
118    }
119
120    impl<'a> OptionsBuilder<'a> {
121        pub(crate) fn new(client: &'a oss::Client, object: &'a str) -> Self {
122            Self {
123                client,
124                object,
125                origin: "",
126                request_method: http::Method::GET,
127                request_headers: AllowedHeaderItem::Any,
128            }
129        }
130
131        pub fn with_origin(mut self, value: &'a str) -> Self {
132            self.origin = value;
133            self
134        }
135
136        pub fn with_request_method(mut self, value: http::Method) -> Self {
137            self.request_method = value;
138            self
139        }
140
141        pub fn with_request_headers(mut self, value: AllowedHeaderItem) -> Self {
142            self.request_headers = value;
143            self
144        }
145
146        pub async fn execute(&self) -> api::ApiResult {
147            let res = format!("/{}/{}", self.client.bucket(), self.object);
148            let url = self.client.object_url(self.object);
149
150            let mut headers = http::header::HeaderMap::new();
151            insert_header(&mut headers, ORIGIN, self.origin);
152            insert_custom_header(
153                &mut headers,
154                "Access-Control-Request-Method",
155                self.request_method.to_string(),
156            );
157            insert_custom_header(
158                &mut headers,
159                "Access-Control-Request-Headers",
160                self.request_headers.to_string(),
161            );
162
163            // dbg!(&headers);
164
165            let resp = self
166                .client
167                .request
168                .task()
169                .with_url(&url)
170                .with_method(http::Method::OPTIONS)
171                .with_headers(headers)
172                .with_resource(&res)
173                .execute_timeout(self.client.options.timeout)
174                .await?;
175
176            Ok(ApiResponseFrom(resp).to_empty().await)
177        }
178    }
179}
180
181/// # 跨域资源共享(CORS)
182#[allow(non_snake_case)]
183impl<'a> oss::Client<'a> {
184    /// 调用PutBucketCors接口为指定的存储空间`Bucket`设置跨域资源共享CORS
185    ///`Cross-Origin Resource Sharing`规则
186    ///
187    /// - [official docs](https://help.aliyun.com/zh/oss/developer-reference/putbucketcors)
188    /// - [xtoss example](https://github.com/isme-sun/xt_oss/blob/main/examples/api_bucket_cors_put.rs)
189    pub fn PutBucketCors(&self) -> PutBucketCorsBuilder {
190        PutBucketCorsBuilder::new(&self)
191    }
192
193    /// GetBucketCors接口用于获取指定存储空间`Bucket`当前的跨域资源共享CORS
194    /// `Cross-Origin Resource Sharing`规则。
195    ///
196    /// - [official docs](https://help.aliyun.com/zh/oss/developer-reference/getbucketcors)
197    /// - [xtoss example](https://github.com/isme-sun/xt_oss/blob/main/examples/api_bucket_cors_get.rs)
198    pub fn GetBucketCors(&self) -> GetBucketCorsBuilder {
199        GetBucketCorsBuilder::new(&self)
200    }
201
202    /// DeleteBucketCors用于关闭指定存储空间`Bucket`对应的跨域资源共享CORS
203    /// `Cross-Origin Resource Sharing`功能并清空所有规则
204    ///
205    /// - [official docs](https://help.aliyun.com/zh/oss/developer-reference/deletebucketcors)
206    /// - [xtoss example](https://github.com/isme-sun/xt_oss/blob/main/examples/api_bucket_cors_del.rs)
207    pub fn DeleteBucketCors(&self) -> DeleteBucketCorsBuilder {
208        DeleteBucketCorsBuilder::new(&self)
209    }
210
211    /// 浏览器在发送跨域请求之前会发送一个preflight请求`Options`给OSS,并带上特定的
212    /// 来源域、HTTP方法和header等信息,以决定是否发送真正的请求。Options请求是由浏览
213    /// 器自动根据是否跨域来决定是否发送。
214    ///
215    /// - [official docs](https://help.aliyun.com/zh/oss/developer-reference/options)
216    /// - [xtoss example](https://github.com/isme-sun/xt_oss/blob/main/examples/api_bucket_cors_options.rs)
217    pub fn Options(&self, object: &'a str) -> OptionsBuilder {
218        OptionsBuilder::new(&self, object)
219    }
220}