aws_sdk_ec2/
ec2_query_errors.rs1use aws_smithy_types::error::metadata::{Builder as ErrorMetadataBuilder, ErrorMetadata};
8use aws_smithy_xml::decode::{try_data, Document, ScopedDecoder, XmlDecodeError};
9
10#[allow(unused)]
11pub fn body_is_error(body: &[u8]) -> Result<bool, XmlDecodeError> {
12 let mut doc = Document::try_from(body)?;
13 let scoped = doc.root_element()?;
14 Ok(scoped.start_el().matches("Response"))
15}
16
17pub fn parse_error_metadata(body: &[u8]) -> Result<ErrorMetadataBuilder, XmlDecodeError> {
18 let mut doc = Document::try_from(body)?;
19 let mut root = doc.root_element()?;
20 let mut err_builder = ErrorMetadata::builder();
21 while let Some(mut tag) = root.next_tag() {
22 if tag.start_el().local() == "Errors" {
23 while let Some(mut error_tag) = tag.next_tag() {
24 if let "Error" = error_tag.start_el().local() {
25 while let Some(mut error_field) = error_tag.next_tag() {
26 match error_field.start_el().local() {
27 "Code" => {
28 err_builder = err_builder.code(try_data(&mut error_field)?);
29 }
30 "Message" => {
31 err_builder = err_builder.message(try_data(&mut error_field)?);
32 }
33 _ => {}
34 }
35 }
36 }
37 }
38 }
39 }
40 Ok(err_builder)
41}
42
43#[allow(unused)]
44pub fn error_scope<'a, 'b>(doc: &'a mut Document<'b>) -> Result<ScopedDecoder<'b, 'a>, XmlDecodeError> {
45 let root = doc
46 .next_start_element()
47 .ok_or_else(|| XmlDecodeError::custom("no root found searching for an Error"))?;
48 if !root.matches("Response") {
49 return Err(XmlDecodeError::custom("expected Response as root"));
50 }
51
52 while let Some(el) = doc.next_start_element() {
53 if el.matches("Errors") && el.depth() == 1 {
54 while let Some(el) = doc.next_start_element() {
55 if el.matches("Error") && el.depth() == 2 {
56 return Ok(doc.scoped_to(el));
57 }
58 }
59 }
60 }
62 Err(XmlDecodeError::custom("no error found inside of response"))
63}
64
65#[cfg(test)]
66mod test {
67 use super::{body_is_error, parse_error_metadata};
68 use crate::ec2_query_errors::error_scope;
69 use aws_smithy_xml::decode::Document;
70
71 #[test]
72 fn parse_wrapped_error() {
73 let xml = br#"
74 <Response>
75 <Errors>
76 <Error>
77 <Code>InvalidGreeting</Code>
78 <Message>Hi</Message>
79 <AnotherSetting>setting</AnotherSetting>
80 <Ignore><This/></Ignore>
81 </Error>
82 </Errors>
83 <RequestId>foo-id</RequestId>
84 </Response>
85 "#;
86 assert!(body_is_error(xml).unwrap());
87 let parsed = parse_error_metadata(xml).expect("valid xml").build();
88 assert_eq!(parsed.message(), Some("Hi"));
89 assert_eq!(parsed.code(), Some("InvalidGreeting"));
90 }
91
92 #[test]
93 fn test_error_scope() {
94 let xml: &[u8] = br#"
95 <Response>
96 <RequestId>foo-id</RequestId>
97 <MorePreamble>foo-id</RequestId>
98 <Sneaky><Error>These are not the errors you are looking for</Error></Sneaky>
99 <Errors>
100 <Sneaky><Error>These are not the errors you are looking for</Error></Sneaky>
101 <Error>
102 <Code>InvalidGreeting</Code>
103 <Message>Hi</Message>
104 <AnotherSetting>setting</AnotherSetting>
105 <Ignore><This/></Ignore>
106 </Error>
107 </Errors>
108 <RequestId>foo-id</RequestId>
109 </Response>
110 "#;
111 let mut doc = Document::try_from(xml).expect("valid");
112 let mut error = error_scope(&mut doc).expect("contains error");
113 let mut keys = vec![];
114 while let Some(tag) = error.next_tag() {
115 keys.push(tag.start_el().local().to_owned());
116 }
118 assert_eq!(keys, vec!["Code", "Message", "AnotherSetting", "Ignore"])
119 }
120}