• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tu6ge / oss-rs / 5829505807

pending completion
5829505807

push

github

tu6ge
Support std IO (#26)

* feat(decode)!: change init object fn

* todo

* feat(error): OssError add more info

when OssError code is SignatureDoesNotMatch ,show expect
 sign string

* feat(io): support write

* feat: blocking support

* feat: blocking read

* feat: 允许读取的数据于目标数组长度不一致

* feat: 分离 Rc 和内部数据

* feat: support Arc Object Content

* feat: 解决多次写入少量数据导致oss错误的问题

当多次写入少量数据,不符合分片的最小数量时,调用 oss 接口会导致报错

* refactor

* feat: 交互 arc 与 rc 的位置

* docs(io)

* docs(io)

* style

* chore: default close blocking

* fix

* style

* feat(io): change seek

* feat(io): change error type

* style

* feat(bucket)!: change base_bucket_info

* test(io)

* test(doc): remove deprecated

* test(io)

* test(io)

* test(io)

* style(io): clippy

* chore: support more derive

* refactor

* docs

1293 of 1293 new or added lines in 19 files covered. (100.0%)

7298 of 7685 relevant lines covered (94.96%)

9.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.71
/src/tests/object.rs
1
use crate::builder::ArcPointer;
2
#[cfg(feature = "blocking")]
3
use crate::builder::RcPointer;
4
use crate::builder::{BuilderError, ClientWithMiddleware, PointerFamily};
5
use crate::file::Files;
6
use crate::object::ObjectList;
7
use crate::types::object::{CommonPrefixes, ObjectPath};
8
use crate::{builder::Middleware, client::Client};
9
use crate::{BucketName, EndPoint, Query, QueryKey};
10
use async_trait::async_trait;
11
use http::HeaderValue;
12
use reqwest::{Request, Response};
13
use std::error::Error;
14
use std::sync::Arc;
15

16
pub(crate) fn assert_object_list<T: PointerFamily>(
5✔
17
    list: ObjectList<T>,
18
    endpoint: EndPoint,
19
    name: BucketName,
20
    prefix: Option<crate::ObjectDir>,
21
    max_keys: u32,
22
    key_count: u64,
23
    next_continuation_token: String,
24
    common_prefixes: CommonPrefixes,
25
    search_query: Query,
26
) {
27
    assert!(list.bucket().clone().endpoint() == endpoint);
5✔
28
    assert!(list.bucket().clone().name() == name);
5✔
29
    assert!(*list.prefix() == prefix);
5✔
30
    assert!(*list.max_keys() == max_keys);
5✔
31
    assert!(*list.key_count() == key_count);
5✔
32
    assert!(*list.next_continuation_token_str() == next_continuation_token);
5✔
33
    assert!(*list.common_prefixes() == common_prefixes);
5✔
34
    assert!(*list.search_query() == search_query);
5✔
35
}
5✔
36

37
#[cfg(feature = "blocking")]
38
#[test]
39
fn object_list_get_object_list() {
2✔
40
    use crate::client::ClientRc;
41
    use crate::{blocking::builder::Middleware, builder::RcPointer, object::ObjectList};
42
    use reqwest::blocking::{Request, Response};
43
    use std::rc::Rc;
44

45
    #[derive(Debug)]
×
46
    struct MyMiddleware {}
47

48
    impl Middleware for MyMiddleware {
49
        fn handle(&self, request: Request) -> Result<Response, BuilderError> {
1✔
50
            //println!("request {:?}", request);
51
            assert_eq!(request.method(), "GET");
1✔
52
            assert_eq!(
1✔
53
                *request.url(),
1✔
54
                "https://abc.oss-cn-shanghai.aliyuncs.com/?list-type=2&max-keys=5"
1✔
55
                    .parse()
56
                    .unwrap()
57
            );
58
            assert_eq!(
1✔
59
                request.headers().get("canonicalizedresource"),
1✔
60
                Some(&HeaderValue::from_str("/abc/").unwrap())
1✔
61
            );
62
            use http::response::Builder;
63
            let response = Builder::new()
1✔
64
                .status(200)
65
                //.url(url.clone())
66
                .body(
67
                    r#"<?xml version="1.0" encoding="UTF-8"?>
68
                <ListBucketResult>
69
                  <Name>barname</Name>
70
                  <Prefix>foo2</Prefix>
71
                  <MaxKeys>100</MaxKeys>
72
                  <Delimiter></Delimiter>
73
                  <IsTruncated>false</IsTruncated>
74
                  <Contents>
75
                    <Key>9AB932LY.jpeg</Key>
76
                    <LastModified>2022-06-26T09:53:21.000Z</LastModified>
77
                    <ETag>"F75A15996D0857B16FA31A3B16624C26"</ETag>
78
                    <Type>Normal</Type>
79
                    <Size>18027</Size>
80
                    <StorageClass>Standard</StorageClass>
81
                  </Contents>
82
                  <KeyCount>23</KeyCount>
83
                </ListBucketResult>"#,
84
                )
85
                .unwrap();
86
            let response = Response::from(response);
1✔
87
            Ok(response)
1✔
88
        }
1✔
89
    }
90

91
    let client = ClientRc::new(
2✔
92
        "foo1".into(),
1✔
93
        "foo2".into(),
1✔
94
        "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
95
        "foo4".parse().unwrap(),
1✔
96
    )
97
    .middleware(Rc::new(MyMiddleware {}));
1✔
98

99
    let object_list = ObjectList::<RcPointer>::new(
1✔
100
        "abc.oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
101
        Some("foo2/".parse().unwrap()),
1✔
102
        100,
103
        200,
104
        Vec::new(),
1✔
105
        None,
1✔
106
        Rc::new(client),
1✔
107
        vec![("max-keys".into(), 5u8.into())],
1✔
108
    );
109

110
    let res = object_list.get_object_list();
1✔
111

112
    assert!(res.is_ok());
1✔
113
    let list = res.unwrap();
1✔
114
    assert_object_list::<RcPointer>(
1✔
115
        list,
1✔
116
        EndPoint::CN_SHANGHAI,
1✔
117
        "abc".parse().unwrap(),
1✔
118
        Some("foo2/".parse().unwrap()),
1✔
119
        100,
120
        23,
121
        String::default(),
1✔
122
        CommonPrefixes::from_iter([]),
1✔
123
        Query::from_iter([(QueryKey::MAX_KEYS, 5u16)]),
1✔
124
    );
125
}
2✔
126

127
#[tokio::test]
3✔
128
async fn test_get_object_list() {
2✔
129
    #[derive(Debug)]
×
130
    struct MyMiddleware {}
131

132
    #[async_trait]
133
    impl Middleware for MyMiddleware {
134
        async fn handle(&self, request: Request) -> Result<Response, BuilderError> {
3✔
135
            //println!("request {:?}", request);
136
            assert_eq!(request.method(), "GET");
1✔
137
            assert_eq!(
1✔
138
                *request.url(),
1✔
139
                "https://foo4.oss-cn-shanghai.aliyuncs.com/?list-type=2&max-keys=5"
1✔
140
                    .parse()
141
                    .unwrap()
142
            );
143
            assert_eq!(
1✔
144
                request.headers().get("canonicalizedresource"),
1✔
145
                Some(&HeaderValue::from_str("/foo4/").unwrap())
1✔
146
            );
147
            use http::response::Builder;
148
            let response = Builder::new()
1✔
149
                .status(200)
150
                //.url(url.clone())
151
                .body(
152
                    r#"<?xml version="1.0" encoding="UTF-8"?>
153
                <ListBucketResult>
154
                  <Name>barname</Name>
155
                  <Prefix></Prefix>
156
                  <MaxKeys>100</MaxKeys>
157
                  <Delimiter></Delimiter>
158
                  <IsTruncated>false</IsTruncated>
159
                  <Contents>
160
                    <Key>9AB932LY.jpeg</Key>
161
                    <LastModified>2022-06-26T09:53:21.000Z</LastModified>
162
                    <ETag>"F75A15996D0857B16FA31A3B16624C26"</ETag>
163
                    <Type>Normal</Type>
164
                    <Size>18027</Size>
165
                    <StorageClass>Standard</StorageClass>
166
                  </Contents>
167
                  <KeyCount>23</KeyCount>
168
                </ListBucketResult>"#,
169
                )
170
                .unwrap();
171
            let response = Response::from(response);
1✔
172
            Ok(response)
1✔
173
        }
3✔
174
    }
175

176
    let client = Client::<ClientWithMiddleware>::new(
2✔
177
        "foo1".into(),
1✔
178
        "foo2".into(),
1✔
179
        "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
180
        "foo4".parse().unwrap(),
1✔
181
    )
182
    .middleware(Arc::new(MyMiddleware {}));
1✔
183

184
    let res = client
3✔
185
        .get_object_list(vec![("max-keys".parse().unwrap(), "5".parse().unwrap())])
1✔
186
        .await;
1✔
187

188
    assert!(res.is_ok());
1✔
189
    let list = res.unwrap();
1✔
190
    assert_object_list::<ArcPointer>(
2✔
191
        list,
1✔
192
        EndPoint::CN_SHANGHAI,
1✔
193
        "foo4".parse().unwrap(),
1✔
194
        None,
1✔
195
        100,
196
        23,
197
        String::default(),
1✔
198
        CommonPrefixes::from_iter([]),
1✔
199
        Query::from_iter([(QueryKey::MAX_KEYS, 5u16)]),
1✔
200
    );
1✔
201
}
3✔
202

203
#[tokio::test]
3✔
204
async fn test_error_object_list() {
2✔
205
    #[derive(Debug)]
×
206
    struct MyMiddleware {}
207

208
    #[async_trait]
209
    impl Middleware for MyMiddleware {
210
        async fn handle(&self, request: Request) -> Result<Response, BuilderError> {
3✔
211
            //println!("request {:?}", request);
212
            assert_eq!(request.method(), "GET");
1✔
213
            assert_eq!(
1✔
214
                *request.url(),
1✔
215
                "https://foo4.oss-cn-shanghai.aliyuncs.com/?list-type=2&max-keys=5"
1✔
216
                    .parse()
217
                    .unwrap()
218
            );
219
            assert_eq!(
1✔
220
                request.headers().get("canonicalizedresource"),
1✔
221
                Some(&HeaderValue::from_str("/foo4/").unwrap())
1✔
222
            );
223
            use http::response::Builder;
224
            let response = Builder::new()
1✔
225
                .status(200)
226
                //.url(url.clone())
227
                .body(
228
                    r#"<?xml version="1.0" encoding="UTF-8"?>
229
                <ListBucketResult>
230
                  <Name>barname</Name>
231
                  <Prefix></Prefix>
232
                  <MaxKeys>100</MaxKeys>
233
                  <Delimiter></Delimiter>
234
                  <IsTruncated>false</IsTruncated>
235
                  <Contents>
236
                    <Key>9AB932LY.jpeg</Key>
237
                    <LastModified>2022-06-26T09:53:21.000Z</LastModified>
238
                    <ETag>"F75A15996D0857B16FA31A3B16624C26"</ETag>
239
                    <Type>Normal</Type>
240
                    <Size>18027</Size>
241
                    <StorageClass>Standard</StorageClass>
242
                  </Contents>
243
                  <KeyCount>foo</KeyCount>
244
                </ListBucketResult>"#,
245
                )
246
                .unwrap();
247
            let response = Response::from(response);
1✔
248
            Ok(response)
1✔
249
        }
3✔
250
    }
251

252
    let client = Client::<ClientWithMiddleware>::new(
2✔
253
        "foo1".into(),
1✔
254
        "foo2".into(),
1✔
255
        "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
256
        "foo4".parse().unwrap(),
1✔
257
    )
258
    .middleware(Arc::new(MyMiddleware {}));
1✔
259

260
    let res = client
3✔
261
        .get_object_list(vec![("max-keys".parse().unwrap(), "5".parse().unwrap())])
1✔
262
        .await;
1✔
263
    let err = res.unwrap_err();
1✔
264

265
    assert_eq!(format!("{err}"), "decode xml failed");
1✔
266
    assert_eq!(
2✔
267
        format!("{}", err.source().unwrap()),
1✔
268
        "parse key-count failed, gived str: foo"
269
    );
1✔
270
}
3✔
271

272
#[tokio::test]
3✔
273
async fn test_item_error_object_list() {
2✔
274
    #[derive(Debug)]
×
275
    struct MyMiddleware {}
276

277
    #[async_trait]
278
    impl Middleware for MyMiddleware {
279
        async fn handle(&self, request: Request) -> Result<Response, BuilderError> {
3✔
280
            //println!("request {:?}", request);
281
            assert_eq!(request.method(), "GET");
1✔
282
            assert_eq!(
1✔
283
                *request.url(),
1✔
284
                "https://foo4.oss-cn-shanghai.aliyuncs.com/?list-type=2&max-keys=5"
1✔
285
                    .parse()
286
                    .unwrap()
287
            );
288
            assert_eq!(
1✔
289
                request.headers().get("canonicalizedresource"),
1✔
290
                Some(&HeaderValue::from_str("/foo4/").unwrap())
1✔
291
            );
292
            use http::response::Builder;
293
            let response = Builder::new()
1✔
294
                .status(200)
295
                //.url(url.clone())
296
                .body(
297
                    r#"<?xml version="1.0" encoding="UTF-8"?>
298
                <ListBucketResult>
299
                  <Name>barname</Name>
300
                  <Prefix></Prefix>
301
                  <MaxKeys>100</MaxKeys>
302
                  <Delimiter></Delimiter>
303
                  <IsTruncated>false</IsTruncated>
304
                  <Contents>
305
                    <Key>9AB932LY.jpeg</Key>
306
                    <LastModified>2022-06-26T09:53:21.000Z</LastModified>
307
                    <ETag>"F75A15996D0857B16FA31A3B16624C26"</ETag>
308
                    <Type>Normal</Type>
309
                    <Size>aaa</Size>
310
                    <StorageClass>Standard</StorageClass>
311
                  </Contents>
312
                  <KeyCount>23</KeyCount>
313
                </ListBucketResult>"#,
314
                )
315
                .unwrap();
316
            let response = Response::from(response);
1✔
317
            Ok(response)
1✔
318
        }
3✔
319
    }
320

321
    let client = Client::<ClientWithMiddleware>::new(
2✔
322
        "foo1".into(),
1✔
323
        "foo2".into(),
1✔
324
        "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
325
        "foo4".parse().unwrap(),
1✔
326
    )
327
    .middleware(Arc::new(MyMiddleware {}));
1✔
328

329
    let res = client
3✔
330
        .get_object_list(vec![("max-keys".parse().unwrap(), "5".parse().unwrap())])
1✔
331
        .await;
1✔
332
    let err = res.unwrap_err();
1✔
333

334
    assert_eq!(format!("{err}"), "decode xml failed");
1✔
335
    assert_eq!(
2✔
336
        format!("{}", err.source().unwrap()),
1✔
337
        "parse size failed, gived str: aaa"
338
    );
1✔
339
}
3✔
340

341
#[cfg(feature = "blocking")]
342
#[test]
343
fn test_get_blocking_object_list() {
2✔
344
    use crate::blocking::builder::Middleware;
345
    use crate::client::ClientRc;
346
    use reqwest::blocking::{Request, Response};
347
    use std::rc::Rc;
348

349
    #[derive(Debug)]
×
350
    struct MyMiddleware {}
351

352
    impl Middleware for MyMiddleware {
353
        fn handle(&self, request: Request) -> Result<Response, BuilderError> {
1✔
354
            //println!("request {:?}", request);
355
            assert_eq!(request.method(), "GET");
1✔
356
            assert_eq!(
1✔
357
                *request.url(),
1✔
358
                "https://foo4.oss-cn-shanghai.aliyuncs.com/?list-type=2&max-keys=5"
1✔
359
                    .parse()
360
                    .unwrap()
361
            );
362
            assert_eq!(
1✔
363
                request.headers().get("canonicalizedresource"),
1✔
364
                Some(&HeaderValue::from_str("/foo4/").unwrap())
1✔
365
            );
366
            use http::response::Builder;
367
            let response = Builder::new()
1✔
368
                .status(200)
369
                //.url(url.clone())
370
                .body(
371
                    r#"<?xml version="1.0" encoding="UTF-8"?>
372
                <ListBucketResult>
373
                  <Name>barname</Name>
374
                  <Prefix></Prefix>
375
                  <MaxKeys>100</MaxKeys>
376
                  <Delimiter></Delimiter>
377
                  <IsTruncated>false</IsTruncated>
378
                  <Contents>
379
                    <Key>9AB932LY.jpeg</Key>
380
                    <LastModified>2022-06-26T09:53:21.000Z</LastModified>
381
                    <ETag>"F75A15996D0857B16FA31A3B16624C26"</ETag>
382
                    <Type>Normal</Type>
383
                    <Size>18027</Size>
384
                    <StorageClass>Standard</StorageClass>
385
                  </Contents>
386
                  <KeyCount>23</KeyCount>
387
                </ListBucketResult>"#,
388
                )
389
                .unwrap();
390
            let response = Response::from(response);
1✔
391
            Ok(response)
1✔
392
        }
1✔
393
    }
394

395
    let client = ClientRc::new(
2✔
396
        "foo1".into(),
1✔
397
        "foo2".into(),
1✔
398
        "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
399
        "foo4".parse().unwrap(),
1✔
400
    )
401
    .middleware(Rc::new(MyMiddleware {}));
1✔
402

403
    let res = client.get_object_list([("max-keys".into(), "5".into())]);
1✔
404

405
    assert!(res.is_ok());
1✔
406
    let list = res.unwrap();
1✔
407
    assert_object_list::<RcPointer>(
1✔
408
        list,
1✔
409
        EndPoint::CN_SHANGHAI,
1✔
410
        "foo4".parse().unwrap(),
1✔
411
        None,
1✔
412
        100,
413
        23,
414
        String::default(),
1✔
415
        CommonPrefixes::from_iter([]),
1✔
416
        Query::from_iter([(QueryKey::MAX_KEYS, 5u16)]),
1✔
417
    );
418
}
2✔
419

420
#[tokio::test]
3✔
421
async fn test_put_content_base() {
2✔
422
    #[derive(Debug)]
×
423
    struct MyMiddleware {}
424

425
    #[async_trait]
426
    impl Middleware for MyMiddleware {
427
        async fn handle(&self, request: Request) -> Result<Response, BuilderError> {
3✔
428
            //println!("request {:?}", request);
429
            assert_eq!(request.method(), "PUT");
1✔
430
            assert_eq!(
1✔
431
                *request.url(),
1✔
432
                "https://foo4.oss-cn-shanghai.aliyuncs.com/abc.text"
1✔
433
                    .parse()
434
                    .unwrap()
435
            );
436
            assert_eq!(
1✔
437
                request.headers().get("canonicalizedresource"),
1✔
438
                Some(&HeaderValue::from_str("/foo4/abc.text").unwrap())
1✔
439
            );
440
            use http::response::Builder;
441
            let response = Builder::new()
1✔
442
                .status(200)
443
                //.url(url.clone())
444
                .body(r#"content bar"#)
445
                .unwrap();
446
            let response = Response::from(response);
1✔
447
            Ok(response)
1✔
448
        }
3✔
449
    }
450

451
    let client = Client::<ClientWithMiddleware>::new(
2✔
452
        "foo1".into(),
1✔
453
        "foo2".into(),
1✔
454
        "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
455
        "foo4".parse().unwrap(),
1✔
456
    )
457
    .middleware(Arc::new(MyMiddleware {}));
1✔
458

459
    let content = String::from("Hello world");
1✔
460
    let content: Vec<u8> = content.into();
1✔
461

462
    let res = client
3✔
463
        .put_content_base(
464
            content,
1✔
465
            "application/text",
466
            "abc.text".parse::<ObjectPath>().unwrap(),
1✔
467
        )
468
        .await;
1✔
469

470
    //println!("{:?}", res);
471
    assert!(res.is_ok());
2✔
472
}
3✔
473

474
#[cfg(feature = "blocking")]
475
#[test]
476
fn test_blocking_put_content_base() {
2✔
477
    use crate::client::ClientRc;
478
    use crate::{blocking::builder::Middleware, file::blocking::Files};
479
    use reqwest::blocking::{Request, Response};
480
    use std::rc::Rc;
481

482
    #[derive(Debug)]
×
483
    struct MyMiddleware {}
484

485
    impl Middleware for MyMiddleware {
486
        fn handle(&self, request: Request) -> Result<Response, BuilderError> {
1✔
487
            //println!("request {:?}", request);
488
            assert_eq!(request.method(), "PUT");
1✔
489
            assert_eq!(
1✔
490
                *request.url(),
1✔
491
                "https://foo4.oss-cn-shanghai.aliyuncs.com/abc.text"
1✔
492
                    .parse()
493
                    .unwrap()
494
            );
495
            assert_eq!(
1✔
496
                request.headers().get("canonicalizedresource"),
1✔
497
                Some(&HeaderValue::from_str("/foo4/abc.text").unwrap())
1✔
498
            );
499
            use http::response::Builder;
500
            let response = Builder::new()
1✔
501
                .status(200)
502
                //.url(url.clone())
503
                .body(r#"content bar"#)
504
                .unwrap();
505
            let response = Response::from(response);
1✔
506
            Ok(response)
1✔
507
        }
1✔
508
    }
509

510
    let client = ClientRc::new(
2✔
511
        "foo1".into(),
1✔
512
        "foo2".into(),
1✔
513
        "https://oss-cn-shanghai.aliyuncs.com".try_into().unwrap(),
1✔
514
        "foo4".try_into().unwrap(),
1✔
515
    )
516
    .middleware(Rc::new(MyMiddleware {}));
1✔
517

518
    let content = String::from("Hello world");
1✔
519
    let content: Vec<u8> = content.into();
1✔
520

521
    let res = client.put_content_base(content, "application/text", "abc.text");
1✔
522

523
    //println!("{:?}", res);
524
    assert!(res.is_ok());
1✔
525
}
2✔
526

527
mod get_object {
528
    use std::sync::Arc;
529

530
    use http::HeaderValue;
531
    use reqwest::{Request, Response};
532

533
    use crate::builder::{BuilderError, ClientWithMiddleware};
534
    use crate::file::Files;
535
    use crate::types::object::ObjectPath;
536
    use crate::{builder::Middleware, client::Client};
537
    use async_trait::async_trait;
538

539
    #[tokio::test]
3✔
540
    async fn test_all_range() {
2✔
541
        #[derive(Debug)]
×
542
        struct MyMiddleware {}
543

544
        #[async_trait]
545
        impl Middleware for MyMiddleware {
546
            async fn handle(&self, request: Request) -> Result<Response, BuilderError> {
3✔
547
                //println!("request {:?}", request);
548
                assert_eq!(request.method(), "GET");
1✔
549
                assert_eq!(
1✔
550
                    *request.url(),
1✔
551
                    "https://foo4.oss-cn-shanghai.aliyuncs.com/foo.png"
1✔
552
                        .parse()
553
                        .unwrap()
554
                );
555
                assert_eq!(
1✔
556
                    request.headers().get("canonicalizedresource"),
1✔
557
                    Some(&HeaderValue::from_str("/foo4/foo.png").unwrap())
1✔
558
                );
559
                assert_eq!(
1✔
560
                    request.headers().get("Range"),
1✔
561
                    Some(&HeaderValue::from_str("bytes=0-").unwrap())
1✔
562
                );
563
                use http::response::Builder;
564
                let response = Builder::new()
1✔
565
                    .status(200)
566
                    //.url(url.clone())
567
                    .body(r#"content bar"#)
568
                    .unwrap();
569
                let response = Response::from(response);
1✔
570
                Ok(response)
1✔
571
            }
3✔
572
        }
573

574
        let client = Client::<ClientWithMiddleware>::new(
2✔
575
            "foo1".into(),
1✔
576
            "foo2".into(),
1✔
577
            "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
578
            "foo4".parse().unwrap(),
1✔
579
        )
580
        .middleware(Arc::new(MyMiddleware {}));
1✔
581

582
        let res = client
3✔
583
            .get_object("foo.png".parse::<ObjectPath>().unwrap(), ..)
1✔
584
            .await;
1✔
585

586
        //println!("{:?}", res);
587
        assert!(res.is_ok());
1✔
588
        let res = res.unwrap();
1✔
589
        assert_eq!(res, String::from("content bar").into_bytes())
2✔
590
    }
3✔
591

592
    #[tokio::test]
3✔
593
    async fn test_start_range() {
2✔
594
        #[derive(Debug)]
×
595
        struct MyMiddleware {}
596

597
        #[async_trait]
598
        impl Middleware for MyMiddleware {
599
            async fn handle(&self, request: Request) -> Result<Response, BuilderError> {
3✔
600
                //println!("request {:?}", request);
601
                assert_eq!(request.method(), "GET");
1✔
602
                assert_eq!(
1✔
603
                    *request.url(),
1✔
604
                    "https://foo4.oss-cn-shanghai.aliyuncs.com/foo.png"
1✔
605
                        .parse()
606
                        .unwrap()
607
                );
608
                assert_eq!(
1✔
609
                    request.headers().get("canonicalizedresource"),
1✔
610
                    Some(&HeaderValue::from_str("/foo4/foo.png").unwrap())
1✔
611
                );
612
                assert_eq!(
1✔
613
                    request.headers().get("Range"),
1✔
614
                    Some(&HeaderValue::from_str("bytes=1-").unwrap())
1✔
615
                );
616
                use http::response::Builder;
617
                let response = Builder::new()
1✔
618
                    .status(206)
619
                    //.url(url.clone())
620
                    .body(r#"content bar"#)
621
                    .unwrap();
622
                let response = Response::from(response);
1✔
623
                Ok(response)
1✔
624
            }
3✔
625
        }
626

627
        let client = Client::<ClientWithMiddleware>::new(
2✔
628
            "foo1".into(),
1✔
629
            "foo2".into(),
1✔
630
            "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
631
            "foo4".parse().unwrap(),
1✔
632
        )
633
        .middleware(Arc::new(MyMiddleware {}));
1✔
634

635
        let res = client
3✔
636
            .get_object("foo.png".parse::<ObjectPath>().unwrap(), 1..)
1✔
637
            .await;
1✔
638

639
        //println!("{:?}", res);
640
        assert!(res.is_ok());
1✔
641
        let res = res.unwrap();
1✔
642
        assert_eq!(res, String::from("content bar").into_bytes())
2✔
643
    }
3✔
644

645
    #[tokio::test]
3✔
646
    async fn test_end_range() {
2✔
647
        #[derive(Debug)]
×
648
        struct MyMiddleware {}
649

650
        #[async_trait]
651
        impl Middleware for MyMiddleware {
652
            async fn handle(&self, request: Request) -> Result<Response, BuilderError> {
3✔
653
                //println!("request {:?}", request);
654
                assert_eq!(request.method(), "GET");
1✔
655
                assert_eq!(
1✔
656
                    *request.url(),
1✔
657
                    "https://foo4.oss-cn-shanghai.aliyuncs.com/foo.png"
1✔
658
                        .parse()
659
                        .unwrap()
660
                );
661
                assert_eq!(
1✔
662
                    request.headers().get("canonicalizedresource"),
1✔
663
                    Some(&HeaderValue::from_str("/foo4/foo.png").unwrap())
1✔
664
                );
665
                assert_eq!(
1✔
666
                    request.headers().get("Range"),
1✔
667
                    Some(&HeaderValue::from_str("bytes=0-10").unwrap())
1✔
668
                );
669
                use http::response::Builder;
670
                let response = Builder::new()
1✔
671
                    .status(206)
672
                    //.url(url.clone())
673
                    .body(r#"content bar"#)
674
                    .unwrap();
675
                let response = Response::from(response);
1✔
676
                Ok(response)
1✔
677
            }
3✔
678
        }
679

680
        let client = Client::<ClientWithMiddleware>::new(
2✔
681
            "foo1".into(),
1✔
682
            "foo2".into(),
1✔
683
            "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
684
            "foo4".parse().unwrap(),
1✔
685
        )
686
        .middleware(Arc::new(MyMiddleware {}));
1✔
687

688
        let res = client
3✔
689
            .get_object("foo.png".parse::<ObjectPath>().unwrap(), ..10)
1✔
690
            .await;
1✔
691

692
        //println!("{:?}", res);
693
        assert!(res.is_ok());
1✔
694
        let res = res.unwrap();
1✔
695
        assert_eq!(res, String::from("content bar").into_bytes())
2✔
696
    }
3✔
697

698
    #[tokio::test]
3✔
699
    async fn test_start_end_range() {
2✔
700
        #[derive(Debug)]
×
701
        struct MyMiddleware {}
702

703
        #[async_trait]
704
        impl Middleware for MyMiddleware {
705
            async fn handle(&self, request: Request) -> Result<Response, BuilderError> {
3✔
706
                //println!("request {:?}", request);
707
                assert_eq!(request.method(), "GET");
1✔
708
                assert_eq!(
1✔
709
                    *request.url(),
1✔
710
                    "https://foo4.oss-cn-shanghai.aliyuncs.com/foo.png"
1✔
711
                        .parse()
712
                        .unwrap()
713
                );
714
                assert_eq!(
1✔
715
                    request.headers().get("canonicalizedresource"),
1✔
716
                    Some(&HeaderValue::from_str("/foo4/foo.png").unwrap())
1✔
717
                );
718
                assert_eq!(
1✔
719
                    request.headers().get("Range"),
1✔
720
                    Some(&HeaderValue::from_str("bytes=2-10").unwrap())
1✔
721
                );
722
                use http::response::Builder;
723
                let response = Builder::new()
1✔
724
                    .status(206)
725
                    //.url(url.clone())
726
                    .body(r#"content bar"#)
727
                    .unwrap();
728
                let response = Response::from(response);
1✔
729
                Ok(response)
1✔
730
            }
3✔
731
        }
732

733
        let client = Client::<ClientWithMiddleware>::new(
2✔
734
            "foo1".into(),
1✔
735
            "foo2".into(),
1✔
736
            "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
737
            "foo4".parse().unwrap(),
1✔
738
        )
739
        .middleware(Arc::new(MyMiddleware {}));
1✔
740

741
        let res = client
3✔
742
            .get_object("foo.png".parse::<ObjectPath>().unwrap(), 2..10)
1✔
743
            .await;
1✔
744

745
        //println!("{:?}", res);
746
        assert!(res.is_ok());
1✔
747
        let res = res.unwrap();
1✔
748
        assert_eq!(res, String::from("content bar").into_bytes())
2✔
749
    }
3✔
750
}
751

752
#[cfg(feature = "blocking")]
753
mod blocking_get_object {
754
    use std::rc::Rc;
755

756
    use http::HeaderValue;
757
    use reqwest::blocking::{Request, Response};
758

759
    use crate::blocking::builder::ClientWithMiddleware;
760
    use crate::builder::BuilderError;
761
    use crate::file::blocking::Files;
762
    use crate::{blocking::builder::Middleware, client::Client};
763

764
    #[test]
765
    fn test_all_range() {
2✔
766
        #[derive(Debug)]
×
767
        struct MyMiddleware {}
768

769
        impl Middleware for MyMiddleware {
770
            fn handle(&self, request: Request) -> Result<Response, BuilderError> {
1✔
771
                //println!("request {:?}", request);
772
                assert_eq!(request.method(), "GET");
1✔
773
                assert_eq!(
1✔
774
                    *request.url(),
1✔
775
                    "https://foo4.oss-cn-shanghai.aliyuncs.com/foo.png"
1✔
776
                        .parse()
777
                        .unwrap()
778
                );
779
                assert_eq!(
1✔
780
                    request.headers().get("canonicalizedresource"),
1✔
781
                    Some(&HeaderValue::from_str("/foo4/foo.png").unwrap())
1✔
782
                );
783
                assert_eq!(
1✔
784
                    request.headers().get("Range"),
1✔
785
                    Some(&HeaderValue::from_str("bytes=0-").unwrap())
1✔
786
                );
787
                use http::response::Builder;
788
                let response = Builder::new()
1✔
789
                    .status(200)
790
                    //.url(url.clone())
791
                    .body(r#"content bar"#)
792
                    .unwrap();
793
                let response = Response::from(response);
1✔
794
                Ok(response)
1✔
795
            }
1✔
796
        }
797

798
        let client = Client::<ClientWithMiddleware>::new(
2✔
799
            "foo1".into(),
1✔
800
            "foo2".into(),
1✔
801
            "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
802
            "foo4".parse().unwrap(),
1✔
803
        )
804
        .middleware(Rc::new(MyMiddleware {}));
1✔
805

806
        let res = client.get_object("foo.png", ..);
1✔
807

808
        //println!("{:?}", res);
809
        assert!(res.is_ok());
1✔
810
        let res = res.unwrap();
1✔
811
        assert_eq!(res, String::from("content bar").into_bytes())
1✔
812
    }
2✔
813

814
    #[test]
815
    fn test_start_range() {
2✔
816
        #[derive(Debug)]
×
817
        struct MyMiddleware {}
818

819
        impl Middleware for MyMiddleware {
820
            fn handle(&self, request: Request) -> Result<Response, BuilderError> {
1✔
821
                //println!("request {:?}", request);
822
                assert_eq!(request.method(), "GET");
1✔
823
                assert_eq!(
1✔
824
                    *request.url(),
1✔
825
                    "https://foo4.oss-cn-shanghai.aliyuncs.com/foo.png"
1✔
826
                        .parse()
827
                        .unwrap()
828
                );
829
                assert_eq!(
1✔
830
                    request.headers().get("canonicalizedresource"),
1✔
831
                    Some(&HeaderValue::from_str("/foo4/foo.png").unwrap())
1✔
832
                );
833
                assert_eq!(
1✔
834
                    request.headers().get("Range"),
1✔
835
                    Some(&HeaderValue::from_str("bytes=1-").unwrap())
1✔
836
                );
837
                use http::response::Builder;
838
                let response = Builder::new()
1✔
839
                    .status(206)
840
                    //.url(url.clone())
841
                    .body(r#"content bar"#)
842
                    .unwrap();
843
                let response = Response::from(response);
1✔
844
                Ok(response)
1✔
845
            }
1✔
846
        }
847

848
        let client = Client::<ClientWithMiddleware>::new(
2✔
849
            "foo1".into(),
1✔
850
            "foo2".into(),
1✔
851
            "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
852
            "foo4".parse().unwrap(),
1✔
853
        )
854
        .middleware(Rc::new(MyMiddleware {}));
1✔
855

856
        let res = client.get_object("foo.png", 1..);
1✔
857

858
        //println!("{:?}", res);
859
        assert!(res.is_ok());
1✔
860
        let res = res.unwrap();
1✔
861
        assert_eq!(res, String::from("content bar").into_bytes())
1✔
862
    }
2✔
863

864
    #[test]
865
    fn test_end_range() {
2✔
866
        #[derive(Debug)]
×
867
        struct MyMiddleware {}
868

869
        impl Middleware for MyMiddleware {
870
            fn handle(&self, request: Request) -> Result<Response, BuilderError> {
1✔
871
                //println!("request {:?}", request);
872
                assert_eq!(request.method(), "GET");
1✔
873
                assert_eq!(
1✔
874
                    *request.url(),
1✔
875
                    "https://foo4.oss-cn-shanghai.aliyuncs.com/foo.png"
1✔
876
                        .parse()
877
                        .unwrap()
878
                );
879
                assert_eq!(
1✔
880
                    request.headers().get("canonicalizedresource"),
1✔
881
                    Some(&HeaderValue::from_str("/foo4/foo.png").unwrap())
1✔
882
                );
883
                assert_eq!(
1✔
884
                    request.headers().get("Range"),
1✔
885
                    Some(&HeaderValue::from_str("bytes=0-10").unwrap())
1✔
886
                );
887
                use http::response::Builder;
888
                let response = Builder::new()
1✔
889
                    .status(206)
890
                    //.url(url.clone())
891
                    .body(r#"content bar"#)
892
                    .unwrap();
893
                let response = Response::from(response);
1✔
894
                Ok(response)
1✔
895
            }
1✔
896
        }
897

898
        let client = Client::<ClientWithMiddleware>::new(
2✔
899
            "foo1".into(),
1✔
900
            "foo2".into(),
1✔
901
            "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
902
            "foo4".parse().unwrap(),
1✔
903
        )
904
        .middleware(Rc::new(MyMiddleware {}));
1✔
905

906
        let res = client.get_object("foo.png", ..10);
1✔
907

908
        //println!("{:?}", res);
909
        assert!(res.is_ok());
1✔
910
        let res = res.unwrap();
1✔
911
        assert_eq!(res, String::from("content bar").into_bytes())
1✔
912
    }
2✔
913

914
    #[test]
915
    fn test_start_end_range() {
2✔
916
        #[derive(Debug)]
×
917
        struct MyMiddleware {}
918

919
        impl Middleware for MyMiddleware {
920
            fn handle(&self, request: Request) -> Result<Response, BuilderError> {
1✔
921
                //println!("request {:?}", request);
922
                assert_eq!(request.method(), "GET");
1✔
923
                assert_eq!(
1✔
924
                    *request.url(),
1✔
925
                    "https://foo4.oss-cn-shanghai.aliyuncs.com/foo.png"
1✔
926
                        .parse()
927
                        .unwrap()
928
                );
929
                assert_eq!(
1✔
930
                    request.headers().get("canonicalizedresource"),
1✔
931
                    Some(&HeaderValue::from_str("/foo4/foo.png").unwrap())
1✔
932
                );
933
                assert_eq!(
1✔
934
                    request.headers().get("Range"),
1✔
935
                    Some(&HeaderValue::from_str("bytes=2-10").unwrap())
1✔
936
                );
937
                use http::response::Builder;
938
                let response = Builder::new()
1✔
939
                    .status(206)
940
                    //.url(url.clone())
941
                    .body(r#"content bar"#)
942
                    .unwrap();
943
                let response = Response::from(response);
1✔
944
                Ok(response)
1✔
945
            }
1✔
946
        }
947

948
        let client = Client::<ClientWithMiddleware>::new(
2✔
949
            "foo1".into(),
1✔
950
            "foo2".into(),
1✔
951
            "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
952
            "foo4".parse().unwrap(),
1✔
953
        )
954
        .middleware(Rc::new(MyMiddleware {}));
1✔
955

956
        let res = client.get_object("foo.png", 2..10);
1✔
957

958
        //println!("{:?}", res);
959
        assert!(res.is_ok());
1✔
960
        let res = res.unwrap();
1✔
961
        assert_eq!(res, String::from("content bar").into_bytes())
1✔
962
    }
2✔
963
}
964

965
#[tokio::test]
3✔
966
async fn test_delete_object() {
2✔
967
    #[derive(Debug)]
×
968
    struct MyMiddleware {}
969

970
    #[async_trait]
971
    impl Middleware for MyMiddleware {
972
        async fn handle(&self, request: Request) -> Result<Response, BuilderError> {
3✔
973
            //println!("request {:?}", request);
974
            assert_eq!(request.method(), "DELETE");
1✔
975
            assert_eq!(
1✔
976
                *request.url(),
1✔
977
                "https://foo4.oss-cn-shanghai.aliyuncs.com/abc.png"
1✔
978
                    .parse()
979
                    .unwrap()
980
            );
981
            assert_eq!(
1✔
982
                request.headers().get("canonicalizedresource"),
1✔
983
                Some(&HeaderValue::from_str("/foo4/abc.png").unwrap())
1✔
984
            );
985
            use http::response::Builder;
986
            let response = Builder::new()
1✔
987
                .status(200)
988
                //.url(url.clone())
989
                .body(
990
                    r#"<?xml version="1.0" encoding="UTF-8"?>
991
                <ListBucketResult></ListBucketResult>"#,
992
                )
993
                .unwrap();
994
            let response = Response::from(response);
1✔
995
            Ok(response)
1✔
996
        }
3✔
997
    }
998

999
    let client = Client::<ClientWithMiddleware>::new(
2✔
1000
        "foo1".into(),
1✔
1001
        "foo2".into(),
1✔
1002
        "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
1003
        "foo4".parse().unwrap(),
1✔
1004
    )
1005
    .middleware(Arc::new(MyMiddleware {}));
1✔
1006

1007
    let res = client
3✔
1008
        .delete_object("abc.png".parse::<ObjectPath>().unwrap())
1✔
1009
        .await;
1✔
1010
    //println!("{:?}", res);
1011
    assert!(res.is_ok());
2✔
1012
}
3✔
1013

1014
#[cfg(feature = "blocking")]
1015
#[test]
1016
fn test_blocking_delete_object() {
2✔
1017
    use crate::client::ClientRc;
1018
    use crate::{blocking::builder::Middleware, file::BlockingFiles};
1019
    use reqwest::blocking::{Request, Response};
1020
    use std::rc::Rc;
1021

1022
    #[derive(Debug)]
×
1023
    struct MyMiddleware {}
1024

1025
    #[async_trait]
1026
    impl Middleware for MyMiddleware {
1027
        fn handle(&self, request: Request) -> Result<Response, BuilderError> {
1✔
1028
            //println!("request {:?}", request);
1029
            assert_eq!(request.method(), "DELETE");
1✔
1030
            assert_eq!(
1✔
1031
                *request.url(),
1✔
1032
                "https://foo4.oss-cn-shanghai.aliyuncs.com/abc.png"
1✔
1033
                    .parse()
1034
                    .unwrap()
1035
            );
1036
            assert_eq!(
1✔
1037
                request.headers().get("canonicalizedresource"),
1✔
1038
                Some(&HeaderValue::from_str("/foo4/abc.png").unwrap())
1✔
1039
            );
1040
            use http::response::Builder;
1041
            let response = Builder::new()
1✔
1042
                .status(200)
1043
                //.url(url.clone())
1044
                .body(
1045
                    r#"<?xml version="1.0" encoding="UTF-8"?>
1046
                <ListBucketResult></ListBucketResult>"#,
1047
                )
1048
                .unwrap();
1049
            let response = Response::from(response);
1✔
1050
            Ok(response)
1✔
1051
        }
1✔
1052
    }
1053

1054
    let client = ClientRc::new(
2✔
1055
        "foo1".into(),
1✔
1056
        "foo2".into(),
1✔
1057
        "https://oss-cn-shanghai.aliyuncs.com".parse().unwrap(),
1✔
1058
        "foo4".parse().unwrap(),
1✔
1059
    )
1060
    .middleware(Rc::new(MyMiddleware {}));
1✔
1061

1062
    let res = client.delete_object("abc.png");
1✔
1063
    //println!("{:?}", res);
1064
    assert!(res.is_ok());
1✔
1065
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc