opendal/services/webhdfs/
error.rs1use http::response::Parts;
19use http::Response;
20use http::StatusCode;
21use serde::Deserialize;
22
23use crate::raw::*;
24use crate::*;
25
26#[derive(Debug, Deserialize)]
27#[serde(rename_all = "PascalCase")]
28struct WebHdfsErrorWrapper {
29 pub remote_exception: WebHdfsError,
30}
31
32#[derive(Debug, Deserialize)]
34#[serde(rename_all = "camelCase")]
35#[allow(dead_code)]
36struct WebHdfsError {
37 exception: String,
38 message: String,
39 java_class_name: String,
40}
41
42pub(super) fn parse_error(resp: Response<Buffer>) -> Error {
43 let (parts, body) = resp.into_parts();
44 let bs = body.to_bytes();
45 let s = String::from_utf8_lossy(&bs);
46 parse_error_msg(parts, &s)
47}
48
49pub(super) fn parse_error_msg(parts: Parts, body: &str) -> Error {
50 let (kind, retryable) = match parts.status {
51 StatusCode::NOT_FOUND => (ErrorKind::NotFound, false),
52 StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN => (ErrorKind::PermissionDenied, false),
53 StatusCode::BAD_REQUEST => (ErrorKind::Unexpected, false),
56 StatusCode::INTERNAL_SERVER_ERROR
57 | StatusCode::BAD_GATEWAY
58 | StatusCode::SERVICE_UNAVAILABLE
59 | StatusCode::GATEWAY_TIMEOUT => (ErrorKind::Unexpected, true),
60 _ => (ErrorKind::Unexpected, false),
61 };
62
63 let message = match serde_json::from_str::<WebHdfsErrorWrapper>(body) {
64 Ok(wh_error) => format!("{:?}", wh_error.remote_exception),
65 Err(_) => body.to_owned(),
66 };
67
68 let mut err = Error::new(kind, message);
69
70 err = with_error_response_context(err, parts);
71
72 if retryable {
73 err = err.set_temporary();
74 }
75
76 err
77}
78
79#[cfg(test)]
80mod tests {
81 use bytes::Buf;
82 use serde_json::from_reader;
83
84 use super::*;
85
86 #[tokio::test]
88 async fn test_parse_error() -> Result<()> {
89 let ill_args = bytes::Bytes::from(
90 r#"
91{
92 "RemoteException":
93 {
94 "exception" : "IllegalArgumentException",
95 "javaClassName": "java.lang.IllegalArgumentException",
96 "message" : "Invalid value for webhdfs parameter \"permission\": ..."
97 }
98}
99 "#,
100 );
101 let body = Buffer::from(ill_args.clone());
102 let resp = Response::builder()
103 .status(StatusCode::BAD_REQUEST)
104 .body(body)
105 .unwrap();
106
107 let err = parse_error(resp);
108 assert_eq!(err.kind(), ErrorKind::Unexpected);
109 assert!(!err.is_temporary());
110
111 let err_msg: WebHdfsError = from_reader::<_, WebHdfsErrorWrapper>(ill_args.reader())
112 .expect("must success")
113 .remote_exception;
114 assert_eq!(err_msg.exception, "IllegalArgumentException");
115 assert_eq!(
116 err_msg.java_class_name,
117 "java.lang.IllegalArgumentException"
118 );
119 assert_eq!(
120 err_msg.message,
121 "Invalid value for webhdfs parameter \"permission\": ..."
122 );
123
124 Ok(())
125 }
126}