opendal/services/yandex_disk/
error.rs1use bytes::Buf;
19use http::Response;
20use quick_xml::de;
21use serde::Deserialize;
22
23use crate::raw::*;
24use crate::*;
25
26#[derive(Default, Debug, Deserialize)]
28#[allow(unused)]
29struct YandexDiskError {
30 message: String,
31 description: String,
32 error: String,
33}
34
35pub(super) fn parse_error(resp: Response<Buffer>) -> Error {
37 let (parts, body) = resp.into_parts();
38 let bs = body.to_bytes();
39
40 let (kind, retryable) = match parts.status.as_u16() {
41 410 | 403 => (ErrorKind::PermissionDenied, false),
42 404 => (ErrorKind::NotFound, false),
43 423 => (ErrorKind::RateLimited, true),
45 499 => (ErrorKind::Unexpected, true),
46 503 | 507 => (ErrorKind::Unexpected, true),
47 _ => (ErrorKind::Unexpected, false),
48 };
49
50 let (message, _yandex_disk_err) = de::from_reader::<_, YandexDiskError>(bs.clone().reader())
51 .map(|yandex_disk_err| (format!("{yandex_disk_err:?}"), Some(yandex_disk_err)))
52 .unwrap_or_else(|_| (String::from_utf8_lossy(&bs).into_owned(), None));
53
54 let mut err = Error::new(kind, message);
55
56 err = with_error_response_context(err, parts);
57
58 if retryable {
59 err = err.set_temporary();
60 }
61
62 err
63}
64
65#[cfg(test)]
66mod test {
67 use http::StatusCode;
68
69 use super::*;
70
71 #[tokio::test]
72 async fn test_parse_error() {
73 let err_res = vec![
74 (
75 r#"{
76 "message": "Не удалось найти запрошенный ресурс.",
77 "description": "Resource not found.",
78 "error": "DiskNotFoundError"
79 }"#,
80 ErrorKind::NotFound,
81 StatusCode::NOT_FOUND,
82 ),
83 (
84 r#"{
85 "message": "Не авторизован.",
86 "description": "Unauthorized",
87 "error": "UnauthorizedError"
88 }"#,
89 ErrorKind::PermissionDenied,
90 StatusCode::FORBIDDEN,
91 ),
92 ];
93
94 for res in err_res {
95 let bs = bytes::Bytes::from(res.0);
96 let body = Buffer::from(bs);
97 let resp = Response::builder().status(res.2).body(body).unwrap();
98
99 let err = parse_error(resp);
100
101 assert_eq!(err.kind(), res.1);
102 }
103 }
104}