opendal/services/cos/
error.rs1use bytes::Buf;
19use http::Response;
20use http::StatusCode;
21use quick_xml::de;
22use serde::Deserialize;
23
24use crate::raw::*;
25use crate::*;
26
27#[derive(Default, Debug, Deserialize)]
29#[serde(default, rename_all = "PascalCase")]
30struct CosError {
31 code: String,
32 message: String,
33 resource: String,
34 request_id: String,
35 host_id: String,
36}
37
38pub(super) fn parse_error(resp: Response<Buffer>) -> Error {
40 let (parts, body) = resp.into_parts();
41 let bs = body.to_bytes();
42
43 let (kind, retryable) = match parts.status {
44 StatusCode::NOT_FOUND => (ErrorKind::NotFound, false),
45 StatusCode::FORBIDDEN => (ErrorKind::PermissionDenied, false),
46 StatusCode::PRECONDITION_FAILED | StatusCode::NOT_MODIFIED | StatusCode::CONFLICT => {
47 (ErrorKind::ConditionNotMatch, false)
48 }
49 StatusCode::INTERNAL_SERVER_ERROR
50 | StatusCode::BAD_GATEWAY
51 | StatusCode::SERVICE_UNAVAILABLE
52 | StatusCode::GATEWAY_TIMEOUT => (ErrorKind::Unexpected, true),
53 v if v.as_u16() == 520 => (ErrorKind::Unexpected, true),
55
56 _ => (ErrorKind::Unexpected, false),
57 };
58
59 let message = match de::from_reader::<_, CosError>(bs.clone().reader()) {
60 Ok(cos_error) => format!("{cos_error:?}"),
61 Err(_) => String::from_utf8_lossy(&bs).into_owned(),
62 };
63
64 let mut err = Error::new(kind, message);
65
66 err = with_error_response_context(err, parts);
67
68 if retryable {
69 err = err.set_temporary();
70 }
71 err
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_parse_error() {
80 let bs = bytes::Bytes::from(
81 r#"
82<?xml version="1.0" encoding="UTF-8"?>
83<Error>
84<Code>NoSuchKey</Code>
85<Message>The resource you requested does not exist</Message>
86<Resource>/example-bucket/object</Resource>
87<RequestId>001B21A61C6C0000013402C4616D5285</RequestId>
88<HostId>RkRCRDJENDc5MzdGQkQ4OUY3MTI4NTQ3NDk2Mjg0M0FBQUFBQUFBYmJiYmJiYmJD</HostId>
89</Error>
90"#,
91 );
92
93 let out: CosError = de::from_reader(bs.reader()).expect("must success");
94 println!("{out:?}");
95
96 assert_eq!(out.code, "NoSuchKey");
97 assert_eq!(out.message, "The resource you requested does not exist");
98 assert_eq!(out.resource, "/example-bucket/object");
99 assert_eq!(out.request_id, "001B21A61C6C0000013402C4616D5285");
100 assert_eq!(
101 out.host_id,
102 "RkRCRDJENDc5MzdGQkQ4OUY3MTI4NTQ3NDk2Mjg0M0FBQUFBQUFBYmJiYmJiYmJD"
103 );
104 }
105}