opendal/services/obs/
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 ObsError {
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 => {
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::<_, ObsError>(bs.clone().reader()) {
60 Ok(obs_error) => format!("{obs_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
72 err
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_parse_error() {
81 let bs = bytes::Bytes::from(
82 r#"
83<?xml version="1.0" encoding="UTF-8"?>
84<Error>
85<Code>NoSuchKey</Code>
86<Message>The resource you requested does not exist</Message>
87<Resource>/example-bucket/object</Resource>
88<RequestId>001B21A61C6C0000013402C4616D5285</RequestId>
89<HostId>RkRCRDJENDc5MzdGQkQ4OUY3MTI4NTQ3NDk2Mjg0M0FBQUFBQUFBYmJiYmJiYmJD</HostId>
90</Error>
91"#,
92 );
93
94 let out: ObsError = de::from_reader(bs.reader()).expect("must success");
95 println!("{out:?}");
96
97 assert_eq!(out.code, "NoSuchKey");
98 assert_eq!(out.message, "The resource you requested does not exist");
99 assert_eq!(out.resource, "/example-bucket/object");
100 assert_eq!(out.request_id, "001B21A61C6C0000013402C4616D5285");
101 assert_eq!(
102 out.host_id,
103 "RkRCRDJENDc5MzdGQkQ4OUY3MTI4NTQ3NDk2Mjg0M0FBQUFBQUFBYmJiYmJiYmJD"
104 );
105 }
106}